diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/robot/RequestProcessor.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/robot/RequestProcessor.java new file mode 100644 index 000000000..878b98acc --- /dev/null +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/robot/RequestProcessor.java @@ -0,0 +1,61 @@ +package cn.iocoder.yudao.module.system.api.robot; + +import cn.hutool.core.map.MapUtil; +import cn.iocoder.yudao.module.infra.api.websocket.WebSocketSenderApi; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; + +import javax.annotation.PreDestroy; +import javax.annotation.Resource; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; + +@Component +@Slf4j +public class RequestProcessor { + private final ConcurrentHashMap> cache = new ConcurrentHashMap<>(); + private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1); + + @Resource + public WebSocketSenderApi webSocketSenderApi; + + public RequestProcessor() { + // 每秒执行一次 - 处理并发送数据 - 避免数据丢失 + scheduler.scheduleAtFixedRate(this::processAndSend, 1, 1, TimeUnit.SECONDS); + } + + public void handleRequest(String map, String mac, String data) { + cache.computeIfAbsent(map, k -> new ConcurrentHashMap<>()).put(mac, data); + } + + + private void processAndSend() { + Map> snapshot = new ConcurrentHashMap<>(cache); // 创建快照 + cache.clear(); // 先清理缓存 + for (Map.Entry> entry : snapshot.entrySet()) { + if (!MapUtil.isEmpty(entry.getValue())) { + sendData(entry.getKey(), entry.getValue()); + } + } + } + + private void sendData(String map, Map data) { + // -- 发送给对应的websocket +// System.out.println("key:" + map + "发送数据:" + data); + log.info("key:" + map + "发送数据:" + data); + webSocketSenderApi.sendObject(map, "map_push", data); + } + + public void shutdown() { + scheduler.shutdown(); + } + + @PreDestroy + public void destroy() { + // 在Bean销毁前关闭去啊 + shutdown(); + } +} 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 557cd2bfb..8d9c78b90 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 @@ -24,6 +24,7 @@ import org.springframework.web.bind.annotation.RestController; import javax.annotation.Resource; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; import java.util.Map; import java.util.stream.Collectors; @@ -48,8 +49,12 @@ public class RobotStatusApiImpl implements RobotStatusApi { @Value("${zn.robot_position_cache_time:600}") private Long robotPositionCacheTime; + @Resource + private RequestProcessor processor; + /** * 更新机器人点位/异常/能否做任务 + * * @param robotStatusDataDTO * @return */ @@ -61,26 +66,31 @@ public class RobotStatusApiImpl implements RobotStatusApi { return; } - String taskStatusKey = RobotTaskChcheConstant.ROBOT_TASK_STATUS +robotStatusDataDTO.getMac(); - String cargoDetectedKey = RobotTaskChcheConstant.ROBOT_CARGO_DETECTED +robotStatusDataDTO.getMac(); - String pose2dKey = RobotTaskChcheConstant.ROBOT_INFORMATION_POSE_BAT_SOC +robotStatusDataDTO.getMac(); - redisUtil.set(taskStatusKey, robotStatusDataDTO.getData().getTask_status(),robotPositionCacheTime); - redisUtil.set(cargoDetectedKey,robotStatusDataDTO.getData().getCargo_detected(),robotPositionCacheTime); + String taskStatusKey = RobotTaskChcheConstant.ROBOT_TASK_STATUS + robotStatusDataDTO.getMac(); + String cargoDetectedKey = RobotTaskChcheConstant.ROBOT_CARGO_DETECTED + robotStatusDataDTO.getMac(); + String pose2dKey = RobotTaskChcheConstant.ROBOT_INFORMATION_POSE_BAT_SOC + robotStatusDataDTO.getMac(); + redisUtil.set(taskStatusKey, robotStatusDataDTO.getData().getTask_status(), robotPositionCacheTime); + redisUtil.set(cargoDetectedKey, robotStatusDataDTO.getData().getCargo_detected(), robotPositionCacheTime); Object object = redisUtil.get(pose2dKey); - RobotStatusDataPoseDTO robotStatusDataPoseDTO= JSONUtil.toBean((String)object, RobotStatusDataPoseDTO.class); + RobotStatusDataPoseDTO robotStatusDataPoseDTO = JSONUtil.toBean((String) object, RobotStatusDataPoseDTO.class); robotStatusDataPoseDTO.setX(robotStatusDataDTO.getData().getPose2d().getX()); robotStatusDataPoseDTO.setY(robotStatusDataDTO.getData().getPose2d().getY()); robotStatusDataPoseDTO.setYaw(robotStatusDataDTO.getData().getPose2d().getYaw()); - robotStatusDataPoseDTO.setFloor(robotStatusDataDTO.getData().getPose2d().getFloor()); - robotStatusDataPoseDTO.setArea(robotStatusDataDTO.getData().getPose2d().getArea()); - redisUtil.set(pose2dKey,JSON.toJSONString(robotStatusDataPoseDTO),robotPositionCacheTime); + robotStatusDataPoseDTO.setFloor(robotStatusDataDTO.getData().getFloor_zone().getFloor()); + robotStatusDataPoseDTO.setArea(robotStatusDataDTO.getData().getFloor_zone().getArea()); + redisUtil.set(pose2dKey, JSON.toJSONString(robotStatusDataPoseDTO), robotPositionCacheTime); + + // 模拟请求 + processor.handleRequest(robotStatusDataPoseDTO.getFloor() + "_" + robotStatusDataPoseDTO.getArea(), + robotStatusDataDTO.getMac(), JSONUtil.toJsonStr(robotStatusDataDTO.getData().getPose2d())); + if (ObjectUtil.isNotNull(robotStatusDataDTO.getData().getErr_code())) { List errCode = robotStatusDataDTO.getData().getErr_code(); String robotNo = robotInformationService.getRobotNoByMac(robotStatusDataDTO.getMac()); if (ObjectUtil.isNull(robotNo)) { - log.info("查不到机器人编号 :{}",robotStatusDataDTO.getMac()); + log.info("查不到机器人编号 :{}", robotStatusDataDTO.getMac()); return; } @@ -88,7 +98,7 @@ public class RobotStatusApiImpl implements RobotStatusApi { errCode.stream().map(RobotStatusDataErrorDTO::getError_code).collect(Collectors.toList()); List robotWarnCodeMappingDOS = warnCodeMappingMapper.selectList(new LambdaQueryWrapper() - .in(RobotWarnCodeMappingDO::getWarnCode, warnCodes)); + .in(RobotWarnCodeMappingDO::getWarnCode, warnCodes)); if (ObjectUtil.isEmpty(robotWarnCodeMappingDOS)) { log.info("查不对应编号的告警信息 :{}", JSON.toJSONString(warnCodes)); return; @@ -102,7 +112,7 @@ public class RobotStatusApiImpl implements RobotStatusApi { for (RobotStatusDataErrorDTO robotStatusData : errCode) { List mappingDOS = warnCodeMapping.get(robotStatusData.getError_code()); if (ObjectUtil.isEmpty(mappingDOS)) { - log.info("当前告警类型查不到对应的告警信息 :{}",robotStatusData.getError_code()); + log.info("当前告警类型查不到对应的告警信息 :{}", robotStatusData.getError_code()); continue; } RobotWarnMsgDO warnMsg = RobotWarnMsgDO.builder().warnLevel(Integer.valueOf(robotStatusData.getCode_level())) @@ -119,5 +129,4 @@ public class RobotStatusApiImpl implements RobotStatusApi { } - } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/housearea/HouseAreaController.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/housearea/HouseAreaController.java index 4c31153b4..86732f3e6 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/housearea/HouseAreaController.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/housearea/HouseAreaController.java @@ -82,8 +82,8 @@ public class HouseAreaController { @GetMapping("/getHouseAreaList") @Operation(summary = "获得全部库区") @PreAuthorize("@ss.hasPermission('ware:house-area:query')") - public CommonResult> getHouseAreaList() { - List list = houseAreaService.getHouseAreaList(); + public CommonResult> getHouseAreaList(@RequestParam Long positionMapId) { + List list = houseAreaService.getHouseAreaList(positionMapId); return success(BeanUtils.toBean(list, HouseAreaRespVO.class)); } 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 f5d0c2fda..aa2336132 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 @@ -6,7 +6,7 @@ import cn.iocoder.yudao.framework.common.pojo.PageParam; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; -import cn.iocoder.yudao.module.infra.api.websocket.WebSocketSenderApi; +import cn.iocoder.yudao.module.system.api.robot.dto.RobotStatusDTO; import cn.iocoder.yudao.module.system.controller.admin.robot.vo.*; import cn.iocoder.yudao.module.system.dal.dataobject.robot.RobotInformationDO; import cn.iocoder.yudao.module.system.service.robot.RobotInformationService; @@ -36,8 +36,14 @@ public class RobotInformationController { @Resource private RobotInformationService informationService; - @Resource - private WebSocketSenderApi webSocketSenderApi; + + @PostMapping("/test") + @Operation(summary = "测试") + @PermitAll + public CommonResult test(@RequestBody RobotStatusDTO dto) { + informationService.test(dto); + return success(true); + } @PostMapping("/create") @Operation(summary = "创建车辆信息") @@ -46,14 +52,6 @@ public class RobotInformationController { return success(informationService.createInformation(createReqVO)); } - @PostMapping("/test") - @PermitAll - @Operation(summary = "测试") - public CommonResult test(@RequestParam String id, @RequestParam String msg) { - webSocketSenderApi.sendObject(id,"map_push", msg); - return success(true); - } - @PutMapping("/update") @Operation(summary = "更新车辆信息") @PreAuthorize("@ss.hasPermission('robot:information:update')") diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/housearea/HouseAreaService.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/housearea/HouseAreaService.java index 5d7275044..8c6475fd6 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/housearea/HouseAreaService.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/housearea/HouseAreaService.java @@ -64,5 +64,5 @@ public interface HouseAreaService { * 获得全部库区 * @return */ - List getHouseAreaList(); + List getHouseAreaList(Long positionMapId); } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/housearea/HouseAreaServiceImpl.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/housearea/HouseAreaServiceImpl.java index 3e9f356a2..cb35de163 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/housearea/HouseAreaServiceImpl.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/housearea/HouseAreaServiceImpl.java @@ -14,7 +14,6 @@ import cn.iocoder.yudao.module.system.controller.admin.positionmap.dto.PositionM import cn.iocoder.yudao.module.system.dal.dataobject.housearea.HouseAreaDO; 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.RobotModelDO; import cn.iocoder.yudao.module.system.dal.mysql.housearea.HouseAreaMapper; import cn.iocoder.yudao.module.system.service.houselocation.HouseLocationService; import cn.iocoder.yudao.module.system.service.positionmap.PositionMapItemService; @@ -157,10 +156,10 @@ public class HouseAreaServiceImpl implements HouseAreaService { } @Override - public List getHouseAreaList() { - List list = houseAreaMapper.selectList(new LambdaQueryWrapper() + public List getHouseAreaList(Long positionMapId) { + return houseAreaMapper.selectList(new LambdaQueryWrapper() + .eq(HouseAreaDO::getPositionMapId, positionMapId) .orderByAsc(HouseAreaDO::getId)); - return list; } } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/robot/RobotInformationService.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/robot/RobotInformationService.java index b1265bf10..9017637c2 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/robot/RobotInformationService.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/robot/RobotInformationService.java @@ -4,6 +4,7 @@ import java.util.*; import javax.validation.*; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.module.system.api.robot.dto.RobotStatusDTO; import cn.iocoder.yudao.module.system.controller.admin.robot.vo.*; import cn.iocoder.yudao.module.system.dal.dataobject.robot.RobotInformationDO; @@ -77,4 +78,9 @@ public interface RobotInformationService { */ String getRobotNoByMac(String mac); -} \ No newline at end of file + /** + * + * @param dto + */ + void test(@Valid RobotStatusDTO dto); +} 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 6ccf44a78..7b00d6cec 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 @@ -3,6 +3,11 @@ package cn.iocoder.yudao.module.system.service.robot; import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.util.ObjectUtil; import cn.hutool.json.JSONUtil; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder; +import cn.iocoder.yudao.module.system.api.robot.RequestProcessor; +import cn.iocoder.yudao.module.system.api.robot.dto.RobotStatusDTO; import cn.iocoder.yudao.module.system.api.robot.dto.RobotStatusDataPoseDTO; import cn.iocoder.yudao.module.system.constant.robot.RobotTaskChcheConstant; import cn.iocoder.yudao.module.system.controller.admin.robot.vo.*; @@ -18,13 +23,11 @@ import cn.iocoder.yudao.module.system.enums.robot.*; import cn.iocoder.yudao.module.system.util.redis.RedisUtil; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import org.springframework.stereotype.Service; -import javax.annotation.Resource; import org.springframework.validation.annotation.Validated; -import java.util.*; -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.framework.common.util.object.BeanUtils; - +import javax.annotation.Resource; +import java.util.List; +import java.util.Set; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.*; @@ -52,6 +55,8 @@ public class RobotInformationServiceImpl implements RobotInformationService { @Resource private RedisUtil redisUtil; + @Resource + private RequestProcessor processor; @Override public Long createInformation(RobotInformationSaveReqVO createReqVO) { @@ -308,4 +313,23 @@ public class RobotInformationServiceImpl implements RobotInformationService { return ""; } -} \ No newline at end of file + @Override + public void test(RobotStatusDTO robotStatusDataDTO) { + TenantContextHolder.setTenantId(1L); + if (ObjectUtil.isEmpty(robotStatusDataDTO) || ObjectUtil.isEmpty(robotStatusDataDTO.getMac())) { + return; + } + RobotStatusDataPoseDTO robotStatusDataPoseDTO = new RobotStatusDataPoseDTO(); + robotStatusDataPoseDTO.setX(robotStatusDataDTO.getData().getPose2d().getX()); + robotStatusDataPoseDTO.setY(robotStatusDataDTO.getData().getPose2d().getY()); + robotStatusDataPoseDTO.setYaw(robotStatusDataDTO.getData().getPose2d().getYaw()); + robotStatusDataPoseDTO.setFloor(robotStatusDataDTO.getData().getFloor_zone().getFloor()); + robotStatusDataPoseDTO.setArea(robotStatusDataDTO.getData().getFloor_zone().getArea()); + robotStatusDataPoseDTO.setBat_soc(robotStatusDataDTO.getData().getPose2d().getBat_soc()); + // 模拟请求 + processor.handleRequest(robotStatusDataDTO.getData().getFloor_zone().getFloor() + "_" + robotStatusDataDTO.getData().getFloor_zone().getArea(), + robotStatusDataDTO.getMac(), JSONUtil.toJsonStr(robotStatusDataPoseDTO)); + + } + +} 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 bbb91d42c..621594aeb 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 @@ -58,7 +58,7 @@ spring: primary: master datasource: master: - url: jdbc:mysql://47.97.8.94:3306/zn_wcs?useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true&rewriteBatchedStatements=true # MySQL Connector/J 8.X 连接的示例 + url: jdbc:mysql://47.97.8.94:3306/zn_wcs?useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true&rewriteBatchedStatements=true&allowMultiQueries=true # MySQL Connector/J 8.X 连接的示例 # url: jdbc:mysql://127.0.0.1:3306/ruoyi-vue-pro?useSSL=true&allowPublicKeyRetrieval=true&useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&rewriteBatchedStatements=true # MySQL Connector/J 5.X 连接的示例 # url: jdbc:postgresql://127.0.0.1:5432/ruoyi-vue-pro # PostgreSQL 连接的示例 # url: jdbc:oracle:thin:@127.0.0.1:1521:xe # Oracle 连接的示例 @@ -72,7 +72,7 @@ spring: # password: SYSDBA # DM 连接的示例 slave: # 模拟从库,可根据自己需要修改 lazy: true # 开启懒加载,保证启动速度 - url: jdbc:mysql://47.97.8.94:3306/zn_wcs?useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true&rewriteBatchedStatements=true + url: jdbc:mysql://47.97.8.94:3306/zn_wcs?useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true&rewriteBatchedStatements=true&allowMultiQueries=true username: root password: yhtkj@2024! @@ -229,4 +229,4 @@ zn: lane_auto_move: true #线库是否自动移库 true:线库执行自动移库 、false:线库关闭执行自动移库 robot_position_cache_time: 10 #机器人上报点位存储时间 cycle_do_auto_move: true #存在循环的任务,是否开启自动移库. true:存在循环任务,开启自动移库; false:有循环任务不自动移库 - full_electricity: 100 #机器人充满电的电量 \ No newline at end of file + full_electricity: 100 #机器人充满电的电量