opt:语音控制功能-添加vc回调接口

This commit is contained in:
zhaoyf
2026-04-20 10:12:55 +08:00
parent 6950c6c2c2
commit 5d83cceca5
6 changed files with 383 additions and 0 deletions

View File

@@ -0,0 +1,74 @@
package org.nl.wms.system_manage.controller.speech;
import cn.dev33.satoken.annotation.SaIgnore;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.nl.common.exception.BadRequestException;
import org.nl.wms.system_manage.service.speech.VoiceCallbackService;
import org.nl.wms.system_manage.service.speech.dto.InboundTaskRequest;
import org.nl.wms.system_manage.service.speech.dto.MoveTaskRequest;
import org.nl.wms.system_manage.service.speech.dto.OutboundTaskRequest;
import org.nl.wms.system_manage.service.speech.dto.QueryBoundRequest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
*
* vc回调接口
*/
@RestController
@RequestMapping("/api/wms/task")
@Slf4j
public class VoiceCallbackController {
@Autowired
private VoiceCallbackService voiceCallbackService;
/**
* 语音语义解析后异步调用的任务生成接口
*/
@PostMapping("/generate")
@SaIgnore
public ResponseEntity<Object> generate(@RequestBody JSONObject voiceDto) {
System.out.println("接收任务" + JSON.toJSONString(voiceDto));
String commandType = voiceDto.getString("commandType");
JSONObject commandParam = voiceDto.getJSONObject("commandParam");
JSONObject result;
switch (commandType) {
case "taskIssue":
final String taskType = commandParam.getString("taskType");
switch (taskType) {
case "inbound":
InboundTaskRequest inboundRequest = JSON.toJavaObject(commandParam, InboundTaskRequest.class);
result = voiceCallbackService.handleInboundTask(inboundRequest);
break;
case "move":
MoveTaskRequest moveRequest = JSON.toJavaObject(commandParam, MoveTaskRequest.class);
result = voiceCallbackService.handleMoveTask(moveRequest);
break;
case "outbound":
OutboundTaskRequest outboundRequest = JSON.toJavaObject(commandParam, OutboundTaskRequest.class);
result = voiceCallbackService.handleOutboundTask(outboundRequest);
break;
default:
throw new BadRequestException("未知的指令类型: " + commandType);
}
break;
case "InventoryQuery":
QueryBoundRequest queryRequest = JSON.toJavaObject(commandParam, QueryBoundRequest.class);
result = voiceCallbackService.handleQueryTask(queryRequest);
break;
default:
throw new BadRequestException("未知的指令类型: " + commandType);
}
return new ResponseEntity<>(result, HttpStatus.OK);
}
}

View File

@@ -0,0 +1,241 @@
package org.nl.wms.system_manage.service.speech;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.nl.common.exception.BadRequestException;
import org.nl.common.utils.CodeUtil;
import org.nl.common.utils.IdUtil;
import org.nl.common.utils.MapOf;
import org.nl.common.utils.SecurityUtils;
import org.nl.config.SpringContextHolder;
import org.nl.wms.basedata_manage.enums.BaseDataEnum;
import org.nl.wms.basedata_manage.service.IMdMeMaterialbaseService;
import org.nl.wms.basedata_manage.service.IStructattrService;
import org.nl.wms.basedata_manage.service.dao.*;
import org.nl.wms.basedata_manage.service.dto.StrategyMater;
import org.nl.wms.basedata_manage.service.dto.StrategyStructMaterialVO;
import org.nl.wms.basedata_manage.service.dto.StrategyStructParam;
import org.nl.wms.pda_manage.ios_manage.service.PdaIosInService;
import org.nl.wms.pda_manage.ios_manage.service.PdaIosOutService;
import org.nl.wms.sch_manage.enums.StatusEnum;
import org.nl.wms.sch_manage.enums.TaskEnum;
import org.nl.wms.sch_manage.service.ISchBasePointService;
import org.nl.wms.sch_manage.service.dao.SchBasePoint;
import org.nl.wms.sch_manage.service.util.AbstractTask;
import org.nl.wms.sch_manage.service.util.tasks.StInTask;
import org.nl.wms.sch_manage.service.util.tasks.VehicleOutTask;
import org.nl.wms.system_manage.service.speech.dto.InboundTaskRequest;
import org.nl.wms.system_manage.service.speech.dto.MoveTaskRequest;
import org.nl.wms.system_manage.service.speech.dto.OutboundTaskRequest;
import org.nl.wms.system_manage.service.speech.dto.QueryBoundRequest;
import org.nl.wms.warehouse_manage.enums.IOSConstant;
import org.nl.wms.warehouse_manage.enums.IOSEnum;
import org.nl.wms.warehouse_manage.service.IMdPbGroupplateService;
import org.nl.wms.warehouse_manage.service.IStIvtMoveinvService;
import org.nl.wms.warehouse_manage.service.dao.GroupPlate;
import org.nl.wms.warehouse_manage.service.dto.MoveInsertDto;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.ByteArrayResource;
import org.springframework.http.*;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Base64Utils;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.multipart.MultipartFile;
import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import static org.nl.wms.warehouse_manage.enums.IOSEnum.GROUP_PLATE_STATUS;
@Slf4j
@Service
public class VoiceCallbackService {
@Autowired
private IStructattrService iStructattrService;
@Resource
private Map<String, AbstractTask> applyTaskMap;
@Autowired
private IMdMeMaterialbaseService iMdMeMaterialbaseService;
@Autowired
private ISchBasePointService iSchBasePointService;
@Autowired
private IMdPbGroupplateService iMdPbGroupplateService;
@Transactional
public JSONObject handleInboundTask(InboundTaskRequest inboundTaskRequest){
SchBasePoint one = iSchBasePointService.getOne(new LambdaQueryWrapper<SchBasePoint>()
.eq(SchBasePoint::getPoint_code, inboundTaskRequest.getLocationFrom()));
//分配仓位
MdMeMaterialbase meMaterialbase = iMdMeMaterialbaseService.getByCode(inboundTaskRequest.getMaterial());
GroupPlate groupDao = GroupPlate.builder()
.group_id(IdUtil.getStringId())
.material_id(meMaterialbase.getMaterial_id())
.storagevehicle_code(one.getVehicle_code())
.pcsn("111")
.qty_unit_id(meMaterialbase.getQty_unit_id())
.qty_unit_name(meMaterialbase.getQty_unit_name())
.qty(new BigDecimal(inboundTaskRequest.getQty()))
.status(GROUP_PLATE_STATUS.code("组盘"))
.create_id(SecurityUtils.getCurrentUserId())
.create_name(SecurityUtils.getCurrentNickName())
.create_time(DateUtil.now())
.build();
iMdPbGroupplateService.save(groupDao);
StrategyMater mater = new StrategyMater();
mater.setMaterial_code(inboundTaskRequest.getMaterial());
mater.setMaterial_id(meMaterialbase.getMaterial_id());
mater.setQty(new BigDecimal(inboundTaskRequest.getQty()));
mater.setPcsn("111");
List<StrategyMater> materss = new ArrayList<>();
materss.add(mater);
List<Structattr> structattrs = iStructattrService.inBoundSectDiv(
StrategyStructParam.builder()
.ioType(StatusEnum.STRATEGY_TYPE.code("入库"))
.sect_code("BG01")
.stor_code("BGK")
.storagevehicle_code(one.getVehicle_code())
.strategyMaters(materss)
.build());
if (CollectionUtils.isEmpty(structattrs)) {
throw new BadRequestException("无可用货位");
}
Structattr attrDao = structattrs.get(0);
//确定起点
SchBasePoint schBasePoint = iSchBasePointService.getOne(new LambdaQueryWrapper<SchBasePoint>()
.eq(SchBasePoint::getPoint_code, inboundTaskRequest.getLocationFrom()));
if (ObjectUtil.isEmpty(schBasePoint)) {
throw new BadRequestException("未找到载具所在的点位信息,请检查");
}
JSONObject whereJson = new JSONObject();
whereJson.put("point_code1", schBasePoint.getPoint_code());
//确定终点
whereJson.put("point_code2", attrDao.getStruct_code());
whereJson.put("vehicle_code", one.getVehicle_code());
//创建任务
String taskId = applyTaskMap.get("VehicleInTask").create(whereJson);
// 更新起点绑定id
iSchBasePointService.update(
new UpdateWrapper<SchBasePoint>().lambda()
.set(SchBasePoint::getIos_id, null)
.eq(SchBasePoint::getPoint_code, schBasePoint.getPoint_code())
);
// 更新终点锁定状态
JSONObject lock_map = new JSONObject();
lock_map.put("struct_code", attrDao.getStruct_code());
lock_map.put("inv_id", null);
lock_map.put("inv_code", null);
lock_map.put("inv_type", null);
lock_map.put("taskdtl_id", taskId);
lock_map.put("lock_type", IOSEnum.LOCK_TYPE.code("入库锁"));
iStructattrService.updateStatusByCode("0", lock_map);
return null;
};
@Transactional
public JSONObject handleOutboundTask(OutboundTaskRequest outboundTaskRequest){
MdMeMaterialbase meMaterialbase = iMdMeMaterialbaseService.getByCode(outboundTaskRequest.getMaterial());
JSONObject whereJson = new JSONObject();
whereJson.put("material_id", meMaterialbase.getMaterial_id());
whereJson.put("material_code", meMaterialbase.getMaterial_code());
whereJson.put("stor_code", "BGK");
whereJson.put("sect_code", "BG01");
whereJson.put("siteCode", "CKD01");
StrategyMater mater = new StrategyMater();
mater.setQty(BigDecimal.valueOf(outboundTaskRequest.getQty()));
mater.setMaterial_id(meMaterialbase.getMaterial_id());
mater.setMaterial_code(meMaterialbase.getMaterial_code());
List<StrategyMater> maters = new ArrayList<>();
maters.add(mater);
StrategyStructParam strategyStructParam = StrategyStructParam.builder()
.ioType(whereJson.getString(StatusEnum.STRATEGY_TYPE.code("出库")))
.sect_code(whereJson.getString("sect_code"))
.stor_code(whereJson.getString("stor_code"))
.strategyMaters(maters)
.build();
List<StrategyStructMaterialVO> structList = iStructattrService.outBoundSectDiv(strategyStructParam);
if (CollectionUtils.isEmpty(structList)) {
throw new BadRequestException("无可用库存!");
}
structList.forEach(r -> {
//创建任务
JSONObject taskForm = new JSONObject();
taskForm.put("task_type", IOSConstant.VEHICLE_OUT_TASK);
taskForm.put("config_code", IOSConstant.VEHICLE_OUT_TASK);
taskForm.put("TaskCode", CodeUtil.getNewCode("TASK_CODE"));
taskForm.put("PickingLocation", r.getStruct_code());
taskForm.put("PlacedLocation", whereJson.getString("siteCode"));
taskForm.put("vehicle_code", r.getStoragevehicle_code());
applyTaskMap.get(IOSConstant.VEHICLE_OUT_TASK).create(taskForm);
});
//更新组盘记录表
Set<String> vehicleCodeSet = structList.stream()
.map(StrategyStructMaterialVO::getStoragevehicle_code)
.collect(Collectors.toSet());
iMdPbGroupplateService.update(
new GroupPlate(),
new LambdaUpdateWrapper<GroupPlate>()
.set(GroupPlate::getStatus, IOSEnum.GROUP_PLATE_STATUS.code("出库"))
.in(GroupPlate::getStoragevehicle_code, vehicleCodeSet)
);
//锁定仓位
Set<String> structCodeSet = structList.stream()
.map(StrategyStructMaterialVO::getStruct_code)
.collect(Collectors.toSet());
iStructattrService.update(
new LambdaUpdateWrapper<Structattr>()
.set(Structattr::getInv_id, null)
.set(Structattr::getInv_code, null)
.set(Structattr::getInv_type, null)
.set(Structattr::getLock_type, IOSEnum.LOCK_TYPE.code("出库锁"))
.in(Structattr::getStruct_code, structCodeSet)
);
return null;
};
public JSONObject handleMoveTask(MoveTaskRequest moveTaskRequest){
String taskId = applyTaskMap.get("StructMoveTask").create((JSONObject) JSONObject.toJSON(moveTaskRequest));
return null;
};
public JSONObject handleQueryTask(QueryBoundRequest queryBoundRequest){
List<StructattrVechielDto> structCode = iStructattrService.collectVechicle(MapOf.of("struct_code", queryBoundRequest.getLocation(), "search", queryBoundRequest.getMaterial()));
StringBuffer stringBuffer = new StringBuffer();
stringBuffer.append("当前仓库物料有物料");
for (StructattrVechielDto vechielDtos : structCode) {
stringBuffer.append(vechielDtos.getMaterial_name()).append("共计")
.append(vechielDtos.getQty())
.append("");
}
String text = stringBuffer.toString();
try {
// voiceService.speechTts(text);
}catch (Exception ex){
ex.printStackTrace();
}
JSONObject result = new JSONObject();
result.put("has",text);
return result ;
};
}

View File

@@ -0,0 +1,19 @@
package org.nl.wms.system_manage.service.speech.dto;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
@Data
public class InboundTaskRequest {
@JsonProperty("commandType")
private String commandType; // 指令类型taskIssue
@JsonProperty("deviceId")
private String deviceId; // 语音设备ID
@JsonProperty("taskType")
private String taskType; // 任务类型inbound
@JsonProperty("locationFrom")
private String locationFrom; // 取货点编号:从哪个位置入库
@JsonProperty("material")
private String material; // 物料编码
@JsonProperty("qty")
private Integer qty; // 入库物料数量
}

View File

@@ -0,0 +1,17 @@
package org.nl.wms.system_manage.service.speech.dto;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
@Data
public class MoveTaskRequest {
@JsonProperty("commandType")
private String commandType; // 指令类型taskIssue
@JsonProperty("deviceId")
private String deviceId; // 语音设备ID
@JsonProperty("taskType")
private String taskType; // 任务类型move
@JsonProperty("locationFrom")
private String locationFrom; // 取货点编号:从哪个库位取货
@JsonProperty("locationTo")
private String locationTo; // 放货点编号:移到哪个库位
}

View File

@@ -0,0 +1,17 @@
package org.nl.wms.system_manage.service.speech.dto;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
@Data
public class OutboundTaskRequest {
@JsonProperty("commandType")
private String commandType; // 指令类型taskIssue
@JsonProperty("deviceId")
private String deviceId; // 语音设备ID
@JsonProperty("taskType")
private String taskType; // 任务类型outbound
@JsonProperty("material")
private String material; // 物料编码:需要出什么料
@JsonProperty("qty")
private Integer qty; // 出库数量
}

View File

@@ -0,0 +1,15 @@
package org.nl.wms.system_manage.service.speech.dto;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
@Data
public class QueryBoundRequest {
@JsonProperty("commandType")
private String commandType; // 指令类型InventoryQuery
@JsonProperty("deviceId")
private String deviceId; // 语音设备ID
@JsonProperty("location")
private String location; // 货位编号:基于货位查看库存
@JsonProperty("material")
private String material; // 物料编码:基于物料查询库存
}