diff --git a/README.md b/README.md index 0e2897165..1ad273451 100644 --- a/README.md +++ b/README.md @@ -370,3 +370,5 @@ | ![](/.image/admin-uniapp/07.png) | ![](/.image/admin-uniapp/08.png) | ![](/.image/admin-uniapp/09.png) | 目前已经实现登录、我的、工作台、编辑资料、头像修改、密码修改、常见问题、关于我们等基础功能。 + +### CICD 测试6 diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/apilog/core/interceptor/ApiAccessLogInterceptor.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/apilog/core/interceptor/ApiAccessLogInterceptor.java index 18c9b3bb3..448cfd05d 100644 --- a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/apilog/core/interceptor/ApiAccessLogInterceptor.java +++ b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/apilog/core/interceptor/ApiAccessLogInterceptor.java @@ -34,7 +34,9 @@ public class ApiAccessLogInterceptor implements HandlerInterceptor { private static final String ATTRIBUTE_STOP_WATCH = "ApiAccessLogInterceptor.StopWatch"; - private static final List ignoreInterfaceUrls = Arrays.asList("/rpc-api/system/task/robotStatusUpdate","/rpc-api/system/task/updateRobotCommonStatus"); + private static final List ignoreInterfaceUrls = Arrays.asList("/rpc-api/system/task/robotStatusUpdate", + "/rpc-api/system/task/robotReactiveStatus", + "/rpc-api/system/task/updateRobotCommonStatus"); @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) { diff --git a/yudao-module-mqtt/yudao-module-mqtt-api/src/main/java/cn/iocoder/yudao/module/mqtt/api/path/dto/PathToRobotChangeXYArgDTO.java b/yudao-module-mqtt/yudao-module-mqtt-api/src/main/java/cn/iocoder/yudao/module/mqtt/api/path/dto/PathToRobotChangeXYArgDTO.java index 6bb0bf2de..7b67dc6df 100644 --- a/yudao-module-mqtt/yudao-module-mqtt-api/src/main/java/cn/iocoder/yudao/module/mqtt/api/path/dto/PathToRobotChangeXYArgDTO.java +++ b/yudao-module-mqtt/yudao-module-mqtt-api/src/main/java/cn/iocoder/yudao/module/mqtt/api/path/dto/PathToRobotChangeXYArgDTO.java @@ -13,6 +13,7 @@ import java.util.List; @AllArgsConstructor public class PathToRobotChangeXYArgDTO { private List pose2ds; + private PathToRobotChangeXYArgMovePoseDTO pose2d; private PathToRobotChangeXYArgPoseDTO backPose; private PathToRobotChangeXYArgPoseDTO cargoPose; private Double height; diff --git a/yudao-module-mqtt/yudao-module-mqtt-api/src/main/java/cn/iocoder/yudao/module/mqtt/api/path/dto/PathToRobotChangeXYDTO.java b/yudao-module-mqtt/yudao-module-mqtt-api/src/main/java/cn/iocoder/yudao/module/mqtt/api/path/dto/PathToRobotChangeXYDTO.java index 565276c74..f01ef7b3e 100644 --- a/yudao-module-mqtt/yudao-module-mqtt-api/src/main/java/cn/iocoder/yudao/module/mqtt/api/path/dto/PathToRobotChangeXYDTO.java +++ b/yudao-module-mqtt/yudao-module-mqtt-api/src/main/java/cn/iocoder/yudao/module/mqtt/api/path/dto/PathToRobotChangeXYDTO.java @@ -19,6 +19,7 @@ public class PathToRobotChangeXYDTO { //这个实体类不要修改 private String executionType; private String orderId; + private String timeStamp; private String orderType; private String robotNo; private String taskType; diff --git a/yudao-module-mqtt/yudao-module-mqtt-api/src/main/java/cn/iocoder/yudao/module/mqtt/api/path/dto/PathToRobotDTO.java b/yudao-module-mqtt/yudao-module-mqtt-api/src/main/java/cn/iocoder/yudao/module/mqtt/api/path/dto/PathToRobotDTO.java index 17c269b05..4bc36da18 100644 --- a/yudao-module-mqtt/yudao-module-mqtt-api/src/main/java/cn/iocoder/yudao/module/mqtt/api/path/dto/PathToRobotDTO.java +++ b/yudao-module-mqtt/yudao-module-mqtt-api/src/main/java/cn/iocoder/yudao/module/mqtt/api/path/dto/PathToRobotDTO.java @@ -18,6 +18,7 @@ public class PathToRobotDTO { //这个实体类的信息,不能修改 //这个实体类的信息,不能修改 private String orderType; + private String timeStamp; private Integer isCommandEnd; private String robotNo; private String commandType; diff --git a/yudao-module-mqtt/yudao-module-mqtt-api/src/main/java/cn/iocoder/yudao/module/mqtt/api/path/dto/RobotDimensionsDTO.java b/yudao-module-mqtt/yudao-module-mqtt-api/src/main/java/cn/iocoder/yudao/module/mqtt/api/path/dto/RobotDimensionsDTO.java index 5bf1e96cb..adeb48e37 100644 --- a/yudao-module-mqtt/yudao-module-mqtt-api/src/main/java/cn/iocoder/yudao/module/mqtt/api/path/dto/RobotDimensionsDTO.java +++ b/yudao-module-mqtt/yudao-module-mqtt-api/src/main/java/cn/iocoder/yudao/module/mqtt/api/path/dto/RobotDimensionsDTO.java @@ -31,4 +31,8 @@ public class RobotDimensionsDTO { @Schema(description = "转弯半径(单位米)") private Double robotTurningRadius; + + @Schema(description = "偏移量") + private Double robotOffset; + } diff --git a/yudao-module-mqtt/yudao-module-mqtt-biz/src/main/java/cn/iododer/yudao/module/mqtt/api/common/CommonApiImpl.java b/yudao-module-mqtt/yudao-module-mqtt-biz/src/main/java/cn/iododer/yudao/module/mqtt/api/common/CommonApiImpl.java index 4ce25ce8b..32cc4f78c 100644 --- a/yudao-module-mqtt/yudao-module-mqtt-biz/src/main/java/cn/iododer/yudao/module/mqtt/api/common/CommonApiImpl.java +++ b/yudao-module-mqtt/yudao-module-mqtt-biz/src/main/java/cn/iododer/yudao/module/mqtt/api/common/CommonApiImpl.java @@ -23,6 +23,9 @@ public class CommonApiImpl implements CommonApi { try { String str = JSON.toJSONString(obj); mqttUtils.pub(topic, JSON.toJSONString(obj)); + if(topic.equals("AGV_POSE")) { + return; + } if (str.length() > 510) { log.info("MQTT消息发送成功topic :{}, 内容 :{}",topic, str.substring(0, 500)); }else { @@ -37,6 +40,9 @@ public class CommonApiImpl implements CommonApi { public void commonMethodStr(String str, String topic) { try { mqttUtils.pub(topic, str); + if(topic.equals("AGV_POSE")) { + return; + } if (str.length() > 510) { log.info("MQTT消息发送成功topic :{}, 内容 :{}",topic, str.substring(0, 500)); }else { diff --git a/yudao-module-mqtt/yudao-module-mqtt-biz/src/main/java/cn/iododer/yudao/module/mqtt/config/MqttCallBack.java b/yudao-module-mqtt/yudao-module-mqtt-biz/src/main/java/cn/iododer/yudao/module/mqtt/config/MqttCallBack.java index 4fe8dcb99..859691f81 100644 --- a/yudao-module-mqtt/yudao-module-mqtt-biz/src/main/java/cn/iododer/yudao/module/mqtt/config/MqttCallBack.java +++ b/yudao-module-mqtt/yudao-module-mqtt-biz/src/main/java/cn/iododer/yudao/module/mqtt/config/MqttCallBack.java @@ -9,6 +9,8 @@ import org.eclipse.paho.client.mqttv3.MqttMessage; import org.springframework.context.annotation.Configuration; import java.nio.charset.StandardCharsets; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; /** * MQTT回调 @@ -17,6 +19,9 @@ import java.nio.charset.StandardCharsets; @Configuration public class MqttCallBack implements MqttCallback { + + private static final ExecutorService fixedThreadPool = Executors.newFixedThreadPool(10); + /** * 与服务器断开的回调 */ @@ -35,16 +40,19 @@ public class MqttCallBack implements MqttCallback { */ @Override public void messageArrived(String topic, MqttMessage mqttMessage) throws Exception { - String msg = new String(mqttMessage.getPayload(), StandardCharsets.UTF_8); + fixedThreadPool.execute(() -> { + String msg = new String(mqttMessage.getPayload(), StandardCharsets.UTF_8); // log.info("[MQTT]接收当前消息为 :{}", msg); - try { - MqttService mqttService = MqttFactory.getMqttFactory(topic); - mqttService.analysisMessage(msg); - } catch (Exception e) { - log.info("消费失败的消息主题 :{},消息内容 :{}", topic, msg); - log.info("消费消息异常 :{}", e); - } + try { + MqttService mqttService = MqttFactory.getMqttFactory(topic); + mqttService.analysisMessage(msg); + } catch (Exception e) { + log.info("消费失败的消息主题 :{},消息内容 :{}", topic, msg); + log.info("消费消息异常 :{}", e); + } + }); + } /** diff --git a/yudao-module-mqtt/yudao-module-mqtt-biz/src/main/java/cn/iododer/yudao/module/mqtt/service/RobotGenericsStatusServiceImpl.java b/yudao-module-mqtt/yudao-module-mqtt-biz/src/main/java/cn/iododer/yudao/module/mqtt/service/RobotGenericsStatusServiceImpl.java index cacfeb09d..fdb666b8e 100644 --- a/yudao-module-mqtt/yudao-module-mqtt-biz/src/main/java/cn/iododer/yudao/module/mqtt/service/RobotGenericsStatusServiceImpl.java +++ b/yudao-module-mqtt/yudao-module-mqtt-biz/src/main/java/cn/iododer/yudao/module/mqtt/service/RobotGenericsStatusServiceImpl.java @@ -21,7 +21,7 @@ public class RobotGenericsStatusServiceImpl implements MqttService{ @Override public void analysisMessage(String message) { - log.info("处理RobotGenericsStatusServiceImpl的消息 :{}",message); +// log.info("处理RobotGenericsStatusServiceImpl的消息 :{}",message); RobotGenericsDataDTO robotStatusData = JSON.parseObject(message , RobotGenericsDataDTO.class); robotGenericsStatusApi.updateRobotCommonStatus(robotStatusData); } diff --git a/yudao-module-mqtt/yudao-module-mqtt-biz/src/main/java/cn/iododer/yudao/module/mqtt/service/RobotStatusServiceImpl.java b/yudao-module-mqtt/yudao-module-mqtt-biz/src/main/java/cn/iododer/yudao/module/mqtt/service/RobotStatusServiceImpl.java index 2eb8a125b..bcb25c607 100644 --- a/yudao-module-mqtt/yudao-module-mqtt-biz/src/main/java/cn/iododer/yudao/module/mqtt/service/RobotStatusServiceImpl.java +++ b/yudao-module-mqtt/yudao-module-mqtt-biz/src/main/java/cn/iododer/yudao/module/mqtt/service/RobotStatusServiceImpl.java @@ -22,7 +22,7 @@ public class RobotStatusServiceImpl implements MqttService { */ @Override public void analysisMessage(String message) { -// log.info("处理RobotStatusServiceImpl的消息 :{}", message); + log.info("处理RobotStatusServiceImpl的消息 :{}", message); RobotPoseStatusDTO robotStatusData = JSON.parseObject(message, RobotPoseStatusDTO.class); robotStatusApi.robotStatusUpdate(robotStatusData); } diff --git a/yudao-module-mqtt/yudao-module-mqtt-biz/src/main/resources/application-local.yaml b/yudao-module-mqtt/yudao-module-mqtt-biz/src/main/resources/application-local.yaml index 2d0c482cd..0db58fce3 100644 --- a/yudao-module-mqtt/yudao-module-mqtt-biz/src/main/resources/application-local.yaml +++ b/yudao-module-mqtt/yudao-module-mqtt-biz/src/main/resources/application-local.yaml @@ -35,7 +35,8 @@ management: mqtt: # host: tcp://123.57.12.40:1883 host: tcp://127.0.0.1:1883 -# host: tcp://10.10.7.195:1883 +# host: tcp://10.10.7.116:1883 +# host: tcp://10.10.7.114:1883 username: adminuser password: adminuser qos: 2 diff --git a/yudao-module-mqtt/yudao-module-mqtt-biz/src/main/resources/application-test.yaml b/yudao-module-mqtt/yudao-module-mqtt-biz/src/main/resources/application-test.yaml index a267e40df..a6e26b468 100644 --- a/yudao-module-mqtt/yudao-module-mqtt-biz/src/main/resources/application-test.yaml +++ b/yudao-module-mqtt/yudao-module-mqtt-biz/src/main/resources/application-test.yaml @@ -34,7 +34,8 @@ management: # MQTT mqtt: # host: tcp://123.57.12.40:1883 - host: tcp://10.10.100.42:1883 +# host: tcp://10.10.100.42:1883 + host: tcp://127.0.0.1:1883 username: adminuser password: adminuser qos: 0 diff --git a/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/robot/dto/RobotPoseStatusDTO.java b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/robot/dto/RobotPoseStatusDTO.java index b46864b87..699b5c10f 100644 --- a/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/robot/dto/RobotPoseStatusDTO.java +++ b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/robot/dto/RobotPoseStatusDTO.java @@ -18,6 +18,7 @@ public class RobotPoseStatusDTO { * true表示可以做任务,如果是到达了充电点正在充电中应该返回true */ public Boolean taskStatus; + public String timestamp; /** * 机器人位姿 diff --git a/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/robot/websocket/RobotStatusDataPoseDTO.java b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/robot/websocket/RobotStatusDataPoseDTO.java index 9061ecd3d..e60150a56 100644 --- a/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/robot/websocket/RobotStatusDataPoseDTO.java +++ b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/robot/websocket/RobotStatusDataPoseDTO.java @@ -20,4 +20,6 @@ public class RobotStatusDataPoseDTO { public Double forkHeight; //电池剩余容量 废弃 从ROBOT_INFORMATION_SOC 获取电量 // public String batSoc; + + public String timestamp; } diff --git a/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/enums/ErrorCodeConstants.java b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/enums/ErrorCodeConstants.java index bf930a7e3..0f77f8dc2 100644 --- a/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/enums/ErrorCodeConstants.java +++ b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/enums/ErrorCodeConstants.java @@ -202,6 +202,7 @@ public interface ErrorCodeConstants { ErrorCode ROBOT_PORT_NOT_COMPLIANCE = new ErrorCode(1-002-034-016, "车辆端口范围在4096至65535之间"); ErrorCode ROBOT_IP_NOT_COMPLIANCE = new ErrorCode(1-002-034-017, "请检测车辆IP是否符合规范"); ErrorCode ROBOT_IP_OR_PORT_EMPTY = new ErrorCode(1-002-034-020, "车辆IP或者端口为空"); + ErrorCode ROBOT_PART_AREA = new ErrorCode(1-002-034-021, "车辆选择的楼层,不包含目前车辆停靠的楼层"); // ========== 机器人任务主表 1-002-035-000 ========== ErrorCode TASK_NOT_EXISTS = new ErrorCode(1-002-035-001, "车辆任务主表不存在"); diff --git a/yudao-module-system/yudao-module-system-biz/pom.xml b/yudao-module-system/yudao-module-system-biz/pom.xml index f56d0e304..9d56c0fc3 100644 --- a/yudao-module-system/yudao-module-system-biz/pom.xml +++ b/yudao-module-system/yudao-module-system-biz/pom.xml @@ -46,6 +46,12 @@ ${revision} + + cn.iocoder.cloud + yudao-module-remote-api + ${revision} + + cn.iocoder.cloud @@ -179,6 +185,15 @@ 2.8.0 + + org.springframework.integration + spring-integration-mqtt + + + org.eclipse.paho + org.eclipse.paho.client.mqttv3 + + diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/path/PathApiImpl.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/path/PathApiImpl.java index c0cbb4699..322ea977d 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/path/PathApiImpl.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/path/PathApiImpl.java @@ -98,6 +98,7 @@ public class PathApiImpl implements PathApi { */ @Override public void ppDistributionTaskFail(String message) { + log.info("111111路径规划上报失败的消息"); TenantContextHolder.setTenantId(1L); RobotWarnMsgSaveReqVO data = JSON.parseObject(message, RobotWarnMsgSaveReqVO.class); warnMsgService.createWarnMsg(data); @@ -108,7 +109,7 @@ public class PathApiImpl implements PathApi { @Override public void pathPlanningMove(String message) { - log.info("收到路径规划路径的消息 :{}", message); + log.info("111111路径规划发给车机的消息 :{}", message); taskExecutor.execute(() -> { TenantContextHolder.setTenantId(1L); pathPlanningService.sendPosedsToRobot(message); @@ -145,7 +146,7 @@ public class PathApiImpl implements PathApi { @Override public void graphMatchData(String message) { TenantContextHolder.setTenantId(1L); - log.info("匹配路网的消息 :{}",message); + log.info("111111路径规划匹配路网的消息 :{}",message); pathPlanningService.graphMatchData(message); } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/remote/RemoteExceptionTaskApiImpl.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/remote/RemoteExceptionTaskApiImpl.java index 7868edd7e..9658db6df 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/remote/RemoteExceptionTaskApiImpl.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/remote/RemoteExceptionTaskApiImpl.java @@ -5,12 +5,14 @@ import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.module.system.api.remote.dto.*; +import cn.iocoder.yudao.module.system.config.poperties.ZnConfigConstant; import cn.iocoder.yudao.module.system.controller.admin.robot.camera.RobotCameraAddVO; import cn.iocoder.yudao.module.system.service.remote.RemoteControllerInformationService; import cn.iocoder.yudao.module.system.service.robot.RobotTaskDetailService; import cn.iocoder.yudao.module.system.service.robot.camera.RobotCameraService; import cn.iocoder.yudao.module.system.util.aes.AESEncryptionUtil; import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.transaction.annotation.Transactional; import org.springframework.validation.annotation.Validated; @@ -39,8 +41,8 @@ public class RemoteExceptionTaskApiImpl implements RemoteExceptionTaskApi{ @Resource private RobotCameraService cameraService; - @Value("${zn.camera_secret_key}") - private String cameraSecretKey; + @Autowired + private ZnConfigConstant znConfigConstant; /** * 远遥查询异常的车辆 @@ -67,8 +69,8 @@ public class RemoteExceptionTaskApiImpl implements RemoteExceptionTaskApi{ for (RemoteRobotCameraDTO robotCameraDO : list) { try { - robotCameraDO.setCameraAccount(AESEncryptionUtil.decrypt(robotCameraDO.getCameraAccount(),cameraSecretKey)); - robotCameraDO.setCameraPassword(AESEncryptionUtil.decrypt(robotCameraDO.getCameraPassword(),cameraSecretKey)); + robotCameraDO.setCameraAccount(AESEncryptionUtil.decrypt(robotCameraDO.getCameraAccount(),znConfigConstant.getCameraSecretKey())); + robotCameraDO.setCameraPassword(AESEncryptionUtil.decrypt(robotCameraDO.getCameraPassword(),znConfigConstant.getCameraSecretKey())); } catch (Exception e) { throw exception(CAMERA_DECRYPTION_FAILED); } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/robot/RobotGenericsStatusApiImpl.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/robot/RobotGenericsStatusApiImpl.java index 26a3a33e8..0c293c58f 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/robot/RobotGenericsStatusApiImpl.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/robot/RobotGenericsStatusApiImpl.java @@ -30,7 +30,7 @@ public class RobotGenericsStatusApiImpl implements RobotGenericsStatusApi { } public void doUpdateRobotCommonStatus(RobotGenericsDataDTO robotStatusData) { -// log.info("车机每3秒上报其他状态信息 :{}", JSONUtil.toJsonStr(robotStatusData)); +// log.info("111111车机每3秒上报其他状态信息 :{}", JSONUtil.toJsonStr(robotStatusData)); if (ObjectUtil.isEmpty(robotStatusData) || ObjectUtil.isEmpty(robotStatusData.getHwStates()) || ObjectUtil.isEmpty(robotStatusData.getMac())) { log.info("参数不全 :{}", JSON.toJSONString(robotStatusData)); diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/robot/RobotObstaclesStatusApiImpl.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/robot/RobotObstaclesStatusApiImpl.java index 5a9c7b4cc..5edec340f 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/robot/RobotObstaclesStatusApiImpl.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/robot/RobotObstaclesStatusApiImpl.java @@ -41,7 +41,7 @@ public class RobotObstaclesStatusApiImpl implements RobotObstaclesStatusApi{ @Override public void robotObstaclesStatus(String message) { - log.info("障碍物状态上报 :{}" ,message); + log.info("111111障碍物状态上报 :{}" ,message); RobotObstaclesStatusDTO data = JSON.parseObject(message, RobotObstaclesStatusDTO.class); if (!data.getObstacles()) { diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/robot/RobotPathStatusApiImpl.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/robot/RobotPathStatusApiImpl.java index fa89f1487..61fef7840 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/robot/RobotPathStatusApiImpl.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/robot/RobotPathStatusApiImpl.java @@ -41,7 +41,7 @@ public class RobotPathStatusApiImpl implements RobotPathStatusApi { } private void doRobotPathStatus(String message) { - log.info("导航实时行为上报: {}", message); + log.info("111111导航实时行为上报: {}", message); TenantContextHolder.setTenantId(1L); RobotPathStatusDTO data = JSON.parseObject(message, RobotPathStatusDTO.class); String robotNo = robotInformationService.getRobotNoByMac(data.getMac()); diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/robot/RobotStatusApiImpl.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/robot/RobotStatusApiImpl.java index 1108715ef..45cefdaf0 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/robot/RobotStatusApiImpl.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/robot/RobotStatusApiImpl.java @@ -9,6 +9,8 @@ import cn.iocoder.yudao.module.system.api.robot.processor.RequestProcessor; import cn.iocoder.yudao.module.system.api.robot.websocket.RobotInformationVO; import cn.iocoder.yudao.module.system.api.robot.vo.RobotReactiveStatusDTO; import cn.iocoder.yudao.module.system.api.robot.websocket.RobotStatusDataPoseDTO; +import cn.iocoder.yudao.module.system.config.mqtt.util.MqttUtils; +import cn.iocoder.yudao.module.system.config.poperties.ZnConfigConstant; import cn.iocoder.yudao.module.system.config.ratelimiter.SystemRateLimiter; import cn.iocoder.yudao.module.system.constant.CommonConstant; import cn.iocoder.yudao.module.system.constant.area.FloorAreaConstant; @@ -41,16 +43,19 @@ public class RobotStatusApiImpl implements RobotStatusApi { @Autowired private RobotInformationService robotInformationService; - @Value("${zn.robot_position_cache_time:10}") - private Long robotPositionCacheTime; + @Autowired + private ZnConfigConstant znConfigConstant; @Resource private RequestProcessor processor; - private static final ExecutorService executorService = Executors.newFixedThreadPool(5); + private static final ExecutorService executorService = Executors.newFixedThreadPool(50); - @Resource - private CommonApi commonApi; + /*@Resource + private CommonApi commonApi;*/ + + @Autowired + private MqttUtils mqttUtils; /** * 更新机器人点位/异常/能否做任务 @@ -107,13 +112,10 @@ public class RobotStatusApiImpl implements RobotStatusApi { robotStatusDataPoseDTO.setForkHeight(data.getForkHeight()); } - redisUtil.set(pose2dKey, JSON.toJSONString(robotStatusDataPoseDTO), robotPositionCacheTime); + redisUtil.set(pose2dKey, JSON.toJSONString(robotStatusDataPoseDTO), znConfigConstant.getRobotPositionCacheTime()); - //机器人身上是否有货 - String taskStatusKey = RobotTaskChcheConstant.ROBOT_TASK_STATUS + robotStatusDataDTO.getMac(); - String cargoDetectedKey = RobotTaskChcheConstant.ROBOT_CARGO_DETECTED + robotStatusDataDTO.getMac(); - redisUtil.set(taskStatusKey, robotStatusDataDTO.getTaskStatus(), robotPositionCacheTime); - redisUtil.set(cargoDetectedKey, robotStatusDataDTO.getCargoDetected(), robotPositionCacheTime); + robotStatusDataPoseDTO.setTimestamp(robotStatusDataDTO.getTimestamp()); + sendToPP(robotStatusDataPoseDTO); // -- 通过mac 地址获取车辆信息 - (并且加入到缓存中) Map robotInformationVOS = robotInformationService.getAllRobotByRedis(); @@ -123,18 +125,30 @@ public class RobotStatusApiImpl implements RobotStatusApi { } robotInformationVO.setPose2d(robotStatusDataPoseDTO); - Map map = new HashMap<>(); - String value = FloorAreaConstant.FLOOR_AREA_ROBOT + floorZoneDTO.getFloor() + CommonConstant.SYMBOL + floorZoneDTO.getArea(); - map.put(robotStatusDataDTO.getMac(), JSON.toJSONString(robotInformationVO)); - redisUtil.hmset(value, map, 20); + RobotInformationVO finalRobotInformationVO = robotInformationVO; + + String floorArea = floorZoneDTO.getFloor() + CommonConstant.SYMBOL + floorZoneDTO.getArea(); + executorService.execute(() ->{ + //机器人身上是否有货 + String taskStatusKey = RobotTaskChcheConstant.ROBOT_TASK_STATUS + robotStatusDataDTO.getMac(); + String cargoDetectedKey = RobotTaskChcheConstant.ROBOT_CARGO_DETECTED + robotStatusDataDTO.getMac(); + redisUtil.set(taskStatusKey, robotStatusDataDTO.getTaskStatus(), znConfigConstant.getRobotPositionCacheTime()); + redisUtil.set(cargoDetectedKey, robotStatusDataDTO.getCargoDetected(), znConfigConstant.getRobotPositionCacheTime()); + Map map = new HashMap<>(); + String value = FloorAreaConstant.FLOOR_AREA_ROBOT +floorArea; + map.put(robotStatusDataDTO.getMac(), JSON.toJSONString(finalRobotInformationVO)); + redisUtil.hmset(value, map, 5); + }); + + /* executorService.execute(() ->{ + // 合并请求 - 这里接受到的数据都丢给 RequestProcessor - 再整合数据通过WebSocket丢给前端 + processor.handleRequest(floorArea,robotStatusDataDTO.getMac(), JSONUtil.toJsonStr(finalRobotInformationVO)); + });*/ - // 合并请求 - 这里接受到的数据都丢给 RequestProcessor - 再整合数据通过WebSocket丢给前端 - processor.handleRequest(floorZoneDTO.getFloor() + CommonConstant.SYMBOL + floorZoneDTO.getArea(), - robotStatusDataDTO.getMac(), JSONUtil.toJsonStr(robotInformationVO)); - sendToPP(robotStatusDataPoseDTO); } private void sendToPP(RobotStatusDataPoseDTO robotStatusDataPoseDTO) { - commonApi.commonMethod(robotStatusDataPoseDTO, PathPlanningTopicConstant.AGV_POSE); +// commonApi.commonMethod(robotStatusDataPoseDTO, PathPlanningTopicConstant.AGV_POSE); + mqttUtils.pub(PathPlanningTopicConstant.AGV_POSE,JSON.toJSONString(robotStatusDataPoseDTO)); } } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/robot/RobotTaskStatusApiImpl.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/robot/RobotTaskStatusApiImpl.java index a4846ccd9..cde0c4452 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/robot/RobotTaskStatusApiImpl.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/robot/RobotTaskStatusApiImpl.java @@ -13,6 +13,8 @@ import cn.iocoder.yudao.module.system.api.robot.dto.RobotCommandStateDTO; import cn.iocoder.yudao.module.system.api.robot.dto.RobotCompleteTaskDTO; import cn.iocoder.yudao.module.system.api.robot.websocket.RobotSkuInfoDTO; import cn.iocoder.yudao.module.system.api.robot.websocket.WsWareHouseLocationDTO; +import cn.iocoder.yudao.module.system.config.mqtt.util.MqttUtils; +import cn.iocoder.yudao.module.system.config.poperties.ZnConfigConstant; import cn.iocoder.yudao.module.system.constant.CommonConstant; import cn.iocoder.yudao.module.system.constant.area.FloorAreaConstant; import cn.iocoder.yudao.module.system.constant.path.PathPlanningChcheConstant; @@ -99,8 +101,11 @@ public class RobotTaskStatusApiImpl implements RobotTaskStatusApi { @Resource private RobotChargeLogMapper chargeLogMapper; - @Resource - private CommonApi commonApi; + /*@Resource + private CommonApi commonApi;*/ + + @Autowired + private MqttUtils mqttUtils; @Resource public WebSocketSenderApi webSocketSenderApi; @@ -120,15 +125,12 @@ public class RobotTaskStatusApiImpl implements RobotTaskStatusApi { @Resource private DeviceInformationService deviceInformationService; - @Value("${zn.robot_doing_action.doing_action_cache_time:2*24*60*60}") - private Long doingActionCacheTime; - - @Value("${zn.is_simulation:false}") - private Boolean isSimulation; + @Autowired + private ZnConfigConstant znConfigConstant; @Transactional(rollbackFor = Exception.class) public void doRobotDoneTask(RobotCompleteTaskDTO robotCompleteTaskDTO) { - log.info("机器人完成任务上报 :{}", JSON.toJSONString(robotCompleteTaskDTO)); + log.info("111111机器人完成任务上报 :{}", JSON.toJSONString(robotCompleteTaskDTO)); TenantContextHolder.setTenantId(1L); String robotDoingActionKey = RobotTaskChcheConstant.ROBOT_QUERY_DOING_ACTION + robotCompleteTaskDTO.getMac(); @@ -139,8 +141,9 @@ public class RobotTaskStatusApiImpl implements RobotTaskStatusApi { if (!RobotStatusCodeEnum.SUCCESS.getType().equals(robotCompleteTaskDTO.getStatusCode())) { log.info("车机上报异常 :{}", JSON.toJSONString(robotCompleteTaskDTO)); - closeTask(robotCompleteTaskDTO);//todo 取不了和放不了的异常 + //todo 取不了和放不了的异常 redisUtil.del(robotDoingActionKey); + closeTask(robotCompleteTaskDTO); return; } @@ -193,7 +196,7 @@ public class RobotTaskStatusApiImpl implements RobotTaskStatusApi { , null); if (PathTaskTypeEnum.AUTO_CHARGE.getType().equals(robotCompleteTaskDTO.getOrderType()) - || PathTaskTypeEnum.CHARGE.getType().equals(robotCompleteTaskDTO.getOrderType()) ) { + || PathTaskTypeEnum.CHARGE.getType().equals(robotCompleteTaskDTO.getOrderType())) { chargeDoing(robotCompleteTaskDTO); } } @@ -206,6 +209,12 @@ public class RobotTaskStatusApiImpl implements RobotTaskStatusApi { * @param orderId */ public void sendStartDoActionToPP(RobotCommandStateDTO commandStatus, String mac, String orderId) { + if (ObjectUtil.isNotEmpty(commandStatus) + || CommandTypeEnum.WORK_PICK_UP_GOODS_MOVE_TO_CHECK.getType().equals(commandStatus.getCommandType()) + || CommandTypeEnum.WORK_DROP_OFF_GOODS_MOVE_TO_CHECK.getType().equals(commandStatus.getCommandType())) { + log.info("不发作业"); + return; + } if (ObjectUtil.isNotEmpty(commandStatus) && RobotExecutionStateConstant.DOING.equals(commandStatus.getExecutionState()) && !CommandTypeEnum.MOVE_POSES.getType().equals(commandStatus.getCommandType())) { String robotNo = robotInformationService.getRobotNoByMac(mac); @@ -247,10 +256,10 @@ public class RobotTaskStatusApiImpl implements RobotTaskStatusApi { } else if (PathTaskTypeEnum.TAKE_RELEASE.getType().equals(robotCompleteTaskDTO.getOrderType())) { RobotTaskDetailDO robotTaskDetailDO = robotTaskDetailMapper.selectById(robotCompleteTaskDTO.getOrderId()); if (CommandTypeEnum.WORK_PICK_UP_GOODS.getType().equals(robotCompleteTaskDTO.getCommandStatus().getCommandType())) { - log.info("告诉路径规划任务完成 :{}, 状态: {}", robotCompleteTaskDTO.getOrderId(), PathIsReachEnum.END_WORK.getType()); + log.info("告诉路径规划取货任务完成 :{}, 状态: {}", robotCompleteTaskDTO.getOrderId(), PathIsReachEnum.END_WORK.getType()); pathPlanningService.updateBehavior(String.valueOf(robotCompleteTaskDTO.getOrderId()), robotTaskDetailDO.getRobotNo() , "", PathIsReachEnum.END_WORK.getType()); - robotTaskDetailDO.setTaskStage(RobotTaskStageEnum.TAKEING.getType()); + robotTaskDetailDO.setTaskStage(RobotTaskStageEnum.GO_RELEASE.getType()); robotTaskDetailMapper.updateById(robotTaskDetailDO); return; } else if (CommandTypeEnum.WORK_DROP_OFF_GOODS.getType().equals(robotCompleteTaskDTO.getCommandStatus().getCommandType())) { @@ -260,7 +269,7 @@ public class RobotTaskStatusApiImpl implements RobotTaskStatusApi { if (PathTaskTypeEnum.AUTO_CHARGE.getType().equals(robotCompleteTaskDTO.getOrderType()) || PathTaskTypeEnum.CHARGE.getType().equals(robotCompleteTaskDTO.getOrderType())) { - chargeLogMapper.updateChargStatusByTaskId(robotCompleteTaskDTO.getOrderId(),ChargeTaskStatusEnum.DONE.getType()); + chargeLogMapper.updateChargStatusByTaskId(robotCompleteTaskDTO.getOrderId(), ChargeTaskStatusEnum.DONE.getType()); } taskDetailActionLogMapper.updateActionStatus(robotCompleteTaskDTO.getOrderId(), ActionStatusEnum.DONE.getType(), LocalDateTime.now()); @@ -289,7 +298,7 @@ public class RobotTaskStatusApiImpl implements RobotTaskStatusApi { toWareHouseLocation.setLocationLock(LocationLockEnum.YES.getType()); toWareHouseLocation.setLocationUseStatus(LocationUseStatusEnum.YES.getType()); locationMapper.updateById(toWareHouseLocation); - pushWareLocation(toWareHouseLocation,robotCompleteTaskDTO.getMac(),ZeroOneEnum.ONE.getType()); + pushWareLocation(toWareHouseLocation, robotCompleteTaskDTO.getMac(), ZeroOneEnum.ONE.getType()); } /** @@ -345,7 +354,7 @@ public class RobotTaskStatusApiImpl implements RobotTaskStatusApi { wareHouseLocationDO.setLocationLock(LocationLockEnum.YES.getType()); wareHouseLocationDO.setLocationUseStatus(LocationUseStatusEnum.NO.getType()); locationMapper.updateById(wareHouseLocationDO); - pushWareLocation(wareHouseLocationDO,robotCompleteTaskDTO.getMac(),ZeroOneEnum.ZERO.getType()); + pushWareLocation(wareHouseLocationDO, robotCompleteTaskDTO.getMac(), ZeroOneEnum.ZERO.getType()); } public void pushWareLocation(WareHouseLocationDO wareHouseLocationDO, String mac, Integer type) { @@ -378,7 +387,8 @@ public class RobotTaskStatusApiImpl implements RobotTaskStatusApi { .robotNo(robotNo) .id(robotCompleteTaskDTO.getOrderId().toString()) .build(); - commonApi.commonMethod(closePathPlanting, PathPlanningTopicConstant.KILL_TASK); +// commonApi.commonMethod(closePathPlanting, PathPlanningTopicConstant.KILL_TASK); + mqttUtils.pub(PathPlanningTopicConstant.KILL_TASK,JSON.toJSONString(closePathPlanting)); log.info("通知PP把任务取消 :{}", robotCompleteTaskDTO.getOrderId()); } @@ -389,19 +399,28 @@ public class RobotTaskStatusApiImpl implements RobotTaskStatusApi { */ @Transactional(rollbackFor = Exception.class) public void closeTask(RobotCompleteTaskDTO robotCompleteTaskDTO) { + + if (RobotStatusCodeEnum.EXCEEDING_SECONDS.getType().equals(robotCompleteTaskDTO.getStatusCode())) { + doTaskContinue(robotCompleteTaskDTO); + return; + } + PPCloseOrder(robotCompleteTaskDTO); // taskService.closeTaskDetail(robotCompleteTaskDTO.getOrderId().toString(),robotCompleteTaskDTO.getMac()); String robotNo = robotInformationService.getRobotNoByMac(robotCompleteTaskDTO.getMac()); - String msg = ""; + String msg = null; + RobotTaskDetailDO robotTaskDetailDO = robotTaskDetailMapper.selectById(robotCompleteTaskDTO.getOrderId()); if (PathTaskTypeEnum.TAKE_RELEASE.getType().equals(robotCompleteTaskDTO.getOrderType()) || PathTaskTypeEnum.TAKE.getType().equals(robotCompleteTaskDTO.getOrderType())) { - RobotTaskDetailDO robotTaskDetailDO = robotTaskDetailMapper.selectById(robotCompleteTaskDTO.getOrderId()); if (RobotTaskStageEnum.GO_TAKE.getType().equals(robotTaskDetailDO.getTaskStage()) || RobotTaskStageEnum.UN_START.getType().equals(robotTaskDetailDO.getTaskStage())) { robotTaskDetailDO.setTaskStatus(RobotTaskDetailStatusEnum.NEW.getType()); robotTaskDetailDO.setTaskStage(RobotTaskStageEnum.UN_START.getType()); - robotTaskDetailDO.setRobotNo(""); + + if (!znConfigConstant.getIsSimulation()) { +// robotTaskDetailDO.setRobotNo(""); + } robotTaskDetailDO.setOccurError(ZeroOneEnum.ZERO.getType()); robotTaskDetailMapper.updateById(robotTaskDetailDO); String taskNo = taskDetailService.getTaskNoByDetailId(robotCompleteTaskDTO.getOrderId()); @@ -439,8 +458,7 @@ public class RobotTaskStatusApiImpl implements RobotTaskStatusApi { String solve = ""; String taskNo = ""; - if (!PathTaskTypeEnum.AUTO_CHARGE.getType().equals(robotCompleteTaskDTO.getOrderType()) - && ObjectUtil.isEmpty(msg)) { + if (ObjectUtil.isEmpty(msg)) { taskNo = taskDetailService.getTaskNoByDetailId(robotCompleteTaskDTO.getOrderId()); solve = " 并且到任务列表关闭任务 " + taskNo; taskDetailService.setTaskDetailError(robotCompleteTaskDTO.getOrderId()); @@ -462,6 +480,12 @@ public class RobotTaskStatusApiImpl implements RobotTaskStatusApi { warnMsgService.sendWarnMsgToWebsocket(warnMsg.getWarnMsg()); } + private void doTaskContinue(RobotCompleteTaskDTO robotCompleteTaskDTO) { + log.info("恢复任务"); + String robotNo = robotInformationService.getRobotNoByMac(robotCompleteTaskDTO.getMac()); + robotInformationService.doTaskContinue(robotNo, true); + } + /** * 处理充电中 * @@ -478,7 +502,7 @@ public class RobotTaskStatusApiImpl implements RobotTaskStatusApi { setTaskDone(robotCompleteTaskDTO); } - chargeLogMapper.updateChargStatusByTaskId(robotCompleteTaskDTO.getOrderId(),ChargeTaskStatusEnum.CHARGEING.getType()); + chargeLogMapper.updateChargStatusByTaskId(robotCompleteTaskDTO.getOrderId(), ChargeTaskStatusEnum.CHARGEING.getType()); } public RobotTaskDetailDO setTaskDone(RobotCompleteTaskDTO robotCompleteTaskDTO) { @@ -513,7 +537,7 @@ public class RobotTaskStatusApiImpl implements RobotTaskStatusApi { */ private void taskDone(RobotCompleteTaskDTO robotCompleteTaskDTO) { - RobotTaskDetailDO robotTaskDetailDO = setTaskDone(robotCompleteTaskDTO); + RobotTaskDetailDO robotTaskDetailDO = setTaskDone(robotCompleteTaskDTO); RobotInformationDO robotInformationDO = robotInformationMapper.selectOne(new LambdaQueryWrapperX() .eq(RobotInformationDO::getRobotNo, robotTaskDetailDO.getRobotNo())); @@ -528,7 +552,7 @@ public class RobotTaskStatusApiImpl implements RobotTaskStatusApi { pathPlanningService.updateBehavior(String.valueOf(robotCompleteTaskDTO.getOrderId()), robotTaskDetailDO.getRobotNo() , "", PathIsReachEnum.END_WORK.getType()); - if (!isSimulation) { + if (!znConfigConstant.getIsSimulation()) { String plantingKey = PathPlanningChcheConstant.PATH_PLANNING_TASK + robotCompleteTaskDTO.getOrderId(); redisUtil.del(plantingKey); } @@ -558,13 +582,17 @@ public class RobotTaskStatusApiImpl implements RobotTaskStatusApi { robotTaskDetailDO.setTaskStage(RobotTaskStageEnum.GO_TAKE.getType()); } else if (CommandTypeEnum.WORK_PICK_UP_GOODS.getType().equals(commandType)) { logOne.setActionMsg("车辆正在取货"); - robotTaskDetailDO.setTaskStage(RobotTaskStageEnum.TAKEING.getType()); + if (!RobotTaskStageEnum.GO_RELEASE.getType().equals(taskStage)) { + robotTaskDetailDO.setTaskStage(RobotTaskStageEnum.TAKEING.getType()); + } } else if (CommandTypeEnum.WORK_DROP_OFF_GOODS.getType().equals(commandType)) { logOne.setActionMsg("车辆正在放货"); robotTaskDetailDO.setTaskStage(RobotTaskStageEnum.RELEASEING.getType()); } else if (CommandTypeEnum.MOVE_POSES.getType().equals(commandType)) { logOne.setActionMsg("车辆正在前往" + robotTaskDetailDO.getToLocationNo() + "放货"); - robotTaskDetailDO.setTaskStage(RobotTaskStageEnum.GO_RELEASE.getType()); + if (!RobotTaskStageEnum.DONE.getType().equals(taskStage)) { + robotTaskDetailDO.setTaskStage(RobotTaskStageEnum.GO_RELEASE.getType()); + } } } else if (PathTaskTypeEnum.CHARGE.getType().equals(robotCompleteTaskDTO.getOrderType()) @@ -596,7 +624,9 @@ public class RobotTaskStatusApiImpl implements RobotTaskStatusApi { robotTaskDetailDO.setTaskStage(RobotTaskStageEnum.GO_TAKE.getType()); } else if (CommandTypeEnum.WORK_PICK_UP_GOODS.getType().equals(commandType)) { logOne.setActionMsg("车辆正在取货"); - robotTaskDetailDO.setTaskStage(RobotTaskStageEnum.TAKEING.getType()); + if (!RobotTaskStageEnum.DONE.getType().equals(taskStage)) { + robotTaskDetailDO.setTaskStage(RobotTaskStageEnum.TAKEING.getType()); + } } } else if (PathTaskTypeEnum.RELEASE.getType().equals(robotCompleteTaskDTO.getOrderType())) { @@ -605,7 +635,9 @@ public class RobotTaskStatusApiImpl implements RobotTaskStatusApi { robotTaskDetailDO.setTaskStage(RobotTaskStageEnum.GO_RELEASE.getType()); } else if (CommandTypeEnum.WORK_DROP_OFF_GOODS.getType().equals(commandType)) { logOne.setActionMsg("车辆正在放货"); - robotTaskDetailDO.setTaskStage(RobotTaskStageEnum.RELEASEING.getType()); + if (!RobotTaskStageEnum.DONE.getType().equals(taskStage)) { + robotTaskDetailDO.setTaskStage(RobotTaskStageEnum.RELEASEING.getType()); + } } } @@ -631,7 +663,7 @@ public class RobotTaskStatusApiImpl implements RobotTaskStatusApi { logOne.setPositionMapId(mapId); } taskDetailActionLogService.createTaskDetailActionLog(logOne); - redisUtil.set(robotDoingActionKey, logOne.getActionMsg(), doingActionCacheTime); + redisUtil.set(robotDoingActionKey, logOne.getActionMsg(), znConfigConstant.getRobotDoingAction().getDoingActionCacheTime()); robotTaskDetailMapper.updateById(robotTaskDetailDO); } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/robot/RobotUpdatePalletHeightApiImpl.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/robot/RobotUpdatePalletHeightApiImpl.java index 215fd4603..5ebb65709 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/robot/RobotUpdatePalletHeightApiImpl.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/robot/RobotUpdatePalletHeightApiImpl.java @@ -50,7 +50,7 @@ public class RobotUpdatePalletHeightApiImpl implements RobotUpdatePalletHeightAp @Override @Transactional(rollbackFor = Exception.class) public void updatePalletHeight(String message) { - log.info("高度反馈 :{}", message); + log.info("111111高度反馈 :{}", message); TenantContextHolder.setTenantId(1L); RobotUpdatePalletHeightDTO data = JSON.parseObject(message, RobotUpdatePalletHeightDTO.class); if (RobotCommandTypeEnum.WORK_DROP_OFF_GOODS.getType().equals(data.getCommandType())) { diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/robot/RobotWorkStatusApiImpl.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/robot/RobotWorkStatusApiImpl.java index bbabffc09..3a6a07552 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/robot/RobotWorkStatusApiImpl.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/robot/RobotWorkStatusApiImpl.java @@ -4,9 +4,15 @@ import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder; import cn.iocoder.yudao.module.system.api.robot.vo.RobotWorkStatusDTO; import cn.iocoder.yudao.module.system.constant.robot.RobotExecutionStateConstant; import cn.iocoder.yudao.module.system.controller.admin.log.vo.RobotOperationLogSaveReqVO; +import cn.iocoder.yudao.module.system.dal.dataobject.robot.RobotTaskDetailDO; +import cn.iocoder.yudao.module.system.dal.mysql.robot.RobotTaskDetailMapper; import cn.iocoder.yudao.module.system.enums.common.ZeroOneEnum; import cn.iocoder.yudao.module.system.enums.path.PathIsReachEnum; import cn.iocoder.yudao.module.system.enums.robot.CommandTypeEnum; +import cn.iocoder.yudao.module.system.enums.robot.RobotTaskDetailStatusEnum; +import cn.iocoder.yudao.module.system.enums.robot.RobotTaskTypeEnum; +import cn.iocoder.yudao.module.system.enums.robot.task.RobotTaskStageEnum; +import cn.iocoder.yudao.module.system.enums.robot.task.WorkProgressEnum; import cn.iocoder.yudao.module.system.service.log.RobotOperationLogService; import cn.iocoder.yudao.module.system.service.path.PathPlanningService; import cn.iocoder.yudao.module.system.service.robot.RobotInformationService; @@ -32,9 +38,12 @@ public class RobotWorkStatusApiImpl implements RobotWorkStatusApi { @Resource private PathPlanningService pathPlanningService; + @Autowired + private RobotTaskDetailMapper robotTaskDetailMapper; + @Override public void robotWorkStatus(String message) { - log.info("作业实时行为上报: {}", message); + log.info("111111作业实时行为上报: {}", message); TenantContextHolder.setTenantId(1L); RobotWorkStatusDTO data = JSON.parseObject(message, RobotWorkStatusDTO.class); @@ -61,6 +70,59 @@ public class RobotWorkStatusApiImpl implements RobotWorkStatusApi { , data.getCommandType(), PathIsReachEnum.END_WORK.getType()); } + if (CommandTypeEnum.WORK_PICK_UP_GOODS.getType().equals(data.getCommandType()) + && RobotExecutionStateConstant.DONE.equals(Integer.valueOf(data.getExecutionState())) + && WorkProgressEnum.FORK_OFFSET.getType().equals(data.getWorkProgress())) { + setTakeDone(data.getOrderId()); + }else if (CommandTypeEnum.WORK_DROP_OFF_GOODS.getType().equals(data.getCommandType()) + && RobotExecutionStateConstant.DONE.equals(Integer.valueOf(data.getExecutionState())) + && WorkProgressEnum.FORK_OFFSET.getType().equals(data.getWorkProgress())) { + setReleaseDone(data.getOrderId()); + } + } + private void setReleaseDone(String orderId) { + RobotTaskDetailDO data = new RobotTaskDetailDO(); + data.setId(Long.valueOf(orderId)); + data.setTaskStage(RobotTaskStageEnum.DONE.getType()); + data.setTaskStatus(RobotTaskDetailStatusEnum.DONE.getType()); + robotTaskDetailMapper.updateRobotDetailById(data); + } + + private void setTakeDone(String orderId) { + RobotTaskDetailDO robotTaskDetailDO = robotTaskDetailMapper.selectById(orderId); + if (RobotTaskTypeEnum.TAKE_RELEASE.getType().equals(robotTaskDetailDO.getTaskType())) { + RobotTaskDetailDO data = new RobotTaskDetailDO(); + data.setId(robotTaskDetailDO.getId()); + data.setTaskStage(RobotTaskStageEnum.GO_RELEASE.getType()); + robotTaskDetailMapper.updateRobotDetailById(data); + }else if (RobotTaskTypeEnum.TAKE.getType().equals(robotTaskDetailDO.getTaskType())){ + RobotTaskDetailDO data = new RobotTaskDetailDO(); + data.setId(robotTaskDetailDO.getId()); + data.setTaskStage(RobotTaskStageEnum.DONE.getType()); + data.setTaskStatus(RobotTaskDetailStatusEnum.DONE.getType()); + robotTaskDetailMapper.updateRobotDetailById(data); + } + } + + + + + + + + + + + + + + + + + + + + } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/config/aop/SystemRateLimiterAspect.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/config/aop/SystemRateLimiterAspect.java index 9bb11cf7c..8d3e989f4 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/config/aop/SystemRateLimiterAspect.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/config/aop/SystemRateLimiterAspect.java @@ -1,6 +1,7 @@ package cn.iocoder.yudao.module.system.config.aop; import cn.hutool.core.util.ObjectUtil; +import cn.iocoder.yudao.module.system.config.poperties.ZnConfigConstant; import cn.iocoder.yudao.module.system.config.ratelimiter.SystemRateLimiter; import cn.iocoder.yudao.module.system.util.redis.RedisUtil; import lombok.extern.slf4j.Slf4j; @@ -13,6 +14,7 @@ import org.aspectj.lang.annotation.Pointcut; import org.aspectj.lang.reflect.MethodSignature; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; import org.springframework.web.context.request.RequestContextHolder; @@ -36,8 +38,9 @@ public class SystemRateLimiterAspect { @Resource private RedisUtil redisUtil; - @Value("${zn.open_rate_limiter:false}") - private Boolean openRateLimiter; + + @Autowired + private ZnConfigConstant znConfigConstant; @Pointcut("@annotation(cn.iocoder.yudao.module.system.config.ratelimiter.SystemRateLimiter)") public void serviceLimit() { @@ -46,7 +49,7 @@ public class SystemRateLimiterAspect { @Around("serviceLimit()") public Object around(ProceedingJoinPoint joinPoint) throws Throwable { - if (!openRateLimiter) { + if (!znConfigConstant.getOpenRateLimiter()) { return joinPoint.proceed(); } MethodSignature signature = (MethodSignature) joinPoint.getSignature(); diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/config/mqtt/MqttBeforePoint.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/config/mqtt/MqttBeforePoint.java new file mode 100644 index 000000000..189f91a86 --- /dev/null +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/config/mqtt/MqttBeforePoint.java @@ -0,0 +1,30 @@ +package cn.iocoder.yudao.module.system.config.mqtt; + +import lombok.extern.slf4j.Slf4j; +import org.eclipse.paho.client.mqttv3.MqttException; +import org.springframework.boot.ApplicationArguments; +import org.springframework.boot.ApplicationRunner; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Component; + +/** + * 初始化执行 + */ +@Slf4j +@Order(1) +@Component +public class MqttBeforePoint implements ApplicationRunner { + + @Override + public void run(ApplicationArguments args) throws Exception { + // 初始化Mqtt连接 + try { + MqttFactory.getInstance(); + log.info("[MQTT]初始化成功"); + } catch (MqttException e) { + log.info("[MQTT]初始化失败。考虑是否服务端掉线"); + MqttFactory.reconnect(); + } + } + +} \ No newline at end of file diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/config/mqtt/MqttCallBack.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/config/mqtt/MqttCallBack.java new file mode 100644 index 000000000..d0d22a9cf --- /dev/null +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/config/mqtt/MqttCallBack.java @@ -0,0 +1,69 @@ +package cn.iocoder.yudao.module.system.config.mqtt; + +import cn.iocoder.yudao.module.system.service.mqtt.MqttService; +import lombok.extern.slf4j.Slf4j; +import org.eclipse.paho.client.mqttv3.IMqttAsyncClient; +import org.eclipse.paho.client.mqttv3.IMqttDeliveryToken; +import org.eclipse.paho.client.mqttv3.MqttCallback; +import org.eclipse.paho.client.mqttv3.MqttMessage; +import org.springframework.context.annotation.Configuration; + +import java.nio.charset.StandardCharsets; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +/** + * MQTT回调 + */ +@Slf4j +@Configuration +public class MqttCallBack implements MqttCallback { + + + private static final ExecutorService fixedThreadPool = Executors.newFixedThreadPool(10); + + /** + * 与服务器断开的回调 + */ + @Override + public void connectionLost(Throwable throwable) { + log.info("[MQTT]断开了与服务端的连接。考虑是否服务端掉线 or 回调参数解析报错 or 无默认sub"); + // 执行自动重连 + MqttFactory.reconnect(); + } + + /** + * 消息到达的回调 + * + * @param topic 话题 + * @param mqttMessage 消息内容 + */ + @Override + public void messageArrived(String topic, MqttMessage mqttMessage) throws Exception { + fixedThreadPool.execute(() -> { + String msg = new String(mqttMessage.getPayload(), StandardCharsets.UTF_8); +// log.info("[MQTT]接收当前消息为 :{}", msg); + + try { + MqttService mqttService = MqttFactory.getMqttFactory(topic); + mqttService.analysisMessage(msg); + } catch (Exception e) { + log.info("消费失败的消息主题 :{},消息内容 :{}", topic, msg); + log.info("消费消息异常 :{}", e); + } + }); + + } + + /** + * 消息发布成功的回调 + * + * @param token token + */ + @Override + public void deliveryComplete(IMqttDeliveryToken token) { + IMqttAsyncClient client = token.getClient(); +// log.info("[MQTT]{}:消息发布成功!", client.getClientId()); + } + +} \ No newline at end of file diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/config/mqtt/MqttFactory.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/config/mqtt/MqttFactory.java new file mode 100644 index 000000000..9b547a2e3 --- /dev/null +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/config/mqtt/MqttFactory.java @@ -0,0 +1,190 @@ +package cn.iocoder.yudao.module.system.config.mqtt; + +//import cn.iododer.yudao.module.mqtt.customer.MqttMessageListener; +import cn.iocoder.yudao.module.system.config.mqtt.enums.DefineSubTopicEnum; +import cn.iocoder.yudao.module.system.config.mqtt.util.BeanUtils; +import cn.iocoder.yudao.module.system.service.mqtt.MqttService; +import cn.iocoder.yudao.module.system.service.mqtt.PathPlanningDistributionFailServiceImpl; +import cn.iocoder.yudao.module.system.service.mqtt.PathPlanningDistributionTaskServiceImpl; +import cn.iocoder.yudao.module.system.service.mqtt.PathPlanningInitDataServiceImpl; +import cn.iocoder.yudao.module.system.service.mqtt.PathPlanningMoveServiceImpl; +import cn.iocoder.yudao.module.system.service.mqtt.PathRouteDisplayPlanningServiceImpl; +import cn.iocoder.yudao.module.system.service.mqtt.PlanningGraphMatchDataServiceImpl; +import cn.iocoder.yudao.module.system.service.mqtt.PlanningRemoteRobotMovePosePlanningImpl; +import cn.iocoder.yudao.module.system.service.mqtt.PlanningSimulationRobotPoseRequestServiceImpl; +import cn.iocoder.yudao.module.system.service.mqtt.RobotGenericsStatusServiceImpl; +import cn.iocoder.yudao.module.system.service.mqtt.RobotObstaclesStatusServiceImpl; +import cn.iocoder.yudao.module.system.service.mqtt.RobotPathStatusServiceImpl; +import cn.iocoder.yudao.module.system.service.mqtt.RobotReactiveStatusServiceImpl; +import cn.iocoder.yudao.module.system.service.mqtt.RobotStatusServiceImpl; +import cn.iocoder.yudao.module.system.service.mqtt.RobotTaskStatusServiceImpl; +import cn.iocoder.yudao.module.system.service.mqtt.RobotUpdatePalletHeightServiceImpl; +import cn.iocoder.yudao.module.system.service.mqtt.RobotWirelessSignalStatusServiceImpl; +import cn.iocoder.yudao.module.system.service.mqtt.RobotWorkStatusServiceImpl; +import lombok.extern.slf4j.Slf4j; +import org.eclipse.paho.client.mqttv3.MqttClient; +import org.eclipse.paho.client.mqttv3.MqttConnectOptions; +import org.eclipse.paho.client.mqttv3.MqttException; +import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import javax.annotation.PostConstruct; +import java.util.concurrent.TimeUnit; + +/** + * Mqtt 工厂类 + */ +@Slf4j +@Component +public class MqttFactory { + + @Autowired + private MqttProperties config; + + private static MqttFactory factory; + + private static MqttClient client; + + + @PostConstruct + public void init() { + factory = this; + factory.config = this.config; + } + + + /** + * 获取客户端实例 + * 单例模式:存在即返回,不存在则初始化 + * + * @return client + * @throws MqttException 此处刻意抛出异常,否则无法执行断线重连 + */ + public static MqttClient getInstance() throws MqttException { + if (client == null) { + connect(); + } + return client; + } + + + /** + * 清空客户端实例 + * 当 mqtt 断开连接时,需清空 clientId,再执行断线重连 + */ + public static void clear() { + client = null; + } + + + /** + * 断线重连方法 + */ + public static void reconnect() { + int count = 0; + while (true) { + clear(); + ++ count; + + try { + log.info("----------------[MQTT]即将执行自动重连----------------"); + getInstance(); + log.info("----------------[MQTT]自动重连成功----------------"); + break; + } catch (MqttException e) { + log.error("----------------[MQTT]自动重连失败,当前为第 {} 次尝试----------------", count); + try { + TimeUnit.SECONDS.sleep(5); + } catch (InterruptedException ex) { + log.error("----------------[MQTT]自动重连,休眠失败!----------------", e); + } + } + } + } + + /** + * 客户端连接服务端 + * + * @throws MqttException 此处刻意抛出异常,否则无法执行断线重连 + */ + private static void connect() throws MqttException { + // 创建MQTT客户端对象 + client = new MqttClient(factory.config.getHostUrl(), factory.config.getClientId(), new MemoryPersistence()); + // 连接设置 + MqttConnectOptions options = new MqttConnectOptions(); + // 是否清空session,设置false表示服务器会保留客户端的连接记录(订阅主题,qos),客户端重连之后能获取到服务器在客户端断开连接期间推送的消息 + // 设置为true表示每次连接服务器都是以新的身份 + options.setCleanSession(false); + // 设置连接用户名 + options.setUserName(factory.config.getUsername()); + // 设置连接密码 + options.setPassword(factory.config.getPassword().toCharArray()); + // 设置超时时间,单位为秒 + options.setConnectionTimeout(100); + // 设置心跳时间 单位为秒,表示服务器每隔 20 秒的时间向客户端发送心跳判断客户端是否在线 + options.setKeepAliveInterval(20); + // 调整客户端连接参数 + options.setMaxInflight(factory.config.getMaxInflight()); + // 设置遗嘱消息的话题,若客户端和服务器之间的连接意外断开,服务器将发布客户端的遗嘱信息 + options.setWill("willTopic", (factory.config.getClientId() + "MQTT客户端与服务器断开连接").getBytes(), 0, false); + // 设置回调 + client.setCallback(new MqttCallBack()); + client.connect(options); + + // 设置默认订阅主题 + // 消息等级,与主题数组一一对应 + int[] qos = DefineSubTopicEnum.queryAllQos(); + // 主题 + String[] topics = DefineSubTopicEnum.queryAllTopic(); + // 订阅主题 + client.subscribe(topics, qos); + } + + + /** + * 根据topic去实现自己的业务 + * @param topic + * @return + */ + public static MqttService getMqttFactory(String topic){ + DefineSubTopicEnum defineSubTopicEnum = DefineSubTopicEnum.getDefineSubTopicEnumByTopic(topic); + switch (defineSubTopicEnum){ + case ROBOT_STATUS: + return BeanUtils.getBean(RobotStatusServiceImpl.class); + case ROBOT_REACTIVE_STATUS: + return BeanUtils.getBean(RobotReactiveStatusServiceImpl.class); + case ROBOT_GENERICS_STATUS: + return BeanUtils.getBean(RobotGenericsStatusServiceImpl.class); + case ROBOT_PATH_STATUS: + return BeanUtils.getBean(RobotPathStatusServiceImpl.class); + case ROBOT_WORK_STATUS: + return BeanUtils.getBean(RobotWorkStatusServiceImpl.class); + case ROBOT_UPDATE_PALLET_HEIGHT: + return BeanUtils.getBean(RobotUpdatePalletHeightServiceImpl.class); + case ROBOT_OBSTACLES_STATUS: + return BeanUtils.getBean(RobotObstaclesStatusServiceImpl.class); + case ROBOT_WIRELESS_SIGNAL_STATUS: + return BeanUtils.getBean(RobotWirelessSignalStatusServiceImpl.class); + case PLANNING_INIT_DATA: + return BeanUtils.getBean(PathPlanningInitDataServiceImpl.class); + case PLANNING_DISTRIBUTION_TASK: + return BeanUtils.getBean(PathPlanningDistributionTaskServiceImpl.class); + case PLANNING_DISTRIBUTION_FAIL: + return BeanUtils.getBean(PathPlanningDistributionFailServiceImpl.class); + case PLANNING_SIMULATION_ROBOT_POSE_REQUEST: + return BeanUtils.getBean(PlanningSimulationRobotPoseRequestServiceImpl.class); + case PLANNING_MOVE: + return BeanUtils.getBean(PathPlanningMoveServiceImpl.class); + case PLANNING_ROUTE_DISPLAY: + return BeanUtils.getBean(PathRouteDisplayPlanningServiceImpl.class); + case PLANNING_GRAPH_MATCH_DATA: + return BeanUtils.getBean(PlanningGraphMatchDataServiceImpl.class); + case PLANNING_REMOTE_ROBOT_MOVE_POSE_PLANNING: + return BeanUtils.getBean(PlanningRemoteRobotMovePosePlanningImpl.class); + default : + return BeanUtils.getBean(RobotTaskStatusServiceImpl.class); + } + } + +} \ No newline at end of file diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/config/mqtt/MqttProperties.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/config/mqtt/MqttProperties.java new file mode 100644 index 000000000..21868e984 --- /dev/null +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/config/mqtt/MqttProperties.java @@ -0,0 +1,43 @@ +package cn.iocoder.yudao.module.system.config.mqtt; + +import cn.hutool.core.util.IdUtil; +import lombok.Getter; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Configuration; + +/** + * Mqtt Config + * * 备注:以下刻意将 defaultClientId、clientId 区分使用。 + * * 防止断线重连的时候,clientId 被重复拼接时间戳 + */ +@Getter +@Configuration +public class MqttProperties { + + @Value("${mqtt.host}") + private String hostUrl; + + @Value("${mqtt.username}") + private String username; + + @Value("${mqtt.password}") + private String password; + + @Value("${mqtt.clientId}") + private String clientId; + + @Value("${mqtt.qos}") + private int qos; + + @Value("${mqtt.maxInflight}") + private int maxInflight; + + private String clientUUId; + + public String getClientId() { + if (clientUUId == null) { + clientUUId = clientId + IdUtil.fastSimpleUUID(); + } + return clientUUId; + } +} diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/config/mqtt/enums/DefineSubTopicEnum.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/config/mqtt/enums/DefineSubTopicEnum.java new file mode 100644 index 000000000..c75ab8e86 --- /dev/null +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/config/mqtt/enums/DefineSubTopicEnum.java @@ -0,0 +1,84 @@ +package cn.iocoder.yudao.module.system.config.mqtt.enums; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.util.ArrayList; +import java.util.List; + +/** + * 默认订阅的话题 -- 枚举类 + */ +@Getter +@AllArgsConstructor +public enum DefineSubTopicEnum { + + //qos 0-至多1次、1-至少1次、2-正好一次 + ROBOT_STATUS("ROBOT_STATUS", 2,"点位"), + ROBOT_TASK_STATUS("ROBOT_TASK_STATUS", 2,"机器人任务完成上报"), + ROBOT_REACTIVE_STATUS("ROBOT_REACTIVE_STATUS", 2,"机器人响应式状态上报"), + ROBOT_GENERICS_STATUS("ROBOT_GENERICS_STATUS", 2,"机器人异常"), + ROBOT_PATH_STATUS("ROBOT_PATH_STATUS", 2,"导航实时行为上报"), + ROBOT_WORK_STATUS("ROBOT_WORK_STATUS", 2,"作业实时行为上报"), + ROBOT_UPDATE_PALLET_HEIGHT("UPDATE_PALLET_HEIGHT", 2,"放货后货物高度反馈和取货后货物高度反馈"), + ROBOT_OBSTACLES_STATUS("ROBOT_OBSTACLES_STATUS", 2,"障碍物状态上报"), + ROBOT_WIRELESS_SIGNAL_STATUS("ROBOT_WIRELESS_SIGNAL_STATUS", 2,"信号强度上报"), + PLANNING_INIT_DATA("SYNCHRONOUS_ALL_MAP_REQUEST", 2,"路径规划需要初始数据上报"), + PLANNING_DISTRIBUTION_TASK("TASK_ASSIGNMENT_FEEDBACK", 2,"路径规划任务分配上报"), + PLANNING_DISTRIBUTION_FAIL("TASK_ASSIGNMENT_FAIL", 2,"路径规划失败上报"), + PLANNING_SIMULATION_ROBOT_POSE_REQUEST("SIMULATION_ROBOT_POSE_REQUEST", 2,"仿真初始化点位信息"), + PLANNING_MOVE("UPDATE_ROUTE_DISPLAY_PLANNING", 2,"车辆即将走的点位"), + PLANNING_ROUTE_DISPLAY("ROBOT_MOVE_POSE_PLANNING", 2,"路径规划上报实时路径"), + PLANNING_GRAPH_MATCH_DATA("GRAPH_MATCH_DATA", 2,"路网匹配实时数据"), + PLANNING_REMOTE_ROBOT_MOVE_POSE_PLANNING("REMOTE_ROBOT_MOVE_POSE_PLANNING", 2,"远遥车辆行走导航"); + + + private final String topic; + + private final int qos; + + private final String msg; + + /** + * 获取所有话题名 + * + * @return topicArr + */ + public static String[] queryAllTopic() { + List topicList = new ArrayList<>(); + for (DefineSubTopicEnum item : DefineSubTopicEnum.values()) { + topicList.add(item.getTopic()); + } + String[] topicArr = new String[topicList.size()]; + topicArr = topicList.toArray(topicArr); + return topicArr; + } + + + /** + * 获取所有qos + * + * @return qosArr + */ + public static int[] queryAllQos() { + List qosList = new ArrayList<>(); + for (DefineSubTopicEnum item : DefineSubTopicEnum.values()) { + qosList.add(item.getQos()); + } + + int[] qosArr = new int[qosList.size()]; + qosArr = qosList.stream().mapToInt(Integer::intValue).toArray(); + + return qosArr; + } + + public static DefineSubTopicEnum getDefineSubTopicEnumByTopic(String topic) { + for (DefineSubTopicEnum item : DefineSubTopicEnum.values()) { + if (item.getTopic().equals(topic)) { + return item; + } + } + return null; + } + +} \ No newline at end of file diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/config/mqtt/util/BeanUtils.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/config/mqtt/util/BeanUtils.java new file mode 100644 index 000000000..0be825b04 --- /dev/null +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/config/mqtt/util/BeanUtils.java @@ -0,0 +1,31 @@ +package cn.iocoder.yudao.module.system.config.mqtt.util; + +import org.springframework.beans.BeansException; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; +import org.springframework.stereotype.Component; + +@Component +public class BeanUtils implements ApplicationContextAware { + protected static ApplicationContext applicationContext ; + + @Override + public void setApplicationContext(ApplicationContext arg0) throws BeansException { + if (applicationContext == null) { + applicationContext = arg0; + } + + } + public static Object getBean(String name) { + //name表示其他要注入的注解name名 + return applicationContext.getBean(name); + } + + /** + * 拿到ApplicationContext对象实例后就可以手动获取Bean的注入实例对象 + */ + public static T getBean(Class clazz) { + return applicationContext.getBean(clazz); + } +} + diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/config/mqtt/util/MqttUtils.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/config/mqtt/util/MqttUtils.java new file mode 100644 index 000000000..446ddd093 --- /dev/null +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/config/mqtt/util/MqttUtils.java @@ -0,0 +1,93 @@ +package cn.iocoder.yudao.module.system.config.mqtt.util; + +import cn.hutool.core.util.ObjectUtil; +import cn.iocoder.yudao.module.system.config.mqtt.MqttFactory; +import cn.iocoder.yudao.module.system.config.mqtt.MqttProperties; +import cn.iocoder.yudao.module.system.constant.path.PathPlanningTopicConstant; +import lombok.extern.slf4j.Slf4j; +import org.eclipse.paho.client.mqttv3.MqttClient; +import org.eclipse.paho.client.mqttv3.MqttDeliveryToken; +import org.eclipse.paho.client.mqttv3.MqttException; +import org.eclipse.paho.client.mqttv3.MqttMessage; +import org.eclipse.paho.client.mqttv3.MqttTopic; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import java.nio.charset.StandardCharsets; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +@Slf4j +@Component +public class MqttUtils { + + @Autowired + private MqttProperties config; + + private static final ExecutorService executorService = Executors.newFixedThreadPool(50); + + /** + * 发布消息 + * + * @param qos 0-至多1次、1-至少1次、2-一次 + * @param retained 是否保留:true-sub重新连接mqtt服务端时,总能拿到该主题的最新消息、false-sub重新连接mqtt服务端时,只能拿到连接后发布的消息 + * @param topic 话题 + * @param message 消息内容 + */ + public void pub(String topic, String message) { + executorService.execute(() ->{ + send(topic, message); + }); + } + + public void send(String topic, String message) { + // 获取客户端实例 + MqttClient client = null; + try { + client = MqttFactory.getInstance(); + } catch (MqttException e) { + log.info("获取客户端异常 :{}",e); + } + MqttMessage mqttMessage = new MqttMessage(); + mqttMessage.setQos(config.getQos()); + mqttMessage.setRetained(false); + // 此处必须指明编码方式,否则会出现订阅端中文乱码的情况 + mqttMessage.setPayload(message.getBytes(StandardCharsets.UTF_8)); + // 主题的目的地,用于发布/订阅信息 + MqttTopic mqttTopic = client.getTopic(topic); + // 提供一种机制来跟踪消息的传递进度 + // 用于在以非阻塞方式(在后台运行)执行发布是跟踪消息的传递进度 + MqttDeliveryToken token; + try { + // 将指定消息发布到主题,但不等待消息传递完成,返回的token可用于跟踪消息的传递状态 + // 一旦此方法干净地返回,消息就已被客户端接受发布,当连接可用,将在后台完成消息传递。 + token = mqttTopic.publish(mqttMessage); + token.waitForCompletion(); + } catch (MqttException e) { + log.info("MQTT"); + } + + if (PathPlanningTopicConstant.AGV_POSE.equals(topic)) { + return; + } + + if (message.length() > 510) { + log.info("发送的主题 :{}, 内容 :{}",topic, message.substring(0, 500)); + }else { + log.info("发送的主题 :{}, 内容 :{}",topic, message); + } + } + + /** + * 断开连接 + */ + public static void disConnect() { + try { + // 获取客户端实例 + MqttClient client = MqttFactory.getInstance(); + client.disconnect(); + } catch (MqttException e) { + e.printStackTrace(); + } + } +} \ No newline at end of file diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/config/poperties/ZnConfigConstant.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/config/poperties/ZnConfigConstant.java new file mode 100644 index 000000000..1029c4cf4 --- /dev/null +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/config/poperties/ZnConfigConstant.java @@ -0,0 +1,37 @@ +package cn.iocoder.yudao.module.system.config.poperties; + +import cn.iocoder.yudao.module.system.config.poperties.dto.RobotCharge; +import cn.iocoder.yudao.module.system.config.poperties.dto.RobotConfig; +import cn.iocoder.yudao.module.system.config.poperties.dto.RobotDoingAction; +import cn.iocoder.yudao.module.system.config.poperties.dto.Task; +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.cloud.context.config.annotation.RefreshScope; +import org.springframework.stereotype.Component; + +@Data +@RefreshScope +@Component +@ConfigurationProperties(prefix = "zn") +public class ZnConfigConstant { + private String taskNo; + private String moveNo; + private String chargeNo; + private String cameraSecretKey; + private Boolean doCycle; + private Boolean laneAutoMove; + private Long robotPositionCacheTime; + private Boolean cycleDoAutoMove; + private String fullElectricity; + private Boolean taskNeedSingle; + private Long locationNumberReduce; + private RobotDoingAction robotDoingAction; + private RobotCharge robotCharge; + private Task task ; + private RobotConfig robotConfig; + private Boolean openRateLimiter; + private Boolean isSimulation; + private Boolean sendRobotInitPose; + private Integer synchronousAllMapNode; + private Boolean taskNotCheck; +} diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/config/poperties/dto/RobotCharge.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/config/poperties/dto/RobotCharge.java new file mode 100644 index 000000000..672566d7f --- /dev/null +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/config/poperties/dto/RobotCharge.java @@ -0,0 +1,9 @@ +package cn.iocoder.yudao.module.system.config.poperties.dto; + +import lombok.Data; + +@Data +public class RobotCharge { + private Long releaseLocationNumberConfig; + private Long priorityConfig; +} diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/config/poperties/dto/RobotConfig.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/config/poperties/dto/RobotConfig.java new file mode 100644 index 000000000..b481f7fe6 --- /dev/null +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/config/poperties/dto/RobotConfig.java @@ -0,0 +1,9 @@ +package cn.iocoder.yudao.module.system.config.poperties.dto; + +import lombok.Data; + +@Data +public class RobotConfig { + private Double offsetHeight; + private Double defaultTrayHeight; +} diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/config/poperties/dto/RobotDoingAction.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/config/poperties/dto/RobotDoingAction.java new file mode 100644 index 000000000..91c3f27c3 --- /dev/null +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/config/poperties/dto/RobotDoingAction.java @@ -0,0 +1,8 @@ +package cn.iocoder.yudao.module.system.config.poperties.dto; + +import lombok.Data; + +@Data +public class RobotDoingAction { + private Long doingActionCacheTime; +} diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/config/poperties/dto/Task.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/config/poperties/dto/Task.java new file mode 100644 index 000000000..bf5e43e15 --- /dev/null +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/config/poperties/dto/Task.java @@ -0,0 +1,9 @@ +package cn.iocoder.yudao.module.system.config.poperties.dto; + +import lombok.Data; + +@Data +public class Task { + private Boolean checkSkuInfo; + private Long taskCacheTime; +} diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/constant/robot/RobotTaskChcheConstant.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/constant/robot/RobotTaskChcheConstant.java index f15b5c986..99a15f076 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/constant/robot/RobotTaskChcheConstant.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/constant/robot/RobotTaskChcheConstant.java @@ -49,4 +49,7 @@ public class RobotTaskChcheConstant { //机器人物料数量(拼接的是mac地址) public static String ROBOT_TASK_SKU_INFO = "robot:task:sku:info"; + + //所有的车辆信息 获得到一个map, key是 mac,value是具体信息 + public static String ROBOT_ALL_INFORMATION = "robot:all:information"; } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/robot/RobotInformationController.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/robot/RobotInformationController.java index 50e3ff803..e278d79b9 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/robot/RobotInformationController.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/robot/RobotInformationController.java @@ -153,7 +153,7 @@ public class RobotInformationController { @Operation(summary = "恢复任务") @PreAuthorize("@ss.hasPermission('robot:information:doTaskContinue')") public CommonResult doTaskContinue(@RequestParam("robotNo") String robotNo) { - informationService.doTaskContinue(robotNo); + informationService.doTaskContinue(robotNo,false); return success(true); } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/robot/RobotTaskController.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/robot/RobotTaskController.java index e93bcefdf..9384bd7eb 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/robot/RobotTaskController.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/robot/RobotTaskController.java @@ -130,4 +130,11 @@ public class RobotTaskController { return success(true); } + @GetMapping("/getRobotTaskNum") + @Operation(summary = "获取这台车工作的任务总数") + @Parameter(name = "robotNo", description = "车辆编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('robot:task:getRobotTaskNum')") + public CommonResult getRobotTaskNum(@RequestParam("robotNo") String robotNo) { + return success(taskService.getRobotTaskNum(robotNo)); + } } \ No newline at end of file diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/positionmap/PositionMapItemDO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/positionmap/PositionMapItemDO.java index eca00f0db..baa4ddfaf 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/positionmap/PositionMapItemDO.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/positionmap/PositionMapItemDO.java @@ -84,6 +84,7 @@ public class PositionMapItemDO extends BaseDO { /** * AGV编号 */ + @TableField(updateStrategy = FieldStrategy.IGNORED) private String robotNo; } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/cycle/TaskCycleMapper.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/cycle/TaskCycleMapper.java index e111cc529..62ead36ed 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/cycle/TaskCycleMapper.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/cycle/TaskCycleMapper.java @@ -27,4 +27,10 @@ public interface TaskCycleMapper extends BaseMapperX { } void deletByRobotTaskId(@Param("robotTaskId") Long robotTaskId); + + /** + * 批量删除 + * @param taskIds + */ + void deletByRobotTaskIds(@Param("taskIds") Set taskIds); } \ No newline at end of file diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/positionmap/PositionMapItemMapper.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/positionmap/PositionMapItemMapper.java index 7dae73ffa..5f0db31a4 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/positionmap/PositionMapItemMapper.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/positionmap/PositionMapItemMapper.java @@ -6,7 +6,6 @@ import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; import cn.iocoder.yudao.module.mqtt.api.path.dto.PositionMapItemSynDTO; import cn.iocoder.yudao.module.mqtt.api.task.dto.Pose2ds; import cn.iocoder.yudao.module.system.controller.admin.positionmap.dto.RobotPositionMapDTO; -import cn.iocoder.yudao.module.system.controller.admin.positionmap.vo.PositionMapIdNumMapVO; import cn.iocoder.yudao.module.system.controller.admin.positionmap.vo.PositionMapItemPageReqVO; import cn.iocoder.yudao.module.system.dal.dataobject.positionmap.PositionMapItemDO; import org.apache.ibatis.annotations.Mapper; @@ -96,5 +95,7 @@ public interface PositionMapItemMapper extends BaseMapperX { * @param ids * @return */ - List selectSortNumByIds(@Param("ids") List ids); + /*@MapKey("id") + Map selectSortNumByIds(@Param("ids") List ids);*/ + List selectSortNumByIds(@Param("ids") List ids); } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/robot/RobotInformationMapper.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/robot/RobotInformationMapper.java index 43c66cea0..b13efbd4d 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/robot/RobotInformationMapper.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/robot/RobotInformationMapper.java @@ -88,4 +88,8 @@ public interface RobotInformationMapper extends BaseMapperX * @return */ List getListByMapId(@Param("mapId") Long mapId); + + RobotInformationDO selectByRobotNoAndIdNotIn(@Param("robotNo") String robotNo, @Param("id") Long id); + + RobotInformationDO selectByMacAndIdNotIn(@Param("macAddress") String macAddress,@Param("id") Long id); } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/enums/robot/task/RobotStatusCodeEnum.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/enums/robot/task/RobotStatusCodeEnum.java index bfda718ca..271064018 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/enums/robot/task/RobotStatusCodeEnum.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/enums/robot/task/RobotStatusCodeEnum.java @@ -13,7 +13,8 @@ public enum RobotStatusCodeEnum { FAIL_JSON("10001","入参JSON解析失败"), FAIL_SYSTEM("10002","系统内部异常"), FAIL_UN_KNOW("10003","未知错误"), - FAIL_UN_SUPPOD("10004","未支持该指令执行"); + FAIL_UN_SUPPOD("10004","未支持该指令执行"), + EXCEEDING_SECONDS("10017","PP发送的任务超过5秒到达"); /** * 类型 */ diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/enums/robot/task/WorkProgressEnum.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/enums/robot/task/WorkProgressEnum.java new file mode 100644 index 000000000..ffe96d5ef --- /dev/null +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/enums/robot/task/WorkProgressEnum.java @@ -0,0 +1,17 @@ +package cn.iocoder.yudao.module.system.enums.robot.task; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +@Getter +@AllArgsConstructor +public enum WorkProgressEnum { + + FORK_OFFSET("FORK_OFFSET","取放货"); + + /** + * 类型 + */ + private final String type; + private final String msg; +} diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/mqtt/MqttConfiguration.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/mqtt/MqttConfiguration.java index 37ff1a43a..fb74c29c6 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/mqtt/MqttConfiguration.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/mqtt/MqttConfiguration.java @@ -3,10 +3,11 @@ package cn.iocoder.yudao.module.system.framework.mqtt; import cn.iocoder.yudao.module.mqtt.api.common.CommonApi; import cn.iocoder.yudao.module.mqtt.api.path.PathPlanningApi; import cn.iocoder.yudao.module.mqtt.api.task.RobotTaskApi; +import cn.iocoder.yudao.module.remote.api.path.RemotePathApi; import org.springframework.cloud.openfeign.EnableFeignClients; import org.springframework.context.annotation.Configuration; @Configuration(proxyBeanMethods = false) -@EnableFeignClients(clients = {RobotTaskApi.class, PathPlanningApi.class, CommonApi.class}) +@EnableFeignClients(clients = {RobotTaskApi.class, PathPlanningApi.class, CommonApi.class, RemotePathApi.class}) public class MqttConfiguration { } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/job/robot/RobotJob.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/job/robot/RobotJob.java index 06e8faf9f..cd91eace5 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/job/robot/RobotJob.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/job/robot/RobotJob.java @@ -84,9 +84,11 @@ public class RobotJob { RLock lock = redissonUtils.getLock(RobotCacheLockEnum.ROBOT_TASK_DISTRIBUTE_LOCK.getKey()); if (lock.tryLock()){ try { - log.info("----下发自动充电任务----"); + log.info("----111111下发自动充电任务----"); autoChargeService.autoChargeJob(); - } finally { + } catch (Exception e) { + log.info("自动充电异常 :{}",e); + } finally { lock.unlock(); } }else { @@ -105,9 +107,11 @@ public class RobotJob { RLock lock = redissonUtils.getLock(RobotCacheLockEnum.ROBOT_TASK_DISTRIBUTE_LOCK.getKey()); if (lock.tryLock()){ try { - log.info("----下发任务给路径规划----"); + log.info("----111111下发任务给路径规划----"); robotPathPlanningService.sendTaskToPP(); - } finally { + } catch (Exception e) { + log.info("----分配任务异常---- :{}",e); + } finally { lock.unlock(); } }else { @@ -127,12 +131,16 @@ public class RobotJob { RLock lock = redissonUtils.getLock(RobotCacheLockEnum.ROBOT_TASK_ADD_LOCK.getKey()); if (lock.tryLock()){ + try { - log.info("----创建循环任务----"); + log.info("----111111创建循环任务----"); cycleService.cycleTaskJob(); - } finally { + } catch (Exception e) { + log.error("创建循环任务异常 :{}",e); + } finally { lock.unlock(); } + }else { log.info("下发任务给路径规划未获取到锁"); throw exception(REDISSON_NOT_OBTAIN_LOCK); @@ -173,7 +181,9 @@ public class RobotJob { log.info("----统计时长开始----"); TenantContextHolder.setTenantId(1L); robotWorkingHoursStatisticsService.statisticsRobotDuration(); - } finally { + } catch (Exception e) { + log.info("统计工作时长异常 :{}",e); + } finally { lock.unlock(); } }else { diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/schedul/RcsMapScheduled.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/schedul/RcsMapScheduled.java new file mode 100644 index 000000000..5c1a88b72 --- /dev/null +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/schedul/RcsMapScheduled.java @@ -0,0 +1,74 @@ +package cn.iocoder.yudao.module.system.schedul; + + +import cn.hutool.core.util.ObjectUtil; +import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder; +import cn.iocoder.yudao.module.infra.api.websocket.WebSocketSenderApi; +import cn.iocoder.yudao.module.system.constant.CommonConstant; +import cn.iocoder.yudao.module.system.constant.area.FloorAreaConstant; +import cn.iocoder.yudao.module.system.constant.webSocket.WebSocketConstant; +import cn.iocoder.yudao.module.system.dal.dataobject.positionmap.PositionMapDO; +import cn.iocoder.yudao.module.system.service.positionmap.PositionMapService; +import cn.iocoder.yudao.module.system.util.redis.RedisUtil; +import com.alibaba.fastjson.JSON; +import lombok.extern.slf4j.Slf4j; +import org.springframework.scheduling.annotation.EnableScheduling; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Component; + +import javax.annotation.Resource; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.TimeUnit; + +@EnableScheduling +@Component +@Slf4j +public class RcsMapScheduled { + + @Resource + private RedisUtil redisUtil; + + @Resource + private PositionMapService positionMapService; + + @Resource + public WebSocketSenderApi webSocketSenderApi; + + private static final ExecutorService FIXED_THREAD_POOL = Executors.newFixedThreadPool(10); + + // 这个方法将每200毫秒执行一次 + @Scheduled(fixedDelay = 100, timeUnit = TimeUnit.MILLISECONDS) + public void executeTask() { + FIXED_THREAD_POOL.execute(this::sendRobotInformationToRcsMap); + } + + private void sendRobotInformationToRcsMap() { + + TenantContextHolder.setTenantId(1L); + Object o = redisUtil.get(FloorAreaConstant.FLOOR_AREA_ALL); + + List allMap = null; + if (ObjectUtil.isEmpty(o)) { + allMap = positionMapService.getAllMap(); + if (ObjectUtil.isEmpty(allMap)) { + return; + } + redisUtil.set(FloorAreaConstant.FLOOR_AREA_ALL, JSON.toJSONString(allMap),600); + }else { + allMap = JSON.parseArray(String.valueOf(o), PositionMapDO.class); + } + + for (PositionMapDO positionMap : allMap) { + String floorArea = positionMap.getFloor() + CommonConstant.SYMBOL + positionMap.getArea(); + String key = FloorAreaConstant.FLOOR_AREA_ROBOT + floorArea; + Map data = redisUtil.hmget(key); + if (ObjectUtil.isEmpty(data)) { + continue; + } + webSocketSenderApi.sendObject(floorArea, WebSocketConstant.MAP_PUSH, data); + } + } +} diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/schedul/ScheduledTasks.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/schedul/ThreeDimensionalScheduled.java similarity index 91% rename from yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/schedul/ScheduledTasks.java rename to yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/schedul/ThreeDimensionalScheduled.java index 0a1f30b37..776ee5b82 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/schedul/ScheduledTasks.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/schedul/ThreeDimensionalScheduled.java @@ -28,7 +28,7 @@ import java.util.concurrent.TimeUnit; @EnableScheduling @Component @Slf4j -public class ScheduledTasks { +public class ThreeDimensionalScheduled { @Resource private PositionMapService positionMapService; @@ -39,17 +39,12 @@ public class ScheduledTasks { @Resource public WebSocketSenderApi webSocketSenderApi; - private static final ExecutorService fixedThreadPool = Executors.newFixedThreadPool(3); + private static final ExecutorService FIXED_THREAD_POOL = Executors.newFixedThreadPool(3); // 这个方法将每200毫秒执行一次 // @Scheduled(fixedDelay = 300, timeUnit = TimeUnit.MILLISECONDS) public void executeTask() { - fixedThreadPool.execute(new Runnable() { - @Override - public void run() { - sendData(); - } - }); + FIXED_THREAD_POOL.execute(this::sendData); } public void sendData() { @@ -61,7 +56,7 @@ public class ScheduledTasks { if (ObjectUtil.isEmpty(allMap)) { return; } - redisUtil.set(FloorAreaConstant.FLOOR_AREA_ALL,JSON.toJSONString(allMap),60); + redisUtil.set(FloorAreaConstant.FLOOR_AREA_ALL,JSON.toJSONString(allMap),600); }else { allMap = JSON.parseArray(String.valueOf(o), PositionMapDO.class); } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/information/DeviceInformationServiceImpl.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/information/DeviceInformationServiceImpl.java index 1038c2044..8cebd5b15 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/information/DeviceInformationServiceImpl.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/information/DeviceInformationServiceImpl.java @@ -5,6 +5,7 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils; +import cn.iocoder.yudao.module.system.config.poperties.ZnConfigConstant; import cn.iocoder.yudao.module.system.constant.device.DeviceChcheConstant; import cn.iocoder.yudao.module.system.controller.admin.information.dto.DeviceInformationDTO; import cn.iocoder.yudao.module.system.controller.admin.information.dto.MapBindDeviceInfoDTO; @@ -40,6 +41,7 @@ import com.serotonin.modbus4j.ModbusMaster; import com.serotonin.modbus4j.exception.ModbusInitException; import com.serotonin.modbus4j.exception.ModbusTransportException; import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Service; @@ -91,8 +93,8 @@ public class DeviceInformationServiceImpl extends ServiceImpl> partition = Lists.partition(positionMapItemSynDTOS, synchronousAllMapNodeSize); + List> partition = Lists.partition(positionMapItemSynDTOS, znConfigConstant.getSynchronousAllMapNode()); for (List nodes : partition) { PositionMapItemPathDTO relatedPathNode = new PositionMapItemPathDTO(); relatedPathNode.setFloor(positionMapDO.getFloor()); relatedPathNode.setArea(positionMapDO.getArea()); relatedPathNode.setType(PathTypeEnum.INIT.getType()); relatedPathNode.setControl_nodes(nodes); - commonApi.commonMethod(relatedPathNode, PathPlanningTopicConstant.SYNCHRONOUS_ALL_MAP_NODE); +// commonApi.commonMethod(relatedPathNode, PathPlanningTopicConstant.SYNCHRONOUS_ALL_MAP_NODE); + mqttUtils.pub(PathPlanningTopicConstant.SYNCHRONOUS_ALL_MAP_NODE,JSON.toJSONString(relatedPathNode)); } } @@ -257,7 +261,8 @@ public class PathPlanningServiceImpl implements PathPlanningService { relatedPathNode.setArea(positionMapDO.getArea()); relatedPathNode.setControl_nodes(list); - commonApi.commonMethod(relatedPathNode, PathPlanningTopicConstant.ADD_MAP_LINE); +// commonApi.commonMethod(relatedPathNode, PathPlanningTopicConstant.ADD_MAP_LINE); + mqttUtils.pub(PathPlanningTopicConstant.ADD_MAP_LINE,JSON.toJSONString(relatedPathNode)); } /** @@ -287,8 +292,8 @@ public class PathPlanningServiceImpl implements PathPlanningService { ids.add(data.getId()); relatedPathNode.setIds(ids); - commonApi.commonMethod(relatedPathNode, PathPlanningTopicConstant.DELETE_MAP_LINE); - +// commonApi.commonMethod(relatedPathNode, PathPlanningTopicConstant.DELETE_MAP_LINE); + mqttUtils.pub(PathPlanningTopicConstant.DELETE_MAP_LINE,JSON.toJSONString(relatedPathNode)); } /** @@ -335,7 +340,8 @@ public class PathPlanningServiceImpl implements PathPlanningService { relatedPathNode.setType(PathTypeEnum.UPDATE.getType()); relatedPathNode.setControl_nodes(list); - commonApi.commonMethod(relatedPathNode, PathPlanningTopicConstant.UPDATE_MAP_LINE); +// commonApi.commonMethod(relatedPathNode, PathPlanningTopicConstant.UPDATE_MAP_LINE); + mqttUtils.pub(PathPlanningTopicConstant.UPDATE_MAP_LINE,JSON.toJSONString(relatedPathNode)); } /** @@ -377,7 +383,8 @@ public class PathPlanningServiceImpl implements PathPlanningService { PositionMapItemPathDTO.setType(PathTypeEnum.ADD.getType()); PositionMapItemPathDTO.setControl_nodes(Arrays.asList(build)); - commonApi.commonMethod(PositionMapItemPathDTO, PathPlanningTopicConstant.ADD_MAP_NODE); +// commonApi.commonMethod(PositionMapItemPathDTO, PathPlanningTopicConstant.ADD_MAP_NODE); + mqttUtils.pub(PathPlanningTopicConstant.ADD_MAP_NODE,JSON.toJSONString(PositionMapItemPathDTO)); } /** @@ -411,7 +418,8 @@ public class PathPlanningServiceImpl implements PathPlanningService { PositionMapItemPathDTO.setType(PathTypeEnum.DELETE.getType()); PositionMapItemPathDTO.setIds(Arrays.asList(data.getId())); - commonApi.commonMethod(PositionMapItemPathDTO, PathPlanningTopicConstant.DELETE_MAP_NODE); +// commonApi.commonMethod(PositionMapItemPathDTO, PathPlanningTopicConstant.DELETE_MAP_NODE); + mqttUtils.pub( PathPlanningTopicConstant.DELETE_MAP_NODE,JSON.toJSONString(PositionMapItemPathDTO)); } @Override @@ -448,13 +456,15 @@ public class PathPlanningServiceImpl implements PathPlanningService { PositionMapItemPathDTO.setType(PathTypeEnum.UPDATE.getType()); PositionMapItemPathDTO.setControl_nodes(Arrays.asList(build)); - commonApi.commonMethod(PositionMapItemPathDTO, PathPlanningTopicConstant.UPDATE_MAP_NODE); +// commonApi.commonMethod(PositionMapItemPathDTO, PathPlanningTopicConstant.UPDATE_MAP_NODE); + mqttUtils.pub(PathPlanningTopicConstant.UPDATE_MAP_NODE,JSON.toJSONString(PositionMapItemPathDTO)); } @Override public void robotDimensions() { List list = informationMapper.selectRobotDimensions(); - commonApi.commonMethod(list, PathPlanningTopicConstant.SEND_ROBOT_DIMENSIONS); +// commonApi.commonMethod(list, PathPlanningTopicConstant.SEND_ROBOT_DIMENSIONS); + mqttUtils.pub(PathPlanningTopicConstant.SEND_ROBOT_DIMENSIONS,JSON.toJSONString(list)); } /** @@ -470,10 +480,11 @@ public class PathPlanningServiceImpl implements PathPlanningService { String topic = RobotTopicConstant.ROBOT_TASK_MOVE_TOPIC + mac; if(RobotCommandTypeEnum.SWITCH_MAP.getType().equals(pathRobotDTO.getTaskType())) { switchMap(pathRobotDTO,topic); - } else if (PathTaskTypeToRobotEnum.DROP_OFF_GOODS.getType().equals(pathRobotDTO.getTaskType())) { + } /*else if (PathTaskTypeToRobotEnum.DROP_OFF_GOODS.getType().equals(pathRobotDTO.getTaskType())) { wordDropOffGoods(message,topic,pathRobotDTO.getRobotNo()); - } else { - commonApi.commonMethodStr(message, topic); + } */else { +// commonApi.commonMethodStr(message, topic); + mqttUtils.pub(topic,message); } } @@ -487,7 +498,8 @@ public class PathPlanningServiceImpl implements PathPlanningService { RobotModelDO model = modelService.getModel(robotInformation.getRobotModelId()); if (String.valueOf(ZeroOneEnum.ZERO.getType()).equals(model.getRobotXOffset()) && String.valueOf(ZeroOneEnum.ZERO.getType()).equals(model.getRobotYOffset())) { - commonApi.commonMethodStr(message, topic); +// commonApi.commonMethodStr(message, topic); + mqttUtils.pub(topic,message); return; } PathToRobotChangeXYDTO pathToRobotChangeXY = JSON.parseObject(message, PathToRobotChangeXYDTO.class); @@ -502,7 +514,8 @@ public class PathPlanningServiceImpl implements PathPlanningService { } if (!needOffset) { - commonApi.commonMethodStr(message, topic); +// commonApi.commonMethodStr(message, topic); + mqttUtils.pub(topic,message); return; } @@ -518,8 +531,10 @@ public class PathPlanningServiceImpl implements PathPlanningService { BigDecimal y = (sino.multiply(robotXOffset, MathContext.DECIMAL32)).add(coso.multiply(robotYOffset, MathContext.DECIMAL32)).add(y1); cargoPose.setX(x.doubleValue()); cargoPose.setY(y.doubleValue()); - log.info("转换后 :{}",JSON.toJSONString(pathToRobotChangeXY)); - commonApi.commonMethodStr(JSON.toJSONString(pathToRobotChangeXY), topic); + log.info("111111转换前数据 :{}",message); + log.info("111111转换后 :{}",JSON.toJSONString(pathToRobotChangeXY)); +// commonApi.commonMethodStr(JSON.toJSONString(pathToRobotChangeXY), topic); + mqttUtils.pub(topic,JSON.toJSONString(pathToRobotChangeXY)); } /** @@ -531,7 +546,8 @@ public class PathPlanningServiceImpl implements PathPlanningService { String mapFileName = positionMapService.getMapFileNameByFloorAndAreaName(pathRobotDTO.getArg().getFloor(),pathRobotDTO.getArg().getAreaId()); pathRobotDTO.getArg().setMapName(mapFileName); controllerInformationService.robotChangeSpeed(pathRobotDTO); - commonApi.commonMethodStr(JSON.toJSONString(pathRobotDTO), topic); +// commonApi.commonMethodStr(JSON.toJSONString(pathRobotDTO), topic); + mqttUtils.pub(topic,JSON.toJSONString(pathRobotDTO)); RobotTaskDetailActionLogDO actionLog = taskDetailActionLogService.getLastTaskByRobotNo(pathRobotDTO.getRobotNo(),null); if (ObjectUtil.isNotEmpty(actionLog)) { //为了统计各个地图的工作时间 @@ -568,7 +584,9 @@ public class PathPlanningServiceImpl implements PathPlanningService { public void updateBehavior(String orderId, String robotNo, String behaviorId, String isReach) { TaskPathPlanningDTO build = TaskPathPlanningDTO.builder().orderId(orderId).robotNo(robotNo) .behaviorId(behaviorId).isReach(isReach).build(); - commonApi.commonMethod(build, PathPlanningTopicConstant.UPDATE_BEHAVIOR); + log.info("111111发给PP的数据 :{}",JSON.toJSONString(build)); +// commonApi.commonMethod(build, PathPlanningTopicConstant.UPDATE_BEHAVIOR); + mqttUtils.pub(PathPlanningTopicConstant.UPDATE_BEHAVIOR,JSON.toJSONString(build)); } /** @@ -577,7 +595,7 @@ public class PathPlanningServiceImpl implements PathPlanningService { */ @Override public void pathPlanningMovePose(String message) { - log.info("车辆即将行走的点位 :{}",message); + log.info("111111路径规划车辆即将行走的点位 :{}",message); PathPlanningMovePoseVO robotStatusData = JSON.parseObject(message, PathPlanningMovePoseVO.class); String mac = robotInformationService.getMacByRobotNo(robotStatusData.getRobotNo()); String floorAreaKey = RobotTaskChcheConstant.ROBOT_FLOOR_AREA + mac; @@ -593,7 +611,7 @@ public class PathPlanningServiceImpl implements PathPlanningService { @Override public void simulationRobotPoseRequest() { - if (!sendRobotInitPose) { + if (!znConfigConstant.getSendRobotInitPose()) { log.info("不同步初始点位信息"); return; } @@ -660,7 +678,8 @@ public class PathPlanningServiceImpl implements PathPlanningService { simulationList.add(simulationRobotPoseDTO); i++; } - commonApi.commonMethod(simulationList, PathPlanningTopicConstant.INIT_ROBOT_POSE); +// commonApi.commonMethod(simulationList, PathPlanningTopicConstant.INIT_ROBOT_POSE); + mqttUtils.pub( PathPlanningTopicConstant.INIT_ROBOT_POSE,JSON.toJSONString(simulationList)); } /** @@ -676,7 +695,8 @@ public class PathPlanningServiceImpl implements PathPlanningService { @Override public void synchronousStart() { - commonApi.commonMethodStr("开始同步点位信息", PathPlanningTopicConstant.SYNCHRONOUS_ALL_MAP_INIT); +// commonApi.commonMethodStr("开始同步点位信息", PathPlanningTopicConstant.SYNCHRONOUS_ALL_MAP_INIT); + mqttUtils.pub(PathPlanningTopicConstant.SYNCHRONOUS_ALL_MAP_INIT,"开始同步点位信息"); try { Thread.sleep(1000); } catch (InterruptedException e) { @@ -688,7 +708,8 @@ public class PathPlanningServiceImpl implements PathPlanningService { public void sendPositionChangePointBinding() { List bindingDTOS = positionChangePointBindingService.getAllPositionChangePointBinding(); if (ObjectUtil.isNotEmpty(bindingDTOS)) { - commonApi.commonMethod(bindingDTOS, PathPlanningTopicConstant.SYNCHRONOUS_ALL_SWITCH_POINT_BINDING); +// commonApi.commonMethod(bindingDTOS, PathPlanningTopicConstant.SYNCHRONOUS_ALL_SWITCH_POINT_BINDING); + mqttUtils.pub(PathPlanningTopicConstant.SYNCHRONOUS_ALL_SWITCH_POINT_BINDING,JSON.toJSONString(bindingDTOS)); } } @@ -745,8 +766,8 @@ public class PathPlanningServiceImpl implements PathPlanningService { relatedPathNode.setControl_nodes(list); - commonApi.commonMethod(relatedPathNode, PathPlanningTopicConstant.SYNCHRONOUS_ALL_MAP_LINE); - +// commonApi.commonMethod(relatedPathNode, PathPlanningTopicConstant.SYNCHRONOUS_ALL_MAP_LINE); + mqttUtils.pub(PathPlanningTopicConstant.SYNCHRONOUS_ALL_MAP_LINE,JSON.toJSONString(relatedPathNode)); } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/positionmap/PositionMapLineServiceImpl.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/positionmap/PositionMapLineServiceImpl.java index 51f0aaa40..6290d1fa8 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/positionmap/PositionMapLineServiceImpl.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/positionmap/PositionMapLineServiceImpl.java @@ -9,6 +9,7 @@ import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.module.system.controller.admin.positionmap.vo.PositionMapIdNumMapVO; import cn.iocoder.yudao.module.system.controller.admin.positionmap.vo.PositionMapLinePageReqVO; import cn.iocoder.yudao.module.system.controller.admin.positionmap.vo.PositionMapLineSaveReqVO; +import cn.iocoder.yudao.module.system.dal.dataobject.positionmap.PositionMapItemDO; import cn.iocoder.yudao.module.system.dal.dataobject.positionmap.PositionMapLineDO; import cn.iocoder.yudao.module.system.dal.mysql.positionmap.PositionMapItemMapper; import cn.iocoder.yudao.module.system.dal.mysql.positionmap.PositionMapLineMapper; @@ -66,8 +67,10 @@ public class PositionMapLineServiceImpl extends ServiceImpl endPointIds = addList.stream().map(PositionMapLineDO::getEndPointId).collect(Collectors.toList()); //合并startPointIds 和 endPointIds 并且去重 Set pointIds = CollUtil.unionDistinct(startPointIds, endPointIds); - List positionMapIdNumMapVOS = positionMapItemMapper.selectSortNumByIds(new ArrayList<>(pointIds)); - map = positionMapIdNumMapVOS.stream().collect(Collectors.toMap(PositionMapIdNumMapVO::getId, PositionMapIdNumMapVO::getSortNum)); + List positionMapItemDOS = positionMapItemMapper.selectSortNumByIds(new ArrayList<>(pointIds)); + if (ObjectUtil.isNotEmpty(positionMapItemDOS)) { + map = positionMapItemDOS.stream().collect(Collectors.toMap(PositionMapItemDO::getId, PositionMapItemDO::getSortNum)); + } } for (PositionMapLineDO positionMapLineDO : newList) { positionMapLineDO.setPositionMapId(positionMapId); diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/positionmap/PositionMapServiceImpl.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/positionmap/PositionMapServiceImpl.java index 09d420990..4426e4752 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/positionmap/PositionMapServiceImpl.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/positionmap/PositionMapServiceImpl.java @@ -7,8 +7,10 @@ import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils; import cn.iocoder.yudao.module.mqtt.api.task.dto.RobotSimulationPoseDTO; +import cn.iocoder.yudao.module.system.api.path.PathApi; import cn.iocoder.yudao.module.system.api.remote.dto.RemoteRobotDTO; import cn.iocoder.yudao.module.system.api.remote.dto.RemoteRobotDetailDTO; +import cn.iocoder.yudao.module.system.constant.area.FloorAreaConstant; import cn.iocoder.yudao.module.system.controller.admin.log.vo.UserOperationLogSaveReqVO; import cn.iocoder.yudao.module.system.controller.admin.positionmap.dto.PositionMapDTO; import cn.iocoder.yudao.module.system.controller.admin.positionmap.vo.PositionMapPageReqVO; @@ -91,6 +93,10 @@ public class PositionMapServiceImpl extends ServiceImpl { * 继续做任务 * @param robotNo */ - void doTaskContinue(String robotNo); + void doTaskContinue(String robotNo,Boolean isRobot); /** * diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/robot/RobotInformationServiceImpl.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/robot/RobotInformationServiceImpl.java index ed5e8ffe3..c1a384a76 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/robot/RobotInformationServiceImpl.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/robot/RobotInformationServiceImpl.java @@ -23,6 +23,8 @@ import cn.iocoder.yudao.module.system.api.robot.dto.FloorZoneDTO; import cn.iocoder.yudao.module.system.api.robot.dto.RobotStatusDTO; import cn.iocoder.yudao.module.system.api.robot.websocket.RobotStatusDataPoseDTO; import cn.iocoder.yudao.module.system.api.robot.websocket.RobotInformationVO; +import cn.iocoder.yudao.module.system.config.mqtt.util.MqttUtils; +import cn.iocoder.yudao.module.system.config.poperties.ZnConfigConstant; import cn.iocoder.yudao.module.system.constant.CommonConstant; import cn.iocoder.yudao.module.system.constant.path.PathPlanningChcheConstant; import cn.iocoder.yudao.module.system.constant.path.PathPlanningTopicConstant; @@ -50,7 +52,6 @@ import cn.iocoder.yudao.module.system.dal.mysql.positionmap.PositionMapItemMappe import cn.iocoder.yudao.module.system.dal.mysql.positionmap.PositionMapMapper; import cn.iocoder.yudao.module.system.dal.mysql.remote.RemoteControllerInformationMapper; import cn.iocoder.yudao.module.system.dal.mysql.robot.*; -import cn.iocoder.yudao.module.system.dal.mysql.statistics.RobotWorkingHoursStatisticsMapper; import cn.iocoder.yudao.module.system.dal.mysql.wait.MoveToWaitMapper; import cn.iocoder.yudao.module.system.enums.common.ZeroOneEnum; import cn.iocoder.yudao.module.system.enums.device.DeviceTypeEnum; @@ -118,8 +119,11 @@ public class RobotInformationServiceImpl extends ServiceImpl() - .eq(RobotInformationDO::getMacAddress, createReqVO.getMacAddress()) - .last("limit 1")); - if (ObjectUtil.isNotEmpty(existRobotMac)) { + RobotInformationDO existRobotInformationDO = + informationMapper.selectByMacAndIdNotIn(createReqVO.getMacAddress(),null); + if (ObjectUtil.isNotEmpty(existRobotInformationDO)) { throw exception(ROBOT_MAC_ADDRESS_EXISTS); } - //判断机器人编号 - RobotInformationDO existRobotNo = informationMapper.selectOne(new LambdaQueryWrapper() - .eq(RobotInformationDO::getRobotNo, createReqVO.getRobotNo()) - .last("limit 1")); - if (ObjectUtil.isNotEmpty(existRobotNo)) { + HashSet set = new HashSet<>(); + set.add(createReqVO.getRobotNo()); + List robots = informationMapper.selectByRobotNos(set); + if (ObjectUtil.isNotEmpty(robots)) { throw exception(ROBOT_ROBOT_NO_EXISTS); } @@ -251,7 +240,8 @@ public class RobotInformationServiceImpl extends ServiceImpl list = informationMapper.selectRobotDimensions(); - commonApi.commonMethod(list, PathPlanningTopicConstant.SEND_ROBOT_DIMENSIONS); +// commonApi.commonMethod(list, PathPlanningTopicConstant.SEND_ROBOT_DIMENSIONS); + mqttUtils.pub(PathPlanningTopicConstant.SEND_ROBOT_DIMENSIONS, JSON.toJSONString(list)); redisUtil.del(key); // 返回 @@ -369,6 +359,21 @@ public class RobotInformationServiceImpl extends ServiceImpl() + .eq(PositionMapItemDO::getRobotNo, robotInformationDO.getRobotNo()) + .eq(PositionMapItemDO::getUseStatus, UseStatusEnum.USEING.getType()) + .eq(PositionMapItemDO::getType, PositionMapItemEnum.STOP.getType()) + .last("limit 1")); + if (ObjectUtil.isNotEmpty(positionMapItem) && ObjectUtil.isEmpty(updateReqVO.getFloorAreaJson())) { + log.info("车辆 :{} ,停靠在 :{},", robotInformationDO.getRobotNo(), positionMapItem.getPositionMapId()); + throw exception(ROBOT_PART_AREA); + } else if (ObjectUtil.isNotEmpty(positionMapItem) && ObjectUtil.isNotEmpty(updateReqVO.getFloorAreaJson()) + && !updateReqVO.getFloorAreaJson().contains(positionMapItem.getPositionMapId())) { + throw exception(ROBOT_PART_AREA); + } + } + RemoteControllerInformationDO remoteControllerInformation = controllerInformationMapper.selectOne(new LambdaQueryWrapper() .eq(RemoteControllerInformationDO::getRobotNo, robotInformationDO.getRobotNo()) .last("limit 1")); @@ -385,24 +390,22 @@ public class RobotInformationServiceImpl extends ServiceImpl existRobot = informationMapper.queryAllByLimit(query); - boolean exist = existRobot.stream().anyMatch(v -> (v.getMacAddress().equals(updateReqVO.getMacAddress()) - && !v.getId().equals(updateReqVO.getId()))); - if (exist) { - throw exception(ROBOT_MAC_ADDRESS_EXISTS); + if (!updateReqVO.getRobotNo().equals(robotInformationDO.getRobotNo())) { + RobotInformationDO existRobotInformationDO = + informationMapper.selectByRobotNoAndIdNotIn(updateReqVO.getRobotNo(),updateReqVO.getId()); + if (ObjectUtil.isNotEmpty(existRobotInformationDO)) { + throw exception(ROBOT_ROBOT_NO_EXISTS); + } } - //校验机器人编号 - query.setMacAddress(null); - query.setRobotNo(updateReqVO.getRobotNo()); - List existRobotNo = informationMapper.queryAllByLimit(query); - boolean robotNoExist = existRobotNo.stream().anyMatch(v -> (v.getRobotNo().equals(updateReqVO.getRobotNo()) - && !v.getId().equals(updateReqVO.getId()))); - if (robotNoExist) { - throw exception(ROBOT_ROBOT_NO_EXISTS); + + if (!updateReqVO.getMacAddress().equals(robotInformationDO.getMacAddress())) { + RobotInformationDO existRobotInformationDO = + informationMapper.selectByMacAndIdNotIn(updateReqVO.getMacAddress(),updateReqVO.getId()); + if (ObjectUtil.isNotEmpty(existRobotInformationDO)) { + throw exception(ROBOT_MAC_ADDRESS_EXISTS); + } } + //校验IP RobotInformationDO existRobotIp = informationMapper.selectOne(new LambdaQueryWrapper() .eq(RobotInformationDO::getRobotIp, updateReqVO.getRobotIp()) @@ -425,7 +428,7 @@ public class RobotInformationServiceImpl extends ServiceImpl RobotDimensions = informationMapper.selectRobotDimensions(); - commonApi.commonMethod(RobotDimensions, PathPlanningTopicConstant.SEND_ROBOT_DIMENSIONS); + List robotDimensions = informationMapper.selectRobotDimensions(); +// commonApi.commonMethod(robotDimensions, PathPlanningTopicConstant.SEND_ROBOT_DIMENSIONS); + mqttUtils.pub(PathPlanningTopicConstant.SEND_ROBOT_DIMENSIONS, JSON.toJSONString(robotDimensions)); } /** * 跟新车辆编号 + * * @param oldRobotNo * @param newRobotNo */ @Transactional(rollbackFor = Exception.class) public void updateRobotNo(String oldRobotNo, String newRobotNo) { - deviceInformationMapper.updateRobotNo(oldRobotNo,newRobotNo); + deviceInformationMapper.updateRobotNo(oldRobotNo, newRobotNo); - controllerInformationMapper.updateRobotNo(oldRobotNo,newRobotNo); + controllerInformationMapper.updateRobotNo(oldRobotNo, newRobotNo); RobotChargeLogDO robotChargeLog = chargeLogMapper.selectOne(new LambdaQueryWrapperX() .eq(RobotChargeLogDO::getRobotNo, oldRobotNo) @@ -504,11 +509,11 @@ public class RobotInformationServiceImpl extends ServiceImpl() + .eq(PositionMapItemDO::getRobotNo, robotInformationDO.getRobotNo()) + .eq(PositionMapItemDO::getType, PositionMapItemEnum.STOP.getType()) + .last("limit 1")); + if (ObjectUtil.isNotEmpty(positionMapItem)) { + positionMapItem.setRobotNo(null); + positionMapItem.setUseStatus(UseStatusEnum.FREE.getType()); + positionMapItemMapper.updateById(positionMapItem); + } + //释放暂停记录 releaseRobotStop(robotInformationDO); - List RobotDimensions = informationMapper.selectRobotDimensions(); - commonApi.commonMethod(RobotDimensions, PathPlanningTopicConstant.SEND_ROBOT_DIMENSIONS); + List robotDimensions = informationMapper.selectRobotDimensions(); +// commonApi.commonMethod(robotDimensions, PathPlanningTopicConstant.SEND_ROBOT_DIMENSIONS); + mqttUtils.pub(PathPlanningTopicConstant.SEND_ROBOT_DIMENSIONS, JSON.toJSONString(robotDimensions)); String pose2dKey = RobotTaskChcheConstant.ROBOT_INFORMATION_POSE_BAT + robotInformationDO.getMacAddress(); redisUtil.del(pose2dKey); @@ -668,7 +684,7 @@ public class RobotInformationServiceImpl extends ServiceImpl robotInformations = informationMapper.queryAllByLimit(query); for (RobotInformationDO robotInformationDO : robotInformations) { String topic = RobotTopicConstant.RCS_HEART_BEAT + robotInformationDO.getMacAddress(); - commonApi.commonMethod(new RobotRcsHeartBeatDTO(), topic); +// commonApi.commonMethod(new RobotRcsHeartBeatDTO(), topic); + mqttUtils.pub(topic, JSON.toJSONString(new RobotRcsHeartBeatDTO())); } } @@ -1117,13 +1134,14 @@ public class RobotInformationServiceImpl extends ServiceImpl robotNoLimitions = Arrays.asList(taskRobotNoLimittationAreaDTO); pathPlanning.setRobotNoLimitationAreaDTOS(robotNoLimitions); - if (!isSimulation || !restoreTaskRestart) { - resendToPPData(pathPlanning, actionLog, robotInformationDO, false); - } + resendToPPData(pathPlanning, actionLog, robotInformationDO, false); List pathPlanningList = new ArrayList<>(); pathPlanningList.add(pathPlanning); String plantingKey = PathPlanningChcheConstant.PATH_PLANNING_TASK + pathPlanning.getOrderId(); - redisUtil.set(plantingKey, JSON.toJSONString(pathPlanning), taskChcheTime); + redisUtil.set(plantingKey, JSON.toJSONString(pathPlanning), znConfigConstant.getTask().getTaskCacheTime()); log.info("任务下发给PP :{}", JSON.toJSONString(pathPlanningList)); - commonApi.commonMethod(pathPlanningList, PathPlanningTopicConstant.TASK_ASSIGNMENT_REQUEST); +// commonApi.commonMethod(pathPlanningList, PathPlanningTopicConstant.TASK_ASSIGNMENT_REQUEST); + mqttUtils.pub(PathPlanningTopicConstant.TASK_ASSIGNMENT_REQUEST, JSON.toJSONString(pathPlanningList)); } private void resendToPPData(TaskToPathPlanningDTO pathPlanning, RobotTaskDetailActionLogDO actionLog, RobotInformationDO robotInformationDO, Boolean isRemote) { @@ -1256,7 +1278,7 @@ public class RobotInformationServiceImpl extends ServiceImpl v.getDeviceAttribute().equals(robot.getChargeType()) - && robot.getFloorAreaJson().contains(v.getPositionMapId())) - .findFirst() - .orElse(new DeviceInformationDO()); - if (ObjectUtil.isEmpty(deviceInformationDO.getDeviceNo())) { + DeviceInformationDO deviceInformationDO = null; + for (DeviceInformationDO v : deviceInformations) { + if (ObjectUtil.isNotEmpty(v.getLastUser()) && v.getLastUser().equals(robot.getRobotNo())) { + deviceInformationDO = v; + break; + } + if (v.getDeviceAttribute().equals(robot.getChargeType()) + && robot.getFloorAreaJson().contains(v.getPositionMapId()) && DeviceUseStatusEnum.IDLE.getType().equals(v.getDeviceUseStatus())) { + deviceInformationDO = v; + } + } + + if (ObjectUtil.isEmpty(deviceInformationDO)) { log.info("当前机器人查不到对应的充电桩类型、或者机器人不能在此区域充电 :{}", robot.getRobotNo()); throw exception(ROBOT_NOT_FOUND_FREE_CHARGING_STATION); } @@ -1453,7 +1506,7 @@ public class RobotInformationServiceImpl extends ServiceImpl robotNos = robots.stream().map(RobotInformationDO::getRobotNo).collect(Collectors.toList()); List list = new ArrayList<>(); - String floorArea = floor + CommonConstant.SYMBOL + area; + String floorArea = floor + CommonConstant.SYMBOL + area; Map hmget = redisUtil.hmget(floorArea); if (ObjectUtil.isEmpty(hmget)) { return new ArrayList<>(); @@ -1519,7 +1573,8 @@ public class RobotInformationServiceImpl extends ServiceImpl robotNos, String str) { for (String robotNo : robotNos) { String mac = getMacByRobotNo(robotNo); - commonApi.commonMethod(robotSimulationPose, RobotTopicConstant.ROBOT_COMMAND_TOPIC + mac); +// commonApi.commonMethod(robotSimulationPose, RobotTopicConstant.ROBOT_COMMAND_TOPIC + mac); + mqttUtils.pub(RobotTopicConstant.ROBOT_COMMAND_TOPIC + mac, JSON.toJSONString(robotSimulationPose)); UserOperationLogSaveReqVO operationLog = UserOperationLogSaveReqVO.builder() .operateAction(str + robotNo) .nickName(SecurityFrameworkUtils.getLoginUserNickname()).build(); @@ -1643,7 +1698,8 @@ public class RobotInformationServiceImpl extends ServiceImpl pathPlanningList = new ArrayList<>(); pathPlanningList.add(pathPlanning); log.info("远遥任务转移, 任务下发给PP :{}", JSON.toJSONString(pathPlanningList)); - commonApi.commonMethod(pathPlanningList, PathPlanningTopicConstant.TASK_ASSIGNMENT_REQUEST); +// commonApi.commonMethod(pathPlanningList, PathPlanningTopicConstant.TASK_ASSIGNMENT_REQUEST); + mqttUtils.pub(PathPlanningTopicConstant.TASK_ASSIGNMENT_REQUEST, JSON.toJSONString(pathPlanningList)); } /** @@ -1692,7 +1749,7 @@ public class RobotInformationServiceImpl extends ServiceImpl { * @param robotNo */ void chargeDone(String robotNo); + + /** + * 查询车辆的工作总数 + * @param robotNo + * @return + */ + Integer getRobotTaskNum(String robotNo); } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/robot/RobotTaskServiceImpl.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/robot/RobotTaskServiceImpl.java index ebeeecce0..ffebb895e 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/robot/RobotTaskServiceImpl.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/robot/RobotTaskServiceImpl.java @@ -13,6 +13,8 @@ import cn.iocoder.yudao.module.mqtt.api.common.CommonApi; import cn.iocoder.yudao.module.mqtt.api.task.dto.*; import cn.iocoder.yudao.module.mqtt.enums.task.ExecutionTypeEnum; import cn.iocoder.yudao.module.system.api.path.vo.RobotClosePathPlantingDTO; +import cn.iocoder.yudao.module.system.config.mqtt.util.MqttUtils; +import cn.iocoder.yudao.module.system.config.poperties.ZnConfigConstant; import cn.iocoder.yudao.module.system.constant.path.PathPlanningTopicConstant; import cn.iocoder.yudao.module.system.constant.robot.RobotTaskChcheConstant; import cn.iocoder.yudao.module.system.constant.robot.RobotTopicConstant; @@ -62,6 +64,7 @@ import cn.iocoder.yudao.module.system.service.information.DeviceInformationServi import cn.iocoder.yudao.module.system.service.log.RobotTaskDetailActionLogService; import cn.iocoder.yudao.module.system.service.log.UserOperationLogService; import cn.iocoder.yudao.module.system.service.positionmap.PositionMapItemService; +import cn.iocoder.yudao.module.system.service.robot.simulation.RobotSimulationService; import cn.iocoder.yudao.module.system.service.statistics.RobotWorkingHoursStatisticsService; import cn.iocoder.yudao.module.system.util.redis.RedisUtil; import cn.iocoder.yudao.module.system.util.redis.RedissonUtils; @@ -129,20 +132,8 @@ public class RobotTaskServiceImpl extends ServiceImpl laneIds = new ArrayList<>(); List areaIds = new ArrayList<>(); - if (ObjectUtil.isNotEmpty(task.getSkuInfo()) && checkSkuInfo) { + if (ObjectUtil.isNotEmpty(task.getSkuInfo()) && znConfigConstant.getTask().getCheckSkuInfo()) { List wareHouseLaneDOS = houseLaneMapper.selectList(new LambdaQueryWrapper() .eq(WareHouseLaneDO::getLaneMsg, task.getSkuInfo())); if (ObjectUtil.isNotEmpty(wareHouseLaneDOS)) { @@ -385,7 +380,7 @@ public class RobotTaskServiceImpl extends ServiceImpl taskDOS = taskMapper.selectList(new LambdaQueryWrapper() .in(RobotTaskDO::getTaskStatus, RobotTaskStatusEnum.NEW.getType(), RobotTaskStatusEnum.DOING.getType())); if (ObjectUtil.isNotEmpty(taskDOS)) { @@ -582,7 +585,7 @@ public class RobotTaskServiceImpl extends ServiceImpl newTaskDetailList = new ArrayList<>(); List mapItemIds = new ArrayList<>(); - if (doCycle) { + if (znConfigConstant.getDoCycle()) { List taskCycleDOS = taskCycleMapper.selectList(new LambdaQueryWrapper()); if (ObjectUtil.isNotEmpty(taskCycleDOS)) { mapItemIds = taskCycleDOS.stream().map(TaskCycleDO::getMapItemId).collect(Collectors.toList()); @@ -1008,7 +1013,7 @@ public class RobotTaskServiceImpl extends ServiceImpl(); } - if (doCycle) { + if (znConfigConstant.getDoCycle()) { List taskCycleDOS = taskCycleMapper.selectList(new LambdaQueryWrapper()); if (ObjectUtil.isNotEmpty(taskCycleDOS)) { List mapItemIds = @@ -1482,7 +1487,7 @@ public class RobotTaskServiceImpl extends ServiceImpl taskDetailDOS = taskDetailMapper.selectList(new LambdaQueryWrapperX() + .eq(RobotTaskDetailDO::getRobotNo, robotNo) + .ne(RobotTaskDetailDO::getTaskStatus, RobotTaskStatusEnum.NEW.getType())); + + return ObjectUtil.isEmpty(taskDetailDOS) ? 0 : taskDetailDOS.size(); + } + /** * 任务日志分页 * diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/robot/camera/RobotCameraServiceImpl.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/robot/camera/RobotCameraServiceImpl.java index 67593b3af..9b675e528 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/robot/camera/RobotCameraServiceImpl.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/robot/camera/RobotCameraServiceImpl.java @@ -1,6 +1,7 @@ package cn.iocoder.yudao.module.system.service.robot.camera; import cn.hutool.core.util.ObjectUtil; +import cn.iocoder.yudao.module.system.config.poperties.ZnConfigConstant; import cn.iocoder.yudao.module.system.controller.admin.robot.camera.RobotCameraAddVO; import cn.iocoder.yudao.module.system.controller.admin.robot.camera.RobotCameraPageReqVO; import cn.iocoder.yudao.module.system.controller.admin.robot.camera.RobotCameraRespVO; @@ -13,6 +14,7 @@ import cn.iocoder.yudao.module.system.util.aes.AESEncryptionUtil; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.google.common.collect.Sets; import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; @@ -45,8 +47,8 @@ public class RobotCameraServiceImpl extends ServiceImpl tasks, List taskDetails, Long positionMapItemId, String deviceNo) { RobotTaskDO task = new RobotTaskDO(); String incrementByKey = redisUtil.getIncrementByKey(RobotCacheLockEnum.CHARGE_TASK_NO.getKey()); - task.setTaskNo(chargeNo + DateUtils.getYearMonthDay() + incrementByKey); + task.setTaskNo(znConfigConstant.getChargeNo() + DateUtils.getYearMonthDay() + incrementByKey); task.setId(IdUtil.getSnowflakeNextId()); task.setCycleNumber(0L); task.setRemainingCycleNumber(0L); diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/robot/job/CycleServiceImpl.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/robot/job/CycleServiceImpl.java index 73d5aa55d..15c0586f2 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/robot/job/CycleServiceImpl.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/robot/job/CycleServiceImpl.java @@ -4,9 +4,11 @@ import cn.hutool.core.util.ObjectUtil; import cn.iocoder.yudao.framework.common.util.date.DateUtils; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder; +import cn.iocoder.yudao.module.system.config.poperties.ZnConfigConstant; import cn.iocoder.yudao.module.system.controller.admin.robot.vo.RobotTaskDetailAddVO; import cn.iocoder.yudao.module.system.dal.dataobject.robot.RobotTaskDO; import cn.iocoder.yudao.module.system.dal.dataobject.robot.RobotTaskDetailDO; +import cn.iocoder.yudao.module.system.dal.mysql.cycle.TaskCycleMapper; import cn.iocoder.yudao.module.system.dal.mysql.houselocation.WareHouseLocationMapper; import cn.iocoder.yudao.module.system.dal.mysql.robot.RobotTaskDetailMapper; import cn.iocoder.yudao.module.system.dal.mysql.robot.RobotTaskMapper; @@ -20,6 +22,7 @@ import cn.iocoder.yudao.module.system.util.redis.RedisUtil; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.google.common.collect.Lists; import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; @@ -45,11 +48,8 @@ public class CycleServiceImpl implements CycleService { @Resource private RobotTaskDetailMapper taskDetailMapper; - @Value("${zn.do_cycle:true}") - private Boolean doCycle; - - @Value("${zn.task-no:ZN}") - private String taskNo; + @Autowired + private ZnConfigConstant znConfigConstant; @Resource private RedisUtil redisUtil; @@ -59,6 +59,9 @@ public class CycleServiceImpl implements CycleService { @Resource private RobotTaskService robotTaskService; + + @Resource + private TaskCycleMapper taskCycleMapper; /** * 创建循环任务 */ @@ -66,7 +69,7 @@ public class CycleServiceImpl implements CycleService { public void cycleTaskJob() { TenantContextHolder.setTenantId(1L); - if (!doCycle) { + if (!znConfigConstant.getDoCycle()) { log.info("循环任务关闭了--不自动创建循环任务"); } @@ -86,11 +89,12 @@ public class CycleServiceImpl implements CycleService { Map> taskIdMap = detailDOS.stream().collect(Collectors.groupingBy(RobotTaskDetailDO::getRobotTaskId)); - String incrementByKey = redisUtil.getIncrementByKey(RobotCacheLockEnum.TASK_NO.getKey()); + List taskDOList = new ArrayList<>(); List taskDetailList = new LinkedList<>(); for (RobotTaskDO v : taskList) { + String incrementByKey = redisUtil.getIncrementByKey(RobotCacheLockEnum.TASK_NO.getKey()); RobotTaskDO taskData = getTaskData(incrementByKey, v); List taskDetailDOS = getTaskDetailData(taskData,taskIdMap,v.getId()); taskDOList.add(taskData); @@ -98,10 +102,21 @@ public class CycleServiceImpl implements CycleService { v.setRemainingCycleNumber(0l); } - taskMapper.insertBatch(taskDOList); + taskMapper.insert(taskDOList); taskMapper.updateById(taskList); - Collections.reverse(taskDetailList); - taskDetailMapper.insertBatch(taskDetailList); + + List moves = taskDetailList.stream().filter(v -> RobotTaskTypeEnum.MOVE_TO_POINT.getType().equals(v.getTaskType())).collect(Collectors.toList()); + List takes = taskDetailList.stream().filter(v -> !RobotTaskTypeEnum.MOVE_TO_POINT.getType().equals(v.getTaskType())).collect(Collectors.toList()); + List taskDetails= new LinkedList<>(); + if (ObjectUtil.isNotEmpty(moves)) { + taskDetails.addAll(moves); + } + if (ObjectUtil.isNotEmpty(takes)) { + Collections.reverse(takes); + taskDetails.addAll(takes); + } + + taskDetailMapper.insert(taskDetails); List fromLocationIds = taskDetailList.stream().map(RobotTaskDetailDO::getFromLocationId).collect(Collectors.toList()); List toLocationIds = taskDetailList.stream().map(RobotTaskDetailDO::getToLocationId).collect(Collectors.toList()); @@ -114,12 +129,13 @@ public class CycleServiceImpl implements CycleService { locationMapper.updateLocationLockList(list, -1l, LocationLockEnum.NO.getType()); }); - List bean = BeanUtils.toBean(taskDetailList, RobotTaskDetailAddVO.class); + List bean = BeanUtils.toBean(taskDetails, RobotTaskDetailAddVO.class); Map> taskDetailMap = bean.stream().collect(Collectors.groupingBy(RobotTaskDetailAddVO::getRobotTaskId)); taskDetailMap.forEach((k,v) ->{ robotTaskService.addCycle(k,v); }); + taskCycleMapper.deletByRobotTaskIds(taskIds); } private List getTaskDetailData(RobotTaskDO taskData, Map>> getLaneAutoMoveLocation(List taskDetailDOS) { List>> result = new ArrayList<>(); - if (ObjectUtil.isEmpty(taskDetailDOS) || !laneAutoMove) { + if (ObjectUtil.isEmpty(taskDetailDOS) || !znConfigConstant.getLaneAutoMove()) { log.info("没有线库的任务明细, 不需要执行线库移库"); return result; } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/robot/pathplanning/RobotPathPlanningServiceImpl.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/robot/pathplanning/RobotPathPlanningServiceImpl.java index b6cb0814e..1f8df07bd 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/robot/pathplanning/RobotPathPlanningServiceImpl.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/robot/pathplanning/RobotPathPlanningServiceImpl.java @@ -10,6 +10,8 @@ import cn.iocoder.yudao.module.mqtt.api.common.CommonApi; import cn.iocoder.yudao.module.mqtt.api.path.task.TaskLimitationAreaDTO; import cn.iocoder.yudao.module.mqtt.api.path.task.TaskRobotNoLimittationAreaDTO; import cn.iocoder.yudao.module.mqtt.api.path.task.TaskToPathPlanningDTO; +import cn.iocoder.yudao.module.system.config.mqtt.util.MqttUtils; +import cn.iocoder.yudao.module.system.config.poperties.ZnConfigConstant; import cn.iocoder.yudao.module.system.constant.path.PathPlanningChcheConstant; import cn.iocoder.yudao.module.system.constant.path.PathPlanningTopicConstant; import cn.iocoder.yudao.module.system.constant.robot.RobotStatusCodeConstant; @@ -68,12 +70,6 @@ public class RobotPathPlanningServiceImpl implements RobotPathPlanningService { @Resource private PositionMapItemMapper positionMapItemMapper; - @Value("${zn.task_need_single:true}") - private Boolean taskNeedSingle; - - @Value("${zn.location_number_reduce:100000000}") - private Long locationNumberReduce; - @Resource private WareHouseLocationMapper locationMapper; @@ -86,29 +82,17 @@ public class RobotPathPlanningServiceImpl implements RobotPathPlanningService { @Resource private PositionMapMapper positionMapMapper; - @Value("${zn.robot_chearg.release_location_number_config:50}") - private Long releaseLocationNumberConfig; - - @Value("${zn.robot_chearg.priority_config:50}") - private Long priorityConfig; - - @Value("${zn.robot_config.offset_height}") - private Double offsetHeight; - - @Value("${zn.path_planning.task_chche_time:604800}") - private Long taskChcheTime; - - @Value("${zn.move-no:MOVE}") - private String moveTaskNo; - - @Value("${zn.robot_config.default_tray_height:0.82}") - private Double defaultTrayHeight; + @Autowired + private ZnConfigConstant znConfigConstant; @Autowired private RobotTaskMapper robotTaskMapper; - @Resource - private CommonApi commonApi; + /*@Resource + private CommonApi commonApi;*/ + + @Autowired + private MqttUtils mqttUtils; @Resource @Lazy @@ -137,7 +121,7 @@ public class RobotPathPlanningServiceImpl implements RobotPathPlanningService { List taskDetailDOS = robotAndTaskDetails.getRight(); if (ObjectUtil.isEmpty(taskDetailDOS)) { log.info("--不存在需要执行的任务--派车辆去等待点"); - moveRobotToWait(robots); +// moveRobotToWait(robots); return; } @@ -148,7 +132,8 @@ public class RobotPathPlanningServiceImpl implements RobotPathPlanningService { return; } - log.info("-------查找到车子和任务------"); + log.info("-------可以分配任务的车辆编号------ ,:{}",JSON.toJSONString(robots.stream().map(RobotInformationDO::getRobotNo).collect(Collectors.toList()))); + log.info("-------需要执行的任务id------ ,:{}",JSON.toJSONString(taskDetailDOS.stream().map(RobotTaskDetailDO::getId).collect(Collectors.toList()))); distributeTasksToPP(robots, taskDetailDOS); } @@ -205,6 +190,8 @@ public class RobotPathPlanningServiceImpl implements RobotPathPlanningService { return; } + Map sortMap = positionMapItems.stream().collect(Collectors.toMap(PositionMapItemDO::getId, PositionMapItemDO::getSortNum)); + List inStopPointRobotNos = new ArrayList<>(); for (PositionMapItemDO positionMapItem : positionMapItems) { if (UseStatusEnum.USEING.getType().equals(positionMapItem.getUseStatus()) && ObjectUtil.isNotEmpty(positionMapItem.getRobotNo())) { @@ -285,8 +272,6 @@ public class RobotPathPlanningServiceImpl implements RobotPathPlanningService { return; } - Map sortMap = positionMapItems.stream().collect(Collectors.toMap(PositionMapItemDO::getId, PositionMapItemDO::getSortNum)); - //机器人不能行走的区域 List robotNoLimitationArea = getRobotNoLimitationArea(robots); Map robotNoLimittationAreaDTOMap = @@ -301,7 +286,7 @@ public class RobotPathPlanningServiceImpl implements RobotPathPlanningService { RobotTaskDO task = new RobotTaskDO(); String incrementByKey = redisUtil.getIncrementByKey(RobotCacheLockEnum.MOVE_TASK_NO.getKey()); - task.setTaskNo(moveTaskNo + DateUtils.getYearMonthDay() + incrementByKey); + task.setTaskNo(znConfigConstant.getMoveNo() + DateUtils.getYearMonthDay() + incrementByKey); task.setId(IdUtil.getSnowflakeNextId()); task.setCycleNumber(0L); task.setRemainingCycleNumber(0L); @@ -332,7 +317,7 @@ public class RobotPathPlanningServiceImpl implements RobotPathPlanningService { pathPlanning.setRobotNoLimitationAreaDTOS(robotNoLimitions); String key = PathPlanningChcheConstant.PATH_PLANNING_TASK + pathPlanning.getOrderId(); - redisUtil.set(key, JSON.toJSONString(pathPlanning), taskChcheTime); + redisUtil.set(key, JSON.toJSONString(pathPlanning), znConfigConstant.getTask().getTaskCacheTime()); pathPlanningList.add(pathPlanning); } @@ -344,7 +329,8 @@ public class RobotPathPlanningServiceImpl implements RobotPathPlanningService { positionMapItemMapper.updateById(robotMapItems); log.info("派车去停车点--任务下发给PP :{}", JSON.toJSONString(pathPlanningList)); - commonApi.commonMethod(pathPlanningList, PathPlanningTopicConstant.TASK_ASSIGNMENT_REQUEST); +// commonApi.commonMethod(pathPlanningList, PathPlanningTopicConstant.TASK_ASSIGNMENT_REQUEST); + mqttUtils.pub(PathPlanningTopicConstant.TASK_ASSIGNMENT_REQUEST,JSON.toJSONString(pathPlanningList)); } @@ -369,7 +355,7 @@ public class RobotPathPlanningServiceImpl implements RobotPathPlanningService { for (RobotChargeLogDO v : logs) { - Long priority = priorityConfig; + Long priority = znConfigConstant.getRobotCharge().getPriorityConfig(); LocalDateTime createTime = LocalDateTime.now(); if (ObjectUtil.isEmpty(ChargeModelEnum.TASK.getType().equals(v.getChargeModel())) && ObjectUtil.isNotEmpty(v.getTaskDetailId()) @@ -396,17 +382,18 @@ public class RobotPathPlanningServiceImpl implements RobotPathPlanningService { pathPlanning.setTaskType(taskType); pathPlanning.setReleaseGroupId("POINT_" + v.getPositionMapItemId()); - pathPlanning.setReleaseLocationNumber(releaseLocationNumberConfig); + pathPlanning.setReleaseLocationNumber(znConfigConstant.getRobotCharge().getReleaseLocationNumberConfig()); pathPlanning.setWaitIds(Collections.singletonList(v.getPositionMapItemId() + "")); String key = PathPlanningChcheConstant.PATH_PLANNING_TASK + pathPlanning.getOrderId(); - redisUtil.set(key, JSON.toJSONString(pathPlanning), taskChcheTime); + redisUtil.set(key, JSON.toJSONString(pathPlanning), znConfigConstant.getTask().getTaskCacheTime()); pathPlanningList.add(pathPlanning); } log.info("充电任务下发给PP :{}", JSON.toJSONString(pathPlanningList)); - commonApi.commonMethod(pathPlanningList, PathPlanningTopicConstant.TASK_ASSIGNMENT_REQUEST); +// commonApi.commonMethod(pathPlanningList, PathPlanningTopicConstant.TASK_ASSIGNMENT_REQUEST); + mqttUtils.pub(PathPlanningTopicConstant.TASK_ASSIGNMENT_REQUEST,JSON.toJSONString(pathPlanningList)); } @Transactional(rollbackFor = Exception.class) @@ -484,20 +471,21 @@ public class RobotPathPlanningServiceImpl implements RobotPathPlanningService { String cargoDetectedKey = RobotTaskChcheConstant.ROBOT_CARGO_DETECTED + mac; Object cargoDetected = redisUtil.get(cargoDetectedKey); log.info("传感器是否按下 :{}", cargoDetected); - if (ObjectUtil.isEmpty(cargoDetected) || (RobotStatusCodeConstant.CARGO_DETECTED.equals(Boolean.parseBoolean(String.valueOf(cargoDetected))) + /* if (ObjectUtil.isNotEmpty(cargoDetected) && (RobotStatusCodeConstant.CARGO_DETECTED.equals(Boolean.parseBoolean(String.valueOf(cargoDetected))) && !RobotTaskTypeEnum.RELEASE.getType().equals(taskDetailDO.getTaskType()))) { log.info("车机上报传感器为空, 或者 被按下且任务非仅放货任务 :{} ,任务id :{}", taskDetailDO.getRobotNo(), taskDetailDO.getId()); continue; - } else if (!RobotStatusCodeConstant.CARGO_DETECTED.equals(Boolean.parseBoolean(String.valueOf(cargoDetected))) + } else if (ObjectUtil.isNotEmpty(cargoDetected) && !RobotStatusCodeConstant.CARGO_DETECTED.equals(Boolean.parseBoolean(String.valueOf(cargoDetected))) && RobotTaskTypeEnum.RELEASE.getType().equals(taskDetailDO.getTaskType())) { log.info("仅放货任务,传感器未被按下,所以不执行任务 :{}, 任务id :{}", taskDetailDO.getRobotNo(), taskDetailDO.getId()); continue; - } + }*/ List robotNoLimitions = null; if (ObjectUtil.isEmpty(taskDetailDO.getRobotNo())) { robotNoLimitions = robotNoLimitationArea; } else { + log.info("区域 :{}",JSON.toJSONString(robotDoReleaseMap)); TaskRobotNoLimittationAreaDTO taskRobotNoLimittationAreaDTO = robotDoReleaseMap.get(taskDetailDO.getRobotNo()); if (ObjectUtil.isEmpty(taskRobotNoLimittationAreaDTO)) { log.info("车辆没有能行走的区域 :{}", taskDetailDO.getRobotNo()); @@ -516,12 +504,12 @@ public class RobotPathPlanningServiceImpl implements RobotPathPlanningService { WareHouseLocationDO toLocation = locationDOMap.get(taskDetailDO.getToLocationId()); if (ObjectUtil.isNotEmpty(taskDetailDO.getFromLocationId())) { - pathPlanning.setTakeLocationNumber(Math.abs(locationNumberReduce - taskDetailDO.getFromLocationNumber())); + pathPlanning.setTakeLocationNumber(Math.abs(znConfigConstant.getLocationNumberReduce() - taskDetailDO.getFromLocationNumber())); pathPlanning.setTakePointId(fromLocation.getMapItemId()); pathPlanningSetTakeHeight(pathPlanning, fromLocation); pathPlanning.setTakeLevel(fromLocation.getLocationStorey()); - pathPlanning.setTakeOffsetHeight(offsetHeight); + pathPlanning.setTakeOffsetHeight(znConfigConstant.getRobotConfig().getOffsetHeight()); if (ObjectUtil.isNotEmpty(taskDetailDO.getFromLaneId())) { pathPlanning.setTakeGroupId("LINE_" + taskDetailDO.getFromLaneId()); } else { @@ -535,7 +523,7 @@ public class RobotPathPlanningServiceImpl implements RobotPathPlanningService { pathPlanningSetReleaseHeight(pathPlanning, toLocation); pathPlanning.setReleaseLevel(toLocation.getLocationStorey()); - pathPlanning.setReleaseOffsetHeight(offsetHeight); + pathPlanning.setReleaseOffsetHeight(znConfigConstant.getRobotConfig().getOffsetHeight()); if (ObjectUtil.isNotEmpty(taskDetailDO.getToLaneId())) { pathPlanning.setReleaseGroupId("LINE_" + taskDetailDO.getToLaneId()); } else { @@ -544,14 +532,15 @@ public class RobotPathPlanningServiceImpl implements RobotPathPlanningService { } String key = PathPlanningChcheConstant.PATH_PLANNING_TASK + pathPlanning.getOrderId(); - redisUtil.set(key, JSON.toJSONString(pathPlanning), taskChcheTime); + redisUtil.set(key, JSON.toJSONString(pathPlanning), znConfigConstant.getTask().getTaskCacheTime()); pathPlanningList.add(pathPlanning); } if (ObjectUtil.isNotEmpty(pathPlanningList)) { - log.info("作业任务下发给PP :{}", JSON.toJSONString(pathPlanningList)); - commonApi.commonMethod(pathPlanningList, PathPlanningTopicConstant.TASK_ASSIGNMENT_REQUEST); + log.info("111111作业任务下发给PP :{}", JSON.toJSONString(pathPlanningList)); +// commonApi.commonMethod(pathPlanningList, PathPlanningTopicConstant.TASK_ASSIGNMENT_REQUEST); + mqttUtils.pub(PathPlanningTopicConstant.TASK_ASSIGNMENT_REQUEST,JSON.toJSONString(pathPlanningList)); } } @@ -567,18 +556,18 @@ public class RobotPathPlanningServiceImpl implements RobotPathPlanningService { return; } - WareHouseLocationDO nextLocation = locationMapper.selectOne(new LambdaQueryWrapperX() + /*WareHouseLocationDO nextLocation = locationMapper.selectOne(new LambdaQueryWrapperX() .eq(WareHouseLocationDO::getId, toLocation.getMapItemId()) .eq(WareHouseLocationDO::getLocationStorey, toLocation.getLocationStorey() - 1) .last("limit 1")); if (ObjectUtil.isNotEmpty(nextLocation) && ObjectUtil.isNotEmpty(nextLocation.getLocationTotalHeight())) { pathPlanning.setReleaseHeight(Double.valueOf(nextLocation.getLocationTotalHeight() + "")); return; - } + }*/ Integer locationStorey = toLocation.getLocationStorey() - 1; - double height = locationStorey * defaultTrayHeight; - log.info("放货设置默认高度 :{}", pathPlanning.getReleaseHeight()); + double height = locationStorey * znConfigConstant.getRobotConfig().getDefaultTrayHeight(); + log.info("放货设置默认高度 :{}", height); pathPlanning.setReleaseHeight(height); } @@ -589,12 +578,12 @@ public class RobotPathPlanningServiceImpl implements RobotPathPlanningService { * @param fromLocation */ private void pathPlanningSetTakeHeight(TaskToPathPlanningDTO pathPlanning, WareHouseLocationDO fromLocation) { - if (ObjectUtil.isNotEmpty(fromLocation.getLocationTotalHeight())) { + /*if (ObjectUtil.isNotEmpty(fromLocation.getLocationTotalHeight())) { pathPlanning.setTakeHeight(Double.valueOf(fromLocation.getLocationTotalHeight() + "")); return; - } + }*/ Integer locationStorey = fromLocation.getLocationStorey(); - double height = locationStorey * defaultTrayHeight; + double height = locationStorey * znConfigConstant.getRobotConfig().getDefaultTrayHeight(); log.info("取货设置默认取货高度 :{}", height); pathPlanning.setTakeHeight(height); } @@ -699,7 +688,7 @@ public class RobotPathPlanningServiceImpl implements RobotPathPlanningService { */ private List getSingleTask(List taskDetailDOS) { //剔除目前正在做的线库和点位 - if (!taskNeedSingle) { + if (!znConfigConstant.getTaskNeedSingle()) { return taskDetailDOS; } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/robot/simulation/RobotSimulationService.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/robot/simulation/RobotSimulationService.java new file mode 100644 index 000000000..5e7335c0f --- /dev/null +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/robot/simulation/RobotSimulationService.java @@ -0,0 +1,8 @@ +package cn.iocoder.yudao.module.system.service.robot.simulation; + +import cn.iocoder.yudao.module.system.controller.admin.robot.vo.RobotTaskSaveReqVO; + +public interface RobotSimulationService { + + void createTask(RobotTaskSaveReqVO createReqVO); +} diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/robot/simulation/RobotSimulationServiceImpl.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/robot/simulation/RobotSimulationServiceImpl.java new file mode 100644 index 000000000..b92d914f6 --- /dev/null +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/robot/simulation/RobotSimulationServiceImpl.java @@ -0,0 +1,504 @@ +package cn.iocoder.yudao.module.system.service.robot.simulation; + +import cn.hutool.core.util.ObjectUtil; +import cn.iocoder.yudao.framework.common.util.date.DateUtils; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.mqtt.api.common.CommonApi; +import cn.iocoder.yudao.module.system.config.poperties.ZnConfigConstant; +import cn.iocoder.yudao.module.system.controller.admin.robot.vo.RobotInformationPageReqVO; +import cn.iocoder.yudao.module.system.controller.admin.robot.vo.RobotTaskDetailAddVO; +import cn.iocoder.yudao.module.system.controller.admin.robot.vo.RobotTaskSaveReqVO; +import cn.iocoder.yudao.module.system.dal.dataobject.cycle.TaskCycleDO; +import cn.iocoder.yudao.module.system.dal.dataobject.housearea.HouseAreaDO; +import cn.iocoder.yudao.module.system.dal.dataobject.houselane.WareHouseLaneDO; +import cn.iocoder.yudao.module.system.dal.dataobject.houselocation.WareHouseLocationDO; +import cn.iocoder.yudao.module.system.dal.dataobject.positionmap.PositionMapItemDO; +import cn.iocoder.yudao.module.system.dal.dataobject.robot.RobotInformationDO; +import cn.iocoder.yudao.module.system.dal.dataobject.robot.RobotTaskDO; +import cn.iocoder.yudao.module.system.dal.dataobject.robot.RobotTaskDetailDO; +import cn.iocoder.yudao.module.system.dal.mysql.cycle.TaskCycleMapper; +import cn.iocoder.yudao.module.system.dal.mysql.housearea.HouseAreaMapper; +import cn.iocoder.yudao.module.system.dal.mysql.houselane.WareHouseLaneMapper; +import cn.iocoder.yudao.module.system.dal.mysql.houselocation.WareHouseLocationMapper; +import cn.iocoder.yudao.module.system.dal.mysql.information.DeviceInformationMapper; +import cn.iocoder.yudao.module.system.dal.mysql.log.RobotTaskDetailActionLogMapper; +import cn.iocoder.yudao.module.system.dal.mysql.robot.RobotChargeLogMapper; +import cn.iocoder.yudao.module.system.dal.mysql.robot.RobotInformationMapper; +import cn.iocoder.yudao.module.system.dal.mysql.robot.RobotTaskDetailMapper; +import cn.iocoder.yudao.module.system.dal.mysql.robot.RobotTaskMapper; +import cn.iocoder.yudao.module.system.enums.redis.RobotCacheLockEnum; +import cn.iocoder.yudao.module.system.enums.robot.LocationEnableEnum; +import cn.iocoder.yudao.module.system.enums.robot.LocationLockEnum; +import cn.iocoder.yudao.module.system.enums.robot.LocationUseStatusEnum; +import cn.iocoder.yudao.module.system.enums.robot.MoveAllEnum; +import cn.iocoder.yudao.module.system.enums.robot.ReleaseTakeEnum; +import cn.iocoder.yudao.module.system.enums.robot.RobotTaskTypeEnum; +import cn.iocoder.yudao.module.system.service.information.DeviceInformationService; +import cn.iocoder.yudao.module.system.service.log.RobotTaskDetailActionLogService; +import cn.iocoder.yudao.module.system.service.log.UserOperationLogService; +import cn.iocoder.yudao.module.system.service.positionmap.PositionMapItemService; +import cn.iocoder.yudao.module.system.service.robot.RobotInformationService; +import cn.iocoder.yudao.module.system.service.robot.RobotTaskDetailService; +import cn.iocoder.yudao.module.system.service.statistics.RobotWorkingHoursStatisticsService; +import cn.iocoder.yudao.module.system.util.redis.RedisUtil; +import cn.iocoder.yudao.module.system.util.redis.RedissonUtils; +import com.alibaba.fastjson.JSON; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.google.common.collect.Lists; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.validation.annotation.Validated; + +import javax.annotation.Resource; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception0; +import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.TASK_CREATE_FAIL; + +@Slf4j +@Service +@Validated +public class RobotSimulationServiceImpl implements RobotSimulationService{ + + @Resource + private RobotTaskMapper taskMapper; + + @Resource + private WareHouseLocationMapper locationMapper; + + @Resource + private RedisUtil redisUtil; + + @Resource + private RobotTaskDetailMapper taskDetailMapper; + + @Resource + private RobotTaskDetailService robotTaskDetailService; + + @Resource + private RobotInformationMapper informationMapper; + + @Resource + private WareHouseLaneMapper houseLaneMapper; + + @Resource + private HouseAreaMapper houseAreaMapper; + + @Resource + private PositionMapItemService positionMapItemService; + + @Autowired + private ZnConfigConstant znConfigConstant; + + @Override + public void createTask(RobotTaskSaveReqVO createReqVO) { + + //设置任务号 + if (ObjectUtil.isEmpty(createReqVO.getTaskNo())) { + String incrementByKey = redisUtil.getIncrementByKey(RobotCacheLockEnum.TASK_NO.getKey()); + createReqVO.setTaskNo(znConfigConstant.getTaskNo() + DateUtils.getYearMonthDay() + incrementByKey); + } + + log.info("111111创建一个不校验的任务 :{}",createReqVO.getTaskNo()); + + RobotTaskDO task = BeanUtils.toBean(createReqVO, RobotTaskDO.class); + task.setRemainingCycleNumber(task.getCycleNumber()); + taskMapper.insert(task); + + List laneIds = new ArrayList<>(); + List areaIds = new ArrayList<>(); + if (ObjectUtil.isNotEmpty(task.getSkuInfo()) && znConfigConstant.getTask().getCheckSkuInfo()) { + List wareHouseLaneDOS = houseLaneMapper.selectList(new LambdaQueryWrapper() + .eq(WareHouseLaneDO::getLaneMsg, task.getSkuInfo())); + if (ObjectUtil.isNotEmpty(wareHouseLaneDOS)) { + laneIds = wareHouseLaneDOS.stream().map(WareHouseLaneDO::getId).collect(Collectors.toList()); + } + List houseAreaDOS = houseAreaMapper.selectList(new LambdaQueryWrapper() + .eq(HouseAreaDO::getSkuInfo, task.getSkuInfo())); + if (ObjectUtil.isNotEmpty(houseAreaDOS)) { + areaIds = houseAreaDOS.stream().map(HouseAreaDO::getId).collect(Collectors.toList()); + } + } + + //查找库位 + List locationIds = new ArrayList<>(); + if (MoveAllEnum.NO.getType().equals(createReqVO.getDoMoveAll())) { + locationIds = setSingleLocationIdNo(createReqVO.getTaskDetailList(), task, laneIds, areaIds); + } else { + locationIds = setAllLocationIdNo(createReqVO, task.getId(), laneIds, areaIds, task.getSkuInfo()); + } + + // 插入 + createReqVO.getTaskDetailList() + .forEach(taskDetail -> { + taskDetail.setRobotTaskId(task.getId()); + }); + robotTaskDetailService.insertRobotDetailList(createReqVO.getTaskDetailList()); + + List> fromPartition = Lists.partition(locationIds, 100); + fromPartition.forEach(list -> { + locationMapper.updateLocationLockList(list, task.getId(), LocationLockEnum.NO.getType()); + }); + + } + + @Transactional(rollbackFor = Exception.class) + public List setSingleLocationIdNo(List taskDetailList, RobotTaskDO task, + List laneIds, List areaIds) { + //取货中的map_item_id, 此集合不能执行放货的任务 + List takeMapItemIds = taskDetailMapper.selectTakeMapItemIds(); + if (ObjectUtil.isEmpty(takeMapItemIds)) { + takeMapItemIds = new ArrayList<>(); + } + //放货中的map_item_id, 此集合不能执行取货的任务 + List releaseMapItemIds = taskDetailMapper.selectReleaseMapItemIds(); + if (ObjectUtil.isEmpty(releaseMapItemIds)) { + releaseMapItemIds = new ArrayList<>(); + } + + List locationIds = new ArrayList<>(); + Set chooseLocationIds = new HashSet<>(); + + for (RobotTaskDetailAddVO robotTaskVo : taskDetailList) { + robotTaskVo.setRobotTaskId(task.getId()); + robotTaskVo.setPriority(task.getPriority()); + RobotTaskTypeEnum robotTaskType = RobotTaskTypeEnum.getRobotTaskType(robotTaskVo.getTaskType()); + switch (robotTaskType) { + case TAKE_RELEASE: + doTakeRelease(robotTaskVo, locationIds, takeMapItemIds, releaseMapItemIds, laneIds, areaIds, task.getSkuInfo(), chooseLocationIds); + break; + case PARK: + doPark(robotTaskVo, locationIds, takeMapItemIds, releaseMapItemIds); + break; + case CHARGE: + doCharge(robotTaskVo, takeMapItemIds, releaseMapItemIds); + break; + case MOVE: + doMove(robotTaskVo, locationIds, takeMapItemIds, releaseMapItemIds); + break; + case TAKE: + doTake(robotTaskVo, locationIds, takeMapItemIds, releaseMapItemIds, chooseLocationIds); + break; + case RELEASE: + doRelease(robotTaskVo, locationIds, takeMapItemIds, releaseMapItemIds, laneIds, areaIds, task.getSkuInfo(), chooseLocationIds); + break; + case SCAN: + //暂无此功能 + doScan(robotTaskVo, locationIds, takeMapItemIds, releaseMapItemIds); + break; + case DETECTING_TRAYS: + //暂无此功能 + doDetectingTrays(robotTaskVo, locationIds, takeMapItemIds, releaseMapItemIds); + break; + case MOVE_TO_POINT: + doMoveToPoint(robotTaskVo); + break; + default: + log.error("任务类型不存在 "); + throw exception0(TASK_CREATE_FAIL.getCode(), "任务类型不存在"); + } + } + return locationIds; + } + + + public void doTakeRelease(RobotTaskDetailAddVO robotTaskVo, List locationIds, + List takeMapItemIds, List releaseMapItemIds, + List laneIds, List areaIds, String skuInfo, Set chooseLocationIds) { + + + //校验放货库位 + setToLocation(robotTaskVo, null, locationIds, takeMapItemIds, releaseMapItemIds, laneIds, areaIds, skuInfo, chooseLocationIds); + locationIds.add(robotTaskVo.getToLocationId()); + + //校验取货库位 + setFromLocation(robotTaskVo, null, locationIds, takeMapItemIds, releaseMapItemIds, chooseLocationIds); + locationIds.add(robotTaskVo.getFromLocationId()); + + //验证取货库位是否存在未完成的任务 + Set set = new HashSet<>(); + set.add(robotTaskVo.getFromLocationId()); + } + + /** + * 移动到指定点位 + * + * @param robotTaskVo + */ + private void doMoveToPoint(RobotTaskDetailAddVO robotTaskVo) { + PositionMapItemDO positionMapItem = positionMapItemService.getPositionMapItem(robotTaskVo.getReleaseId()); + robotTaskVo.setToLocationNo(String.valueOf(positionMapItem.getSortNum())); + } + + /** + * 检测托盘类型 + * + * @param robotTaskVo + */ + @Transactional(rollbackFor = Exception.class) + public void doDetectingTrays(RobotTaskDetailAddVO robotTaskVo, List locationIds, List takeMapItemIds, + List releaseMapItemIds) { + /*setToLocation(robotTaskVo,getMapIdsByRobotNo(robotTaskVo.getRobotNo()),new ArrayList<>()); + locationIds.add(robotTaskVo.getToLocationId());*/ + } + + /** + * 扫描码 + * + * @param robotTaskVo + */ + @Transactional(rollbackFor = Exception.class) + public void doScan(RobotTaskDetailAddVO robotTaskVo, List locationIds, List takeMapItemIds, + List releaseMapItemIds) { + /*setToLocation(robotTaskVo,getMapIdsByRobotNo(robotTaskVo.getRobotNo()),new ArrayList<>()); + locationIds.add(robotTaskVo.getToLocationId());*/ + } + + /** + * 仅放货 + * + * @param robotTaskVo + */ + @Transactional(rollbackFor = Exception.class) + public void doRelease(RobotTaskDetailAddVO robotTaskVo, List locationIds, List takeMapItemIds, + List releaseMapItemIds, List laneIds, List areaIds, String skuInfo, + Set chooseLocationIds) { + setToLocation(robotTaskVo, null, locationIds, takeMapItemIds, + releaseMapItemIds, laneIds, areaIds, skuInfo, chooseLocationIds); + locationIds.add(robotTaskVo.getToLocationId()); + } + + public void setFromLocation(RobotTaskDetailAddVO robotTaskVo, Set mapIds, List locationIds, + List takeMapItemIds, List releaseMapItemIds, Set chooseLocationIds) { + if (ReleaseTakeEnum.TO_LOCATION.getType().equals(robotTaskVo.getTakeType())) { + WareHouseLocationDO query = WareHouseLocationDO.builder().id(robotTaskVo.getTakeId()).build(); + WareHouseLocationDO locationDO = locationMapper.queryAllByLimit(query); + robotTaskVo.setFromLocationNo(locationDO.getLocationNo()); + robotTaskVo.setFromLocationId(robotTaskVo.getTakeId()); + robotTaskVo.setFromLocationStorey(locationDO.getLocationStorey()); + robotTaskVo.setFromLaneId(locationDO.getLaneId()); + robotTaskVo.setFromLocationNumber(locationDO.getLocationNumber()); + robotTaskVo.setFromMapItemId(locationDO.getMapItemId()); + takeMapItemIds.add(locationDO.getMapItemId()); + } else { + WareHouseLocationDO wareHouseLocationDO = + locationMapper.selectByTypeAndId(LocationUseStatusEnum.YES.getType(), robotTaskVo.getTakeType(), + robotTaskVo.getTakeId(), locationIds, null, releaseMapItemIds, new ArrayList<>(), new ArrayList<>()); + robotTaskVo.setFromLocationNo(wareHouseLocationDO.getLocationNo()); + robotTaskVo.setFromLocationId(wareHouseLocationDO.getId()); + robotTaskVo.setFromLocationStorey(wareHouseLocationDO.getLocationStorey()); + robotTaskVo.setFromLaneId(wareHouseLocationDO.getLaneId()); + robotTaskVo.setFromLocationNumber(wareHouseLocationDO.getLocationNumber()); + robotTaskVo.setFromMapItemId(wareHouseLocationDO.getMapItemId()); + takeMapItemIds.add(wareHouseLocationDO.getMapItemId()); + } + } + + /** + * 仅取货 + * + * @param robotTaskVo + */ + @Transactional(rollbackFor = Exception.class) + public void doTake(RobotTaskDetailAddVO robotTaskVo, List locationIds, List takeMapItemIds, + List releaseMapItemIds, Set chooseLocationIds) { + + setFromLocation(robotTaskVo, null, locationIds, takeMapItemIds, releaseMapItemIds, chooseLocationIds); + locationIds.add(robotTaskVo.getFromLocationId()); + } + + public Set getMapIdsByRobotNo(String robotNo) { + if (ObjectUtil.isNotEmpty(robotNo)) { + RobotInformationPageReqVO pageReqVO = new RobotInformationPageReqVO(); + pageReqVO.setRobotNo(robotNo); + return informationMapper.selectPage(pageReqVO).getList() + .stream() + .findFirst() + .map(RobotInformationDO::getFloorAreaJson) + .orElse(new HashSet<>()); + } + return new HashSet<>(); + } + + /** + * 移动 + * + * @param robotTaskVo + */ + @Transactional(rollbackFor = Exception.class) + public void doMove(RobotTaskDetailAddVO robotTaskVo, List locationIds, List takeMapItemIds, + List releaseMapItemIds) { + setToLocation(robotTaskVo, null, locationIds, takeMapItemIds, releaseMapItemIds, + null, null, null, null); + locationIds.add(robotTaskVo.getToLocationId()); + } + + /** + * 充电 + * + * @param robotTaskVo + */ + @Transactional(rollbackFor = Exception.class) + public void doCharge(RobotTaskDetailAddVO robotTaskVo, List takeMapItemIds, + List releaseMapItemIds) { + + } + + /** + * 停车 + * + * @param robotTaskVo + */ + @Transactional(rollbackFor = Exception.class) + public void doPark(RobotTaskDetailAddVO robotTaskVo, List locationIds, List takeMapItemIds, + List releaseMapItemIds) { + // todo 停车后续停到等待点 + /*setToLocation(robotTaskVo,getMapIdsByRobotNo(robotTaskVo.getRobotNo()),locationIds); + locationIds.add(robotTaskVo.getToLocationId());*/ + } + + + /** + * 设置放货和取货的id + * + * @param createReqVO + * @param taskId + */ + @Transactional(rollbackFor = Exception.class) + public List setAllLocationIdNo(RobotTaskSaveReqVO createReqVO, Long taskId, + List laneIds, List areaIds, String skuInfo) { + List taskDetailList = createReqVO.getTaskDetailList(); + + List newTaskDetailList = new ArrayList<>(); + List mapItemIds = new ArrayList<>(); + + //被此次任务锁定的空库位id + List toLocationIds = new ArrayList<>(); + //被此次任务锁定的有货库位id + List fromLocationIds = new ArrayList<>(); + for (RobotTaskDetailAddVO robotTaskVo : taskDetailList) { + Set mapIds = new HashSet<>(); + + //查找有货且非锁定的库位 + WareHouseLocationDO query = null; + if (ReleaseTakeEnum.TO_LANE.getType().equals(robotTaskVo.getTakeType())) { + query = WareHouseLocationDO.builder() + .laneId(robotTaskVo.getTakeId()) + .build(); + } else if (ReleaseTakeEnum.TO_AREA.getType().equals(robotTaskVo.getTakeType())) { + query = WareHouseLocationDO.builder() + .areaId(robotTaskVo.getTakeId()) + .build(); + } + + List stockList = locationMapper.selectLocations(query, toLocationIds, mapIds, + new ArrayList<>(), new ArrayList<>(), new ArrayList<>()); + if (ObjectUtil.isEmpty(stockList)) { + log.error("取货线库/区域为空或者已锁定或者机器人取放货区域受限制 :{}", robotTaskVo.toString()); + throw exception0(TASK_CREATE_FAIL.getCode(), "取货线库/区域为空或者已锁定或者机器人取放货区域受限制"); + } + + //查找空库位 + WareHouseLocationDO releaseQuery = null; + if (ReleaseTakeEnum.TO_LANE.getType().equals(robotTaskVo.getReleaseType())) { + releaseQuery = WareHouseLocationDO.builder() + .laneId(robotTaskVo.getReleaseId()) + .build(); + } else if (ReleaseTakeEnum.TO_AREA.getType().equals(robotTaskVo.getReleaseType())) { + releaseQuery = WareHouseLocationDO.builder() + .areaId(robotTaskVo.getReleaseId()) + .build(); + } + + List releaseStockList = locationMapper.selectLocations(releaseQuery, toLocationIds, mapIds, + laneIds, areaIds, mapItemIds); + if (ObjectUtil.isEmpty(releaseStockList) || releaseStockList.size() < stockList.size()) { + log.error("放货线库/区域库位数量不足或者机器人取放货区域受限制 :{}", robotTaskVo.toString()); + throw exception0(TASK_CREATE_FAIL.getCode(), "放货线库/区域库位数量不足或者机器人取放货区域受限制"); + } + Collections.reverse(releaseStockList); + //赋值数据 + List addTaskDetailList = getTaskDatail(stockList, releaseStockList, toLocationIds, + robotTaskVo, taskId, fromLocationIds); + newTaskDetailList.addAll(addTaskDetailList); + + } + createReqVO.setTaskDetailList(newTaskDetailList); + + if (ObjectUtil.isNotEmpty(fromLocationIds)) { + toLocationIds.addAll(fromLocationIds); + } + return toLocationIds; + } + + private List getTaskDatail(List stockList, + List releaseStockList, + List toLocationIds, RobotTaskDetailAddVO robotTaskVo, + Long taskId, List fromLocationIds) { + List addTaskDetailList = new ArrayList<>(); + for (int i = 0; i < stockList.size(); i++) { + RobotTaskDetailAddVO robotTaskDetailAddVo = new RobotTaskDetailAddVO(); + robotTaskDetailAddVo.setTaskType(robotTaskVo.getTaskType()); + robotTaskDetailAddVo.setReleaseType(robotTaskVo.getReleaseType()); + robotTaskDetailAddVo.setTakeType(robotTaskVo.getTakeType()); + robotTaskDetailAddVo.setTakeId(robotTaskVo.getTakeId()); + robotTaskDetailAddVo.setReleaseId(robotTaskVo.getReleaseId()); + robotTaskDetailAddVo.setRobotNo(robotTaskVo.getRobotNo()); + robotTaskDetailAddVo.setFromLocationNo(stockList.get(i).getLocationNo()); + robotTaskDetailAddVo.setFromLocationId(stockList.get(i).getId()); + robotTaskDetailAddVo.setToLocationNo(releaseStockList.get(i).getLocationNo()); + robotTaskDetailAddVo.setToLocationId(releaseStockList.get(i).getId()); + robotTaskDetailAddVo.setFromLaneId(stockList.get(i).getLaneId()); + robotTaskDetailAddVo.setToLaneId(releaseStockList.get(i).getLaneId()); + robotTaskDetailAddVo.setFromLocationNumber(stockList.get(i).getLocationNumber()); + robotTaskDetailAddVo.setFromMapItemId(stockList.get(i).getMapItemId()); + robotTaskDetailAddVo.setToMapItemId(releaseStockList.get(i).getMapItemId()); + robotTaskDetailAddVo.setRobotTaskId(taskId); + robotTaskDetailAddVo.setPriority(robotTaskVo.getPriority()); + robotTaskDetailAddVo.setFromLocationStorey(stockList.get(i).getLocationStorey()); + robotTaskDetailAddVo.setToLocationStorey(releaseStockList.get(i).getLocationStorey()); + addTaskDetailList.add(robotTaskDetailAddVo); + + toLocationIds.add(releaseStockList.get(i).getId()); + fromLocationIds.add(stockList.get(i).getId()); + } + return addTaskDetailList; + } + + public void setToLocation(RobotTaskDetailAddVO robotTaskVo, Set mapIds, List locationIds, + List takeMapItemIds, List releaseMapItemIds, + List laneIds, List areaIds, String skuInfo, Set chooseLocationIds) { + if (ReleaseTakeEnum.TO_LOCATION.getType().equals(robotTaskVo.getReleaseType())) { + WareHouseLocationDO query = WareHouseLocationDO.builder().id(robotTaskVo.getReleaseId()).build(); + WareHouseLocationDO locationDO = locationMapper.queryAllByLimit(query); + robotTaskVo.setToLocationNo(locationDO.getLocationNo()); + robotTaskVo.setToLocationId(robotTaskVo.getReleaseId()); + robotTaskVo.setToLocationStorey(locationDO.getLocationStorey()); + robotTaskVo.setToLaneId(locationDO.getLaneId()); + robotTaskVo.setToLocationNumber(locationDO.getLocationNumber()); + robotTaskVo.setToMapItemId(locationDO.getMapItemId()); + releaseMapItemIds.add(locationDO.getMapItemId()); + } else { + WareHouseLocationDO wareHouseLocationDO = + locationMapper.selectByTypeAndId(LocationUseStatusEnum.NO.getType(), robotTaskVo.getReleaseType() + , robotTaskVo.getReleaseId(), locationIds, null, takeMapItemIds, laneIds, areaIds); + robotTaskVo.setToLocationNo(wareHouseLocationDO.getLocationNo()); + robotTaskVo.setToLocationId(wareHouseLocationDO.getId()); + robotTaskVo.setToLocationStorey(wareHouseLocationDO.getLocationStorey()); + robotTaskVo.setToLaneId(wareHouseLocationDO.getLaneId()); + robotTaskVo.setToLocationNumber(wareHouseLocationDO.getLocationNumber()); + robotTaskVo.setToMapItemId(wareHouseLocationDO.getMapItemId()); + releaseMapItemIds.add(wareHouseLocationDO.getMapItemId()); + } + } + + +} diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/tool/ToolsServiceImpl.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/tool/ToolsServiceImpl.java index 462a97020..146afea16 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/tool/ToolsServiceImpl.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/tool/ToolsServiceImpl.java @@ -9,6 +9,8 @@ import cn.iocoder.yudao.module.mqtt.api.task.dto.RobotSimulationPoseDTO; import cn.iocoder.yudao.module.mqtt.api.task.dto.RobotSimulationPoseDataDTO; import cn.iocoder.yudao.module.mqtt.enums.task.ExecutionTypeEnum; import cn.iocoder.yudao.module.system.api.path.vo.RobotClosePathPlantingDTO; +import cn.iocoder.yudao.module.system.config.mqtt.util.MqttUtils; +import cn.iocoder.yudao.module.system.config.poperties.ZnConfigConstant; import cn.iocoder.yudao.module.system.constant.path.PathPlanningTopicConstant; import cn.iocoder.yudao.module.system.constant.robot.RobotTopicConstant; import cn.iocoder.yudao.module.system.controller.admin.config.dto.TaskOrderConfigDTO; @@ -48,8 +50,11 @@ import java.util.List; @Validated public class ToolsServiceImpl implements ToolsService { - @Resource - private CommonApi commonApi; + /*@Resource + private CommonApi commonApi;*/ + + @Autowired + private MqttUtils mqttUtils; @Resource private CommonConfigMapper configMapper; @@ -69,14 +74,11 @@ public class ToolsServiceImpl implements ToolsService { @Resource private PositionMapItemService positionMapItemService; - /*@Resource - private CommonConfigService configService;*/ - @Resource private PositionMapService positionMapService; - @Value("${zn.is_simulation:false}") - private Boolean isSimulation; + @Autowired + private ZnConfigConstant znConfigConstant; /** * 发送时间、优先级、距离的权重给PP @@ -100,8 +102,9 @@ public class ToolsServiceImpl implements ToolsService { List robots = informationService.getAllRobot(); if (ObjectUtil.isNotEmpty(robots)) { for (RobotInformationDO robot : robots) { - commonApi.commonMethodStr(String.valueOf(chargeConfig.getWarnWaitTime()), - RobotTopicConstant.WARN_WAIT_TIME_TOPIC+robot.getMacAddress()); +// commonApi.commonMethodStr(String.valueOf(chargeConfig.getWarnWaitTime()), +// RobotTopicConstant.WARN_WAIT_TIME_TOPIC+robot.getMacAddress()); + mqttUtils.pub(RobotTopicConstant.WARN_WAIT_TIME_TOPIC+robot.getMacAddress(),String.valueOf(chargeConfig.getWarnWaitTime())); } } } @@ -120,8 +123,9 @@ public class ToolsServiceImpl implements ToolsService { } TaskOrderConfigDTO taskOrderConfigDTO = JSONUtil.toBean(config.getConfigStr(), TaskOrderConfigDTO.class); - commonApi.commonMethod(taskOrderConfigDTO, - PathPlanningTopicConstant.SEND_SORT_CONFIG_TO_PP); +// commonApi.commonMethod(taskOrderConfigDTO, +// PathPlanningTopicConstant.SEND_SORT_CONFIG_TO_PP); + mqttUtils.pub(PathPlanningTopicConstant.SEND_SORT_CONFIG_TO_PP,JSON.toJSONString(taskOrderConfigDTO)); return "发送数据库权重配置成功"; } @@ -134,7 +138,8 @@ public class ToolsServiceImpl implements ToolsService { @Override public String cleanAgv(String robotNo) { CleanAgvDTO build = CleanAgvDTO.builder().robotNo(robotNo).build(); - commonApi.commonMethod(build, PathPlanningTopicConstant.CLEAN_AGV); +// commonApi.commonMethod(build, PathPlanningTopicConstant.CLEAN_AGV); + mqttUtils.pub(PathPlanningTopicConstant.CLEAN_AGV,JSON.toJSONString(build)); return "清除交管成功 " + robotNo; } @@ -150,15 +155,16 @@ public class ToolsServiceImpl implements ToolsService { .robotNo(informationDO.getRobotNo()) .id(taskDetailId) .build(); - commonApi.commonMethod(closePathPlanting, PathPlanningTopicConstant.KILL_TASK); +// commonApi.commonMethod(closePathPlanting, PathPlanningTopicConstant.KILL_TASK); + mqttUtils.pub(PathPlanningTopicConstant.KILL_TASK,JSON.toJSONString(closePathPlanting)); RobotAcceptTaskDTO robotTask = new RobotAcceptTaskDTO(); robotTask.setOrderId(taskDetailId); String mac = robotInformationService.getMacByRobotNo(informationDO.getRobotNo()); robotTask.setTopic(RobotTopicConstant.ROBOT_TASK_MOVE_TOPIC + mac); robotTask.setExecutionType(ExecutionTypeEnum.CANCEL.getType()); - commonApi.commonMethod(robotTask, robotTask.getTopic()); - +// commonApi.commonMethod(robotTask, robotTask.getTopic()); + mqttUtils.pub(robotTask.getTopic(),JSON.toJSONString(robotTask)); return "关闭任务成功"; } @@ -170,7 +176,8 @@ public class ToolsServiceImpl implements ToolsService { } for (RobotInformationDO robot : robots) { - commonApi.commonMethodStr("请同步告警码值", RobotTopicConstant.UPDATE_ERROR_TOPIC+robot.getMacAddress()); +// commonApi.commonMethodStr("请同步告警码值", RobotTopicConstant.UPDATE_ERROR_TOPIC+robot.getMacAddress()); + mqttUtils.pub(RobotTopicConstant.UPDATE_ERROR_TOPIC+robot.getMacAddress(),"请同步告警码值"); try { //怕车机同时间同步对内存有影响 Thread.sleep(500); @@ -183,7 +190,7 @@ public class ToolsServiceImpl implements ToolsService { @Override public void simulationPose() { - if (!isSimulation) { + if (!znConfigConstant.getIsSimulation()) { log.info("非仿真环境不需要同步默认的节点数据"); } @@ -238,7 +245,8 @@ public class ToolsServiceImpl implements ToolsService { poseData.setYaw(Double.valueOf(itemDOList.get(i).getLocationYaw())); simulationPoseDTO.setPose2d(poseData); simulationPoseDTO.setCommandType(RobotCommandTypeEnum.MOVE_POSE.getType()); - commonApi.commonMethod(simulationPoseDTO, RobotTopicConstant.ROBOT_COMMAND_TOPIC + robot.getMacAddress()); +// commonApi.commonMethod(simulationPoseDTO, RobotTopicConstant.ROBOT_COMMAND_TOPIC + robot.getMacAddress()); + mqttUtils.pub(RobotTopicConstant.ROBOT_COMMAND_TOPIC + robot.getMacAddress(),JSON.toJSONString(simulationPoseDTO)); log.info("仿真环境发送机器人默认点位信息 :{}", JSON.toJSONString(poseData)); i++; } @@ -246,7 +254,8 @@ public class ToolsServiceImpl implements ToolsService { @Override public void sendMsgToMQTT(SendMsgToMqttDTO dto) { - commonApi.commonMethodStr(dto.getMsg(),dto.getTopic()); +// commonApi.commonMethodStr(dto.getMsg(),dto.getTopic()); + mqttUtils.pub(dto.getTopic(),dto.getMsg()); } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/resources/application-dev.yaml b/yudao-module-system/yudao-module-system-biz/src/main/resources/application-dev.yaml index c999a6167..f1e8ab99c 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/resources/application-dev.yaml +++ b/yudao-module-system/yudao-module-system-biz/src/main/resources/application-dev.yaml @@ -191,28 +191,27 @@ zn: camera_secret_key: A2C4rv7DY012c9ef #摄像头秘钥 do_cycle: true #是否开启循环 lane_auto_move: true #线库是否自动移库 true:线库执行自动移库 、false:线库关闭执行自动移库 - robot_position_cache_time: 10 #机器人上报点位存储时间(秒) + robot_position_cache_time: 10000000 #机器人上报点位存储时间(秒) cycle_do_auto_move: true #存在循环的任务,是否开启自动移库. true:存在循环任务,开启自动移库; false:有循环任务不自动移库 - full_electricity: 100 #机器人充满电的电量 + full_electricity: 95 #机器人充满电的电量 task_need_single: true #机器人对同一线库/点位是不是只能有一台机器人做任务 (true:一个点位/线库,只有一台机器人) location_number_reduce: 100000000 #库位排序的差值(下发取货任务,将库位排序减去此值,然后取绝对值) robot_doing_action: # 机器人正在做的动作 doing_action_cache_time: 172800 #单个动作缓存时间 8小时 - robot_chearg: #机器人充电的配置 + robot_charge: #机器人充电的配置 release_location_number_config: 50 #同一组序号,越大越先执行 priority_config: 50 #优先级 task: #任务相关的配置 check_sku_info: true #校验物料信息 + task_cache_time: 1209600 #任务缓存的时间, 默认一星期 robot_config: #机器人取放货默认配置 offset_height: 0.1 #叉起货需要在原来高度基础上偏移的高度 - default_tray_height: 1.1 #默认每层高度 + default_tray_height: 0.82 #默认每层高度 open_rate_limiter: true #是否开启限流 - path_planning: - task_chche_time: 1209600 #任务缓存的时间, 默认一星期 is_simulation: false # 是否为仿真环境 send_robot_init_pose: true # 是否为发送默认的车辆所在地图和点位 - restore_task_restart: false # 恢复任务是否全部重新执行 true:全部重新开始 synchronous_all_map_node: 500 # 点位信息每次发送的数据量 + task_not_check: true # 创建任务不校验 #海康威视的相关配置 @@ -227,4 +226,19 @@ resource: #视频能力 video: previewUrls: /artemis/api/video/v2/cameras/previewURLs - replayUrlApi: /artemis/api/video/v2/cameras/playbackURLs \ No newline at end of file + replayUrlApi: /artemis/api/video/v2/cameras/playbackURLs + +# MQTT +mqtt: + # host: tcp://123.57.12.40:1883 + host: tcp://127.0.0.1:1883 + # host: tcp://10.10.7.116:1883 + # host: tcp://10.10.7.114:1883 + username: adminuser + password: adminuser + qos: 2 + clientId: mqttx_b82345a52 + # 表示允许同时在传输中的最大消息数量 + maxInflight: 1000 + timeout: 10 + keepalive: 20 \ No newline at end of file diff --git a/yudao-module-system/yudao-module-system-biz/src/main/resources/application-local.yaml b/yudao-module-system/yudao-module-system-biz/src/main/resources/application-local.yaml index 156ae6b21..a9370ee8b 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/resources/application-local.yaml +++ b/yudao-module-system/yudao-module-system-biz/src/main/resources/application-local.yaml @@ -228,26 +228,25 @@ zn: lane_auto_move: true #线库是否自动移库 true:线库执行自动移库 、false:线库关闭执行自动移库 robot_position_cache_time: 10000000 #机器人上报点位存储时间(秒) cycle_do_auto_move: true #存在循环的任务,是否开启自动移库. true:存在循环任务,开启自动移库; false:有循环任务不自动移库 - full_electricity: 100 #机器人充满电的电量 + full_electricity: 95 #机器人充满电的电量 task_need_single: true #机器人对同一线库/点位是不是只能有一台机器人做任务 (true:一个点位/线库,只有一台机器人) location_number_reduce: 100000000 #库位排序的差值(下发取货任务,将库位排序减去此值,然后取绝对值) robot_doing_action: # 机器人正在做的动作 doing_action_cache_time: 172800 #单个动作缓存时间 8小时 - robot_chearg: #机器人充电的配置 + robot_charge: #机器人充电的配置 release_location_number_config: 50 #同一组序号,越大越先执行 priority_config: 50 #优先级 task: #任务相关的配置 check_sku_info: true #校验物料信息 + task_cache_time: 1209600 #任务缓存的时间, 默认一星期 robot_config: #机器人取放货默认配置 offset_height: 0.1 #叉起货需要在原来高度基础上偏移的高度 default_tray_height: 0.82 #默认每层高度 open_rate_limiter: true #是否开启限流 - path_planning: - task_chche_time: 1209600 #任务缓存的时间, 默认一星期 - is_simulation: true # 是否为仿真环境 + is_simulation: false # 是否为仿真环境 send_robot_init_pose: true # 是否为发送默认的车辆所在地图和点位 - restore_task_restart: true # 恢复任务是否全部重新执行 true:全部重新开始 synchronous_all_map_node: 500 # 点位信息每次发送的数据量 + task_not_check: true # 创建任务不校验 logging: file: @@ -266,3 +265,18 @@ resource: video: previewUrls: /artemis/api/video/v2/cameras/previewURLs replayUrlApi: /artemis/api/video/v2/cameras/playbackURLs + +# MQTT +mqtt: +# host: tcp://123.57.12.40:1883 + host: tcp://127.0.0.1:1883 + # host: tcp://10.10.7.116:1883 + # host: tcp://10.10.7.114:1883 + username: adminuser + password: adminuser + qos: 2 + clientId: mqttx_b82345a52 + # 表示允许同时在传输中的最大消息数量 + maxInflight: 1000 + timeout: 10 + keepalive: 20 diff --git a/yudao-module-system/yudao-module-system-biz/src/main/resources/application-test.yaml b/yudao-module-system/yudao-module-system-biz/src/main/resources/application-test.yaml index 2a33e2148..681d06597 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/resources/application-test.yaml +++ b/yudao-module-system/yudao-module-system-biz/src/main/resources/application-test.yaml @@ -219,28 +219,27 @@ zn: camera_secret_key: A2C4rv7DY012c9ef #摄像头秘钥 do_cycle: true #是否开启循环 lane_auto_move: true #线库是否自动移库 true:线库执行自动移库 、false:线库关闭执行自动移库 - robot_position_cache_time: 10 #机器人上报点位存储时间(秒) + robot_position_cache_time: 10000000 #机器人上报点位存储时间(秒) cycle_do_auto_move: true #存在循环的任务,是否开启自动移库. true:存在循环任务,开启自动移库; false:有循环任务不自动移库 - full_electricity: 100 #机器人充满电的电量 + full_electricity: 95 #机器人充满电的电量 task_need_single: true #机器人对同一线库/点位是不是只能有一台机器人做任务 (true:一个点位/线库,只有一台机器人) location_number_reduce: 100000000 #库位排序的差值(下发取货任务,将库位排序减去此值,然后取绝对值) robot_doing_action: # 机器人正在做的动作 doing_action_cache_time: 172800 #单个动作缓存时间 8小时 - robot_chearg: #机器人充电的配置 + robot_charge: #机器人充电的配置 release_location_number_config: 50 #同一组序号,越大越先执行 priority_config: 50 #优先级 task: #任务相关的配置 check_sku_info: true #校验物料信息 + task_cache_time: 1209600 #任务缓存的时间, 默认一星期 robot_config: #机器人取放货默认配置 offset_height: 0.1 #叉起货需要在原来高度基础上偏移的高度 - default_tray_height: 1.1 #默认每层高度 + default_tray_height: 0.82 #默认每层高度 open_rate_limiter: true #是否开启限流 - path_planning: - task_chche_time: 1209600 #任务缓存的时间, 默认一星期 is_simulation: false # 是否为仿真环境 send_robot_init_pose: true # 是否为发送默认的车辆所在地图和点位 - restore_task_restart: false # 恢复任务是否全部重新执行 true:全部重新开始 synchronous_all_map_node: 500 # 点位信息每次发送的数据量 + task_not_check: true # 创建任务不校验 #海康威视的相关配置 isc: @@ -254,4 +253,18 @@ resource: #视频能力 video: previewUrls: /artemis/api/video/v2/cameras/previewURLs - replayUrlApi: /artemis/api/video/v2/cameras/playbackURLs \ No newline at end of file + replayUrlApi: /artemis/api/video/v2/cameras/playbackURLs + +# MQTT +mqtt: + # host: tcp://123.57.12.40:1883 + # host: tcp://10.10.100.42:1883 + host: tcp://127.0.0.1:1883 + username: adminuser + password: adminuser + qos: 0 + clientId: mqttx_b82345a52 + # 表示允许同时在传输中的最大消息数量 + maxInflight: 1000 + timeout: 10 + keepalive: 20 \ No newline at end of file diff --git a/yudao-module-system/yudao-module-system-biz/src/main/resources/mapper/positionmap/PositionMapItemMapper.xml b/yudao-module-system/yudao-module-system-biz/src/main/resources/mapper/positionmap/PositionMapItemMapper.xml index 4c33df762..c7db4ded8 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/resources/mapper/positionmap/PositionMapItemMapper.xml +++ b/yudao-module-system/yudao-module-system-biz/src/main/resources/mapper/positionmap/PositionMapItemMapper.xml @@ -86,7 +86,7 @@ (#{item.positionMapId}, #{item.actualLocationX}, #{item.actualLocationY}, #{item.type}) - select id, sort_num as sortNum diff --git a/yudao-module-system/yudao-module-system-biz/src/main/resources/mapper/robot/RobotInformationMapper.xml b/yudao-module-system/yudao-module-system-biz/src/main/resources/mapper/robot/RobotInformationMapper.xml index 7f775cdb6..1a8e28ac3 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/resources/mapper/robot/RobotInformationMapper.xml +++ b/yudao-module-system/yudao-module-system-biz/src/main/resources/mapper/robot/RobotInformationMapper.xml @@ -160,8 +160,7 @@ from robot_information where - deleted = '0' - and robot_no in + robot_no in #{robotNo} @@ -176,7 +175,8 @@ t2.robot_center_headstock AS robotCenterHeadstock, t2.robot_center_tail AS robotCenterTail, t1.mac_address as macAddress, - t2.robot_turning_radius as robotTurningRadius + t2.robot_turning_radius as robotTurningRadius, + t2.robot_offset as robotOffset FROM robot_information t1 LEFT JOIN robot_model t2 ON t1.robot_model_id = t2.id @@ -198,4 +198,28 @@ + + diff --git a/yudao-module-system/yudao-module-system-biz/src/main/resources/mapper/robot/TaskCycleMapper.xml b/yudao-module-system/yudao-module-system-biz/src/main/resources/mapper/robot/TaskCycleMapper.xml index 20015e06b..698e5b814 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/resources/mapper/robot/TaskCycleMapper.xml +++ b/yudao-module-system/yudao-module-system-biz/src/main/resources/mapper/robot/TaskCycleMapper.xml @@ -12,4 +12,12 @@ delete from robot_task_cycle where robot_task_id = #{robotTaskId} + + delete from robot_task_cycle + where robot_task_id in + + #{robotTaskId} + + \ No newline at end of file