Compare commits

...

4 Commits

Author SHA1 Message Date
aikai
9ee9fc7994 Merge branch 'dev' of http://git.znkjfw.com/ak/zn-cloud-wcs into aikai 2025-02-18 16:03:14 +08:00
aikai
86f0385836 refactor(robot): 重构机器人信息获取逻辑
- 新增 RobotInformationVO 类用于封装机器人信息
- 实现机器人信息缓存机制,优化信息获取效率
- 修改测试接口,使用 RobotStatusDTO 作为参数
- 更新机器人状态处理逻辑,支持错误级别判断
-优化数据库查询,减少冗余操作
2025-02-18 16:03:08 +08:00
cbs
a743e1aff7 Merge branch 'dev' into cbs 2025-02-18 08:57:00 +08:00
cbs
28d30da941 充电配置加每天 2025-02-18 08:56:04 +08:00
27 changed files with 545 additions and 144 deletions

View File

@ -3,6 +3,10 @@ package cn.iocoder.yudao.framework.common.enums;
import lombok.AllArgsConstructor;
import lombok.Getter;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
/**
* 通用状态枚举
*
@ -28,4 +32,8 @@ public enum NodeTypeEnum {
*/
private final String name;
public static List<Integer> getAllTypes() {
return Arrays.stream(NodeTypeEnum.values()).map(NodeTypeEnum::getType).collect(Collectors.toList());
}
}

View File

@ -25,7 +25,7 @@ public class PositionMapLineDTO {
@Schema(description = "结束点id(点位子表id)", example = "15890")
private Long endPointId;
@Schema(description = "行走方法 0.直线 1.上左曲线2.上右曲线3.下左曲线 4.下右曲线")
@Schema(description = "行走方法 0.直线 1.曲线")
private Integer method;
@Schema(description = "方向 1.单向 2.双向", example = "15890")
@ -48,7 +48,38 @@ public class PositionMapLineDTO {
@Schema(description = "结束控制点y轴")
private String endControlY;
/**
* 开始点位x轴
*/
private String actualStartPointX;
/**
* 开始点位y轴
*/
private String actualStartPointY;
/**
* 结束点位x轴
*/
private String actualEndPointX;
/**
* 结束点位y轴
*/
private String actualEndPointY;
/**
* 开始控制点x轴
*/
private String actualBeginControlX;
/**
* 开始控制点y轴
*/
private String actualBeginControlY;
/**
* 结束控制点x轴
*/
private String actualEndControlX;
/**
* 结束控制点y轴
*/
private String actualEndControlY;
@Schema(description = "膨胀区域前")
private BigDecimal expansionZoneFront;

View File

@ -0,0 +1,24 @@
package cn.iocoder.yudao.module.mqtt.api.path.task;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.util.List;
/**
* 发送任务给PP
*/
@Data
public class TaskToPathPlanningDTO {
@Schema(description = "robot_task_detail 的 id")
private String id;
@Schema(description = "能执行此任务的机器人编号")
private List<String> robotNoList;
//线库: LINE + 线库号
//普通库位: POINT + 点位号
@Schema(description = "取的编号: 线库id+点位id")
private String takeId;
}

View File

@ -0,0 +1,27 @@
package cn.iocoder.yudao.module.system.api.robot.vo;
import cn.iocoder.yudao.module.system.api.robot.dto.RobotStatusDataPoseDTO;
import lombok.Data;
/**
* 车机响应信息
*/
@Data
public class RobotInformationVO {
/**
* 设备id
*/
private Long id;
/**
* mac地址
*/
private String macAddress;
/**
* 车辆类型
*/
private String robotModelNumber;
/**
* 点位信息
*/
public RobotStatusDataPoseDTO pose2d;
}

View File

@ -6,6 +6,7 @@ import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder;
import cn.iocoder.yudao.module.system.api.robot.dto.RobotStatusDTO;
import cn.iocoder.yudao.module.system.api.robot.dto.RobotStatusDataErrorDTO;
import cn.iocoder.yudao.module.system.api.robot.dto.RobotStatusDataPoseDTO;
import cn.iocoder.yudao.module.system.api.robot.vo.RobotInformationVO;
import cn.iocoder.yudao.module.system.constant.robot.RobotTaskChcheConstant;
import cn.iocoder.yudao.module.system.dal.dataobject.robot.RobotWarnCodeMappingDO;
import cn.iocoder.yudao.module.system.dal.dataobject.robot.RobotWarnMsgDO;
@ -19,7 +20,6 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
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.validation.annotation.Validated;
import org.springframework.web.bind.annotation.RestController;
@ -29,8 +29,6 @@ import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import static cn.iocoder.yudao.module.system.config.SystemJobConfiguration.NOTIFY_THREAD_POOL_TASK_EXECUTOR;
@Slf4j
@RestController // 提供 RESTful API 接口 Feign 调用
@Validated
@ -85,10 +83,16 @@ public class RobotStatusApiImpl implements RobotStatusApi {
robotStatusDataPoseDTO.setFloor(robotStatusDataDTO.getData().getFloor_zone().getFloor());
robotStatusDataPoseDTO.setArea(robotStatusDataDTO.getData().getFloor_zone().getArea());
redisUtil.set(pose2dKey, JSON.toJSONString(robotStatusDataPoseDTO), robotPositionCacheTime);
// -- 通过mac 地址获取车辆信息 - (并且加入到缓存中)
Map<String, RobotInformationVO> robotInformationVOS = robotInformationService.getAllRobotByRedis();
RobotInformationVO robotInformationVO = robotInformationVOS.get(robotStatusDataDTO.getMac());
if (robotInformationVO == null) {
robotInformationVO = robotInformationService.getRobotByRedis(robotStatusDataDTO.getMac());
}
robotInformationVO.setPose2d(robotStatusDataDTO.getData().getPose2d());
// 合并请求 - 这里接受到的数据都丢给 RequestProcessor - 再整合数据通过WebSocket丢给前端
processor.handleRequest(robotStatusDataPoseDTO.getFloor() + "_" + robotStatusDataPoseDTO.getArea(),
robotStatusDataDTO.getMac(), JSONUtil.toJsonStr(robotStatusDataDTO.getData().getPose2d()));
robotStatusDataDTO.getMac(), JSONUtil.toJsonStr(robotInformationVO));
if (ObjectUtil.isNotNull(robotStatusDataDTO.getData().getErr_code())) {

View File

@ -7,43 +7,43 @@ public class PathPlanningTopicConstant {
/**
* 同步全部地图点位 ware_position_map_line数据
*/
public static String SYNCHRONOUS_ALL_MAP_POINT = "SYNCHRONOUS_MAP_POINT";
public static String SYNCHRONOUS_ALL_MAP_LINE = "SYNCHRONOUS_ALL_MAP_LINE";
/**
* 同步 ware_position_map_item数据
*/
public static String SYNCHRONOUS_ALL_ITEM = "SYNCHRONOUS_ALL_ITEM";
public static String SYNCHRONOUS_ALL_MAP_NODE = "SYNCHRONOUS_ALL_MAP_NODE";
/**
* 添加ware_position_map_line地图点位给PP
*/
public static String ADD_MAP_POINT = "ADD_MAP_POINT";
public static String ADD_MAP_LINE = "ADD_MAP_LINE";
/**
* 删除ware_position_map_line地图点位给PP
*/
public static String DELETE_MAP_POINT = "DELETE_MAP_POINT";
public static String DELETE_MAP_LINE = "DELETE_MAP_LINE";
/**
* 更新ware_position_map_line地图点位给PP
*/
public static String UPDATE_MAP_POINT = "UPDATE_MAP_POINT";
public static String UPDATE_MAP_LINE = "UPDATE_MAP_LINE";
/**
* 添加ware_position_map_item地图点位给PP
*/
public static String ADD_MAP_ITEM = "ADD_MAP_ITEM";
public static String ADD_MAP_NODE = "ADD_MAP_NODE";
/**
* 删除ware_position_map_item地图点位给PP
*/
public static String DELETE_MAP_ITEM = "DELETE_MAP_ITEM";
public static String DELETE_MAP_NODE = "DELETE_MAP_NODE";
/**
* 更新ware_position_map_item地图点位给PP
*/
public static String UPDATE_MAP_ITEM = "UPDATE_MAP_ITEM";
public static String UPDATE_MAP_NODE = "UPDATE_MAP_NODE";

View File

@ -28,4 +28,7 @@ public class RobotTaskChcheConstant {
//机器人异常信息(拼接的是mac地址)
public static String ROBOT_ERROR_MSG = "robot:information:error:msg";
//机器人mac地址和机器人id以及机器人类型映射(通过mac地址获取机器人基本信息)
public static String ROBOT_GET_ROBOT_INFO = "robot:information:getRobotInfo";
}

View File

@ -1,19 +1,15 @@
package cn.iocoder.yudao.module.system.controller.admin.positionmap;
import cn.hutool.core.collection.CollectionUtil;
import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog;
import cn.iocoder.yudao.framework.common.enums.NodeTypeEnum;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.iocoder.yudao.module.system.controller.admin.positionmap.dto.NodeBaseDTO;
import cn.iocoder.yudao.module.system.controller.admin.positionmap.vo.PositionMapItemPageReqVO;
import cn.iocoder.yudao.module.system.controller.admin.positionmap.vo.PositionMapItemRespVO;
import cn.iocoder.yudao.module.system.dal.dataobject.positionmap.PositionMapItemDO;
import cn.iocoder.yudao.module.system.handler.mapnode.NodeProcessingContext;
import cn.iocoder.yudao.module.system.service.positionmap.PositionMapItemService;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
@ -22,15 +18,12 @@ import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.io.IOException;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import static cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum.EXPORT;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
@Tag(name = "管理后台 - 仓库点位地图子表")
@ -44,12 +37,6 @@ public class PositionMapItemController {
@Resource
private NodeProcessingContext nodeProcessingContext;
@GetMapping("/getMapItemId")
@Operation(summary = "获取节点id")
public CommonResult<String> getMapItemId() {
return success(String.valueOf(IdWorker.getId()));
}
// -- 前端给所有的节点信息 -
@PostMapping("/batchSaveOrEditOrDel")
@Operation(summary = "批量新增编辑删除节点")
@ -59,10 +46,10 @@ public class PositionMapItemController {
// -- 获取到对应地图的所有点位
List<PositionMapItemDO> oldList = positionMapItemService.getByMapId(positionMapId);
Map<Integer, List<PositionMapItemDO>> oldMap = oldList.stream().collect(Collectors.groupingBy(PositionMapItemDO::getType));
for (Map.Entry<Integer, List<NodeBaseDTO>> entry : map.entrySet()) {
int key = entry.getKey();
for (Integer key : NodeTypeEnum.getAllTypes()) {
List<NodeBaseDTO> nodeBaseDTOList = CollectionUtil.isEmpty(map.get(key)) ? Collections.emptyList() : map.get(key);
List<PositionMapItemDO> oldItemList = CollectionUtil.isEmpty(oldMap.get(key)) ? Collections.emptyList() : oldMap.get(key);
nodeProcessingContext.processNodesByStrategy(positionMapId, oldItemList, key, entry.getValue());
nodeProcessingContext.processNodesByStrategy(positionMapId, oldItemList, key, nodeBaseDTOList);
}
return success(true);
}
@ -88,18 +75,4 @@ public class PositionMapItemController {
.eqIfPresent(PositionMapItemDO::getLaneId, laneId));
return success(BeanUtils.toBean(list, PositionMapItemRespVO.class));
}
@GetMapping("/export-excel")
@Operation(summary = "导出仓库点位地图子表 Excel")
@PreAuthorize("@ss.hasPermission('system:position-map-item:export')")
@ApiAccessLog(operateType = EXPORT)
public void exportPositionMapItemExcel(@Valid PositionMapItemPageReqVO pageReqVO,
HttpServletResponse response) throws IOException {
pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
List<PositionMapItemDO> list = positionMapItemService.getPositionMapItemPage(pageReqVO).getList();
// 导出 Excel
ExcelUtils.write(response, "仓库点位地图子表.xls", "数据", PositionMapItemRespVO.class,
BeanUtils.toBean(list, PositionMapItemRespVO.class));
}
}

View File

@ -23,7 +23,7 @@ public class PositionMapLineDTO {
@Schema(description = "结束点id(点位子表id)", example = "15890")
private Long endPointId;
@Schema(description = "行走方法 0.直线 1.上左曲线2.上右曲线3.下左曲线 4.下右曲线")
@Schema(description = "行走方法 0.直线 1.曲线")
private Integer method;
@Schema(description = "方向 1.单向 2.双向", example = "15890")
@ -46,7 +46,38 @@ public class PositionMapLineDTO {
@Schema(description = "结束控制点y轴")
private String endControlY;
/**
* 开始点位x轴
*/
private String actualStartPointX;
/**
* 开始点位y轴
*/
private String actualStartPointY;
/**
* 结束点位x轴
*/
private String actualEndPointX;
/**
* 结束点位y轴
*/
private String actualEndPointY;
/**
* 开始控制点x轴
*/
private String actualBeginControlX;
/**
* 开始控制点y轴
*/
private String actualBeginControlY;
/**
* 结束控制点x轴
*/
private String actualEndControlX;
/**
* 结束控制点y轴
*/
private String actualEndControlY;
@Schema(description = "膨胀区域前")
private BigDecimal expansionZoneFront;

View File

@ -42,6 +42,12 @@ public class PositionMapItemRespVO {
@ExcelProperty("坐标y轴")
private String locationY;
@Schema(description = "实际坐标x轴")
private String actualLocationX;
@Schema(description = "实际坐标y轴")
private String actualLocationY;
@Schema(description = "类型 1.路径点位 2.库位点 3.充电桩 4.停车点 5.区域变更点 6.等待点 --- 后续补充", example = "1")
@ExcelProperty("类型 1.路径点位 2.库位点 3.充电桩 4.停车点 5.区域变更点 6.等待点 --- 后续补充")
private Integer type;

View File

@ -49,6 +49,30 @@ public class PositionMapLinePageReqVO extends PageParam {
@Schema(description = "结束控制点y轴", example = "15890")
private String endControlY;
@Schema(description = "实际开始点位x轴", example = "15890")
private String actualStartPointX;
@Schema(description = "实际开始点位y轴", example = "15890")
private String actualStartPointY;
@Schema(description = "实际结束点位x轴", example = "15890")
private String actualEndPointX;
@Schema(description = "实际结束点位y轴", example = "15890")
private String actualEndPointY;
@Schema(description = "实际开始控制点x轴", example = "15890")
private String actualBeginControlX;
@Schema(description = "实际开始控制点y轴", example = "15890")
private String actualBeginControlY;
@Schema(description = "实际结束控制点x轴", example = "15890")
private String actualEndControlX;
@Schema(description = "实际结束控制点y轴", example = "15890")
private String actualEndControlY;
@Schema(description = "膨胀区域前", example = "15890")
private BigDecimal expansionZoneFront;
@ -61,7 +85,7 @@ public class PositionMapLinePageReqVO extends PageParam {
@Schema(description = "膨胀区域右", example = "15890")
private BigDecimal expansionZoneRight;
@Schema(description = "行走方法 0.直线 1.上左曲线2.上右曲线3.下左曲线 4.下右曲线")
@Schema(description = "行走方法 0.直线 1.曲线")
private Integer method;
@Schema(description = "方向 1.单向 2.双向", example = "15890")

View File

@ -54,6 +54,30 @@ public class PositionMapLineRespVO {
@ExcelProperty("结束控制点y轴")
private String endControlY;
@Schema(description = "实际开始点位x轴", example = "15890")
private String actualStartPointX;
@Schema(description = "实际开始点位y轴", example = "15890")
private String actualStartPointY;
@Schema(description = "实际结束点位x轴", example = "15890")
private String actualEndPointX;
@Schema(description = "实际结束点位y轴", example = "15890")
private String actualEndPointY;
@Schema(description = "实际开始控制点x轴", example = "15890")
private String actualBeginControlX;
@Schema(description = "实际开始控制点y轴", example = "15890")
private String actualBeginControlY;
@Schema(description = "实际结束控制点x轴", example = "15890")
private String actualEndControlX;
@Schema(description = "实际结束控制点y轴", example = "15890")
private String actualEndControlY;
@Schema(description = "膨胀区域前", example = "15890")
@ExcelProperty("膨胀区域前")
private BigDecimal expansionZoneFront;
@ -70,8 +94,8 @@ public class PositionMapLineRespVO {
@ExcelProperty("膨胀区域右")
private BigDecimal expansionZoneRight;
@Schema(description = "行走方法 0.直线 1.上左曲线2.上右曲线3.下左曲线 4.下右曲线")
@ExcelProperty("行走方法 0.直线 1.上左曲线2.上右曲线3.下左曲线 4.下右曲线")
@Schema(description = "行走方法 0.直线 1.曲线")
@ExcelProperty("行走方法 0.直线 1.曲线")
private Integer method;
@Schema(description = "方向 1.单向 2.双向", example = "15890")

View File

@ -46,6 +46,30 @@ public class PositionMapLineSaveReqVO {
@Schema(description = "结束控制点y轴", example = "15890")
private String endControlY;
@Schema(description = "实际开始点位x轴", example = "15890")
private String actualStartPointX;
@Schema(description = "实际开始点位y轴", example = "15890")
private String actualStartPointY;
@Schema(description = "实际结束点位x轴", example = "15890")
private String actualEndPointX;
@Schema(description = "实际结束点位y轴", example = "15890")
private String actualEndPointY;
@Schema(description = "实际开始控制点x轴", example = "15890")
private String actualBeginControlX;
@Schema(description = "实际开始控制点y轴", example = "15890")
private String actualBeginControlY;
@Schema(description = "实际结束控制点x轴", example = "15890")
private String actualEndControlX;
@Schema(description = "实际结束控制点y轴", example = "15890")
private String actualEndControlY;
@Schema(description = "膨胀区域前", example = "15890")
private BigDecimal expansionZoneFront;
@ -58,7 +82,7 @@ public class PositionMapLineSaveReqVO {
@Schema(description = "膨胀区域右", example = "15890")
private BigDecimal expansionZoneRight;
@Schema(description = "行走方法 0.直线 1.上左曲线2.上右曲线3.下左曲线 4.下右曲线")
@Schema(description = "行走方法 0.直线 1.曲线")
private Integer method;
@Schema(description = "方向 1.单向 2.双向", example = "15890")

View File

@ -6,6 +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.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;
@ -17,6 +18,7 @@ import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import javax.annotation.security.PermitAll;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.io.IOException;
@ -120,4 +122,12 @@ public class RobotInformationController {
PageResult<RobotInformationPageRespVO> pageResult = informationService.getInformationPage(pageReqVO);
return success(BeanUtils.toBean(pageResult, RobotInformationPageRespVO.class));
}
@PostMapping("/test")
@Operation(summary = "测试")
@PermitAll
public CommonResult<Boolean> test(@RequestBody RobotStatusDTO dto) {
informationService.test(dto);
return success(true);
}
}

View File

@ -74,6 +74,38 @@ public class PositionMapLineDO extends BaseDO {
* 结束控制点y轴
*/
private String endControlY;
/**
* 实际开始点位x轴
*/
private String actualStartPointX;
/**
* 实际开始点位y轴
*/
private String actualStartPointY;
/**
* 实际结束点位x轴
*/
private String actualEndPointX;
/**
* 实际结束点位y轴
*/
private String actualEndPointY;
/**
* 实际开始控制点x轴
*/
private String actualBeginControlX;
/**
* 实际开始控制点y轴
*/
private String actualBeginControlY;
/**
* 实际结束控制点x轴
*/
private String actualEndControlX;
/**
* 实际结束控制点y轴
*/
private String actualEndControlY;
/**
* 膨胀区域前
*/
@ -91,7 +123,7 @@ public class PositionMapLineDO extends BaseDO {
*/
private BigDecimal expansionZoneRight;
/**
* 行走方法 0.直线 1.上左曲线2.上右曲线3.下左曲线 4.下右曲线
* 行走方法 0.直线 1.曲线
*/
private Integer method;
/**

View File

@ -42,7 +42,7 @@ public class DeviceStrategyImpl implements NodeProcessingStrategy {
});
List<DeviceInformationDO> oldList = deviceInformationService.getByMapId(positionMapId);
List<List<DeviceInformationDO>> list = CollectionUtils.diffList(oldList, newList,
List<List<DeviceInformationDO>> list = CollectionUtils.compareLists(oldList, newList,
(oldVal, newVal) -> ObjectUtil.equal(oldVal.getId(), newVal.getId()));
deviceInformationService.batchSaveOrEditOrDel(positionMapId, list);
}

View File

@ -55,7 +55,7 @@ public class HouseLocationStrategyImpl implements NodeProcessingStrategy {
});
List<WareHouseLocationDO> oldList = houseLocationService.getByMapId(positionMapId);
List<List<WareHouseLocationDO>> list = CollectionUtils.diffList(oldList, newList,
List<List<WareHouseLocationDO>> list = CollectionUtils.compareLists(oldList, newList,
(oldVal, newVal) -> ObjectUtil.equal(oldVal.getId(), newVal.getId()));
houseLocationService.batchSaveOrEditOrDel(positionMapId, list);
}

View File

@ -43,10 +43,10 @@ public class ParkingSpotStrategyImpl implements NodeProcessingStrategy {
parkingSpotDO.setPositionMapItemId(item.getId());
newList.add(parkingSpotDO);
item.setDataJson(JSONUtil.toJsonStr(parkingSpotDO));
});
});
List<ParkingSpotDO> oldList = parkingSpotService.getByMapId(positionMapId);
List<List<ParkingSpotDO>> list = CollectionUtils.diffList(oldList, newList,
List<List<ParkingSpotDO>> list = CollectionUtils.compareLists(oldList, newList,
(oldVal, newVal) -> ObjectUtil.equal(oldVal.getId(), newVal.getId()));
parkingSpotService.batchSaveOrEditOrDel(positionMapId, list);
}

View File

@ -12,13 +12,16 @@ import cn.iocoder.yudao.module.system.enums.common.ZeroOneEnum;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import org.springframework.validation.annotation.Validated;
import org.springframework.transaction.annotation.Transactional;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
@ -45,11 +48,11 @@ public class CommonConfigServiceImpl implements CommonConfigService {
CommonConfigDO config = BeanUtils.toBean(createReqVO, CommonConfigDO.class);
if (ZeroOneEnum.ONE.getType().equals(config.getConfigType())) {
CommonConfigVO chargeConfig= JSONUtil.toBean(config.getConfigStr(),CommonConfigVO.class);
CommonConfigVO chargeConfig = JSONUtil.toBean(config.getConfigStr(), CommonConfigVO.class);
//一次
if (ZeroOneEnum.ZERO.getType().equals(chargeConfig.getEveryDay())
&& ObjectUtil.isNotEmpty(chargeConfig.getScheduleChargeStartTime())) {
setOnceStartTimeConfig(config,chargeConfig);
setOnceStartTimeConfig(config, chargeConfig);
}
}
@ -60,6 +63,7 @@ public class CommonConfigServiceImpl implements CommonConfigService {
/**
* 设置一次的开始时间和结束时间
*
* @param config
* @param chargeConfig
*/
@ -69,8 +73,8 @@ public class CommonConfigServiceImpl implements CommonConfigService {
LocalDateTime nowEnd = LocalDateTime.now();
if (now.isAfter(chargeConfig.getScheduleChargeEndTime())) {
now.plusDays(1);
nowEnd.plusDays(1);
now = now.plusDays(1);
nowEnd = nowEnd.plusDays(1);
}
LocalDateTime s = LocalDateTime.of(now.getYear(), now.getMonth(), now.getDayOfMonth(),
@ -103,12 +107,12 @@ public class CommonConfigServiceImpl implements CommonConfigService {
CommonConfigDO updateObj = BeanUtils.toBean(updateReqVO, CommonConfigDO.class);
if (ZeroOneEnum.ONE.getType().equals(updateReqVO.getConfigType())) {
CommonConfigVO chargeConfig= JSONUtil.toBean(updateReqVO.getConfigStr(),CommonConfigVO.class);
CommonConfigVO chargeConfig = JSONUtil.toBean(updateReqVO.getConfigStr(), CommonConfigVO.class);
//一次
if (ZeroOneEnum.ZERO.getType().equals(chargeConfig.getEveryDay())
&& ObjectUtil.isNotEmpty(chargeConfig.getScheduleChargeStartTime())) {
setOnceStartTimeConfig(updateObj,chargeConfig);
}else if(ZeroOneEnum.ONE.getType().equals(chargeConfig.getEveryDay()) ) {
setOnceStartTimeConfig(updateObj, chargeConfig);
} else if (ZeroOneEnum.ONE.getType().equals(chargeConfig.getEveryDay())) {
JSONObject jsonObject = new JSONObject(updateObj.getConfigStr());
jsonObject.put("onceStartTime", "");
jsonObject.put("onceEndTime", "");

View File

@ -116,7 +116,7 @@ public class HouseAreaServiceImpl implements HouseAreaService {
}
// -- 这里去判断更新点位的线库信息
List<List<PositionMapItemDO>> allList = CollectionUtils.diffList(oldList, list,
List<List<PositionMapItemDO>> allList = CollectionUtils.compareLists(oldList, list,
(oldVal, newVal) -> ObjectUtil.equal(oldVal.getAreaId(), newVal.getAreaId()));
List<PositionMapItemDO> editList = new ArrayList<>();
if (CollUtil.isNotEmpty(allList.get(0))) {

View File

@ -100,7 +100,7 @@ public class WareHouseLaneServiceImpl extends ServiceImpl<WareHouseLaneMapper, W
}
// -- 这里去判断更新点位的线库信息
List<List<PositionMapItemDO>> allList = CollectionUtils.diffList(oldList, list,
List<List<PositionMapItemDO>> allList = CollectionUtils.compareLists(oldList, list,
(oldVal, newVal) -> ObjectUtil.equal(oldVal.getLaneId(), newVal.getLaneId()));
List<PositionMapItemDO> editList = new ArrayList<>();
if (CollUtil.isNotEmpty(allList.get(0))) {

View File

@ -121,7 +121,7 @@ public class PathPlanningServiceImpl implements PathPlanningService {
relatedPathNode.setType(PathTypeEnum.INIT.getType());
relatedPathNode.setControl_nodes(positionMapItemSynDTOS);
pathPlanningApi.synchronousLineObject(relatedPathNode, PathPlanningTopicConstant.SYNCHRONOUS_ALL_ITEM);
pathPlanningApi.synchronousLineObject(relatedPathNode, PathPlanningTopicConstant.SYNCHRONOUS_ALL_MAP_NODE);
}
}
@ -166,7 +166,7 @@ public class PathPlanningServiceImpl implements PathPlanningService {
relatedPathNode.setArea(positionMapDO.getArea());
relatedPathNode.setControl_nodes(list);
pathPlanningApi.synchronousLineObject(relatedPathNode, PathPlanningTopicConstant.ADD_MAP_POINT);
pathPlanningApi.synchronousLineObject(relatedPathNode, PathPlanningTopicConstant.ADD_MAP_LINE);
}
/**
@ -195,7 +195,7 @@ public class PathPlanningServiceImpl implements PathPlanningService {
ids.add(data.getId());
relatedPathNode.setIds(ids);
pathPlanningApi.synchronousLineObject(relatedPathNode, PathPlanningTopicConstant.DELETE_MAP_POINT);
pathPlanningApi.synchronousLineObject(relatedPathNode, PathPlanningTopicConstant.DELETE_MAP_LINE);
}
@ -240,7 +240,7 @@ public class PathPlanningServiceImpl implements PathPlanningService {
relatedPathNode.setType(PathTypeEnum.UPDATE.getType());
relatedPathNode.setControl_nodes(list);
pathPlanningApi.synchronousLineObject(relatedPathNode, PathPlanningTopicConstant.UPDATE_MAP_POINT);
pathPlanningApi.synchronousLineObject(relatedPathNode, PathPlanningTopicConstant.UPDATE_MAP_LINE);
}
/**
@ -279,7 +279,7 @@ public class PathPlanningServiceImpl implements PathPlanningService {
PositionMapItemPathDTO.setType(PathTypeEnum.ADD.getType());
PositionMapItemPathDTO.setControl_nodes(Arrays.asList(build));
pathPlanningApi.synchronousLineObject(PositionMapItemPathDTO, PathPlanningTopicConstant.ADD_MAP_ITEM);
pathPlanningApi.synchronousLineObject(PositionMapItemPathDTO, PathPlanningTopicConstant.ADD_MAP_NODE);
}
/**
@ -312,7 +312,7 @@ public class PathPlanningServiceImpl implements PathPlanningService {
PositionMapItemPathDTO.setType(PathTypeEnum.DELETE.getType());
PositionMapItemPathDTO.setIds(Arrays.asList(data.getId()));
pathPlanningApi.synchronousLineObject(PositionMapItemPathDTO, PathPlanningTopicConstant.DELETE_MAP_ITEM);
pathPlanningApi.synchronousLineObject(PositionMapItemPathDTO, PathPlanningTopicConstant.DELETE_MAP_NODE);
}
@Override
@ -347,7 +347,7 @@ public class PathPlanningServiceImpl implements PathPlanningService {
PositionMapItemPathDTO.setType(PathTypeEnum.UPDATE.getType());
PositionMapItemPathDTO.setControl_nodes(Arrays.asList(build));
pathPlanningApi.synchronousLineObject(PositionMapItemPathDTO, PathPlanningTopicConstant.UPDATE_MAP_ITEM);
pathPlanningApi.synchronousLineObject(PositionMapItemPathDTO, PathPlanningTopicConstant.UPDATE_MAP_NODE);
}
public PositionMapLineDTO setPositionMapLineDTOData(PositionMapLineDTO positionMapLineDO) {
@ -391,7 +391,7 @@ public class PathPlanningServiceImpl implements PathPlanningService {
relatedPathNode.setControl_nodes(list);
pathPlanningApi.synchronousPointToPP(relatedPathNode, PathPlanningTopicConstant.SYNCHRONOUS_ALL_MAP_POINT);
pathPlanningApi.synchronousPointToPP(relatedPathNode, PathPlanningTopicConstant.SYNCHRONOUS_ALL_MAP_LINE);
});
}

View File

@ -6,7 +6,6 @@ import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
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.houselocation.WareHouseLocationDO;
import cn.iocoder.yudao.module.system.dal.dataobject.positionmap.PositionMapLineDO;
import cn.iocoder.yudao.module.system.dal.mysql.positionmap.PositionMapLineMapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
@ -51,8 +50,10 @@ public class PositionMapLineServiceImpl extends ServiceImpl<PositionMapLineMappe
@Override
public void createOrEditPositionMapLine(Long positionMapId, List<PositionMapLineSaveReqVO> createReqVO) {
List<PositionMapLineDO> newList = BeanUtils.toBean(createReqVO, PositionMapLineDO.class);
newList.forEach(a -> a.setPositionMapId(positionMapId));
// todo 判断是否有重复数据
List<PositionMapLineDO> oldList = this.getByMapId(positionMapId);
List<List<PositionMapLineDO>> list = CollectionUtils.diffList(oldList, newList,
List<List<PositionMapLineDO>> list = CollectionUtils.compareLists(oldList, newList,
(oldVal, newVal) -> ObjectUtil.equal(oldVal.getId(), newVal.getId()));
this.batchSaveOrEditOrDel(list);
}

View File

@ -1,18 +1,22 @@
package cn.iocoder.yudao.module.system.service.robot;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.module.system.api.robot.dto.RobotStatusDTO;
import cn.iocoder.yudao.module.system.api.robot.vo.RobotInformationVO;
import cn.iocoder.yudao.module.system.controller.admin.robot.vo.*;
import cn.iocoder.yudao.module.system.dal.dataobject.robot.RobotInformationDO;
import com.baomidou.mybatisplus.extension.service.IService;
import javax.validation.Valid;
import java.util.List;
import java.util.Map;
/**
* 车辆信息 Service 接口
*
* @author 陈宾顺
*/
public interface RobotInformationService {
public interface RobotInformationService extends IService<RobotInformationDO> {
/**
* 创建车辆信息
@ -80,4 +84,24 @@ public interface RobotInformationService {
* @return
*/
String getRobotNoByMac(String mac);
/**
* @param dto
*/
void test(@Valid RobotStatusDTO dto);
/**
* 获取所有的车辆信息 (缓存中获取)
*
* @return
*/
Map<String, RobotInformationVO> getAllRobotByRedis();
/**
* 通过macAddress 获取设备基础信息 - 然后存入到redis中
*
* @param macAddress
* @return
*/
RobotInformationVO getRobotByRedis(String macAddress);
}

View File

@ -5,28 +5,37 @@ 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.api.robot.vo.RobotInformationVO;
import cn.iocoder.yudao.module.system.constant.robot.RobotTaskChcheConstant;
import cn.iocoder.yudao.module.system.controller.admin.robot.vo.*;
import cn.iocoder.yudao.module.system.dal.dataobject.positionmap.PositionMapDO;
import cn.iocoder.yudao.module.system.dal.dataobject.robot.RobotInformationDO;
import cn.iocoder.yudao.module.system.dal.dataobject.robot.RobotModelDO;
import cn.iocoder.yudao.module.system.dal.dataobject.robot.RobotTaskDetailDO;
import cn.iocoder.yudao.module.system.dal.mysql.positionmap.PositionMapMapper;
import cn.iocoder.yudao.module.system.dal.mysql.robot.RobotInformationMapper;
import cn.iocoder.yudao.module.system.dal.mysql.robot.RobotModelMapper;
import cn.iocoder.yudao.module.system.dal.mysql.robot.RobotTaskDetailMapper;
import cn.iocoder.yudao.module.system.enums.robot.*;
import cn.iocoder.yudao.module.system.enums.robot.CommandTypeEnum;
import cn.iocoder.yudao.module.system.enums.robot.RobotStatusEnum;
import cn.iocoder.yudao.module.system.enums.robot.RobotTaskModelEnum;
import cn.iocoder.yudao.module.system.enums.robot.information.RobotStatisticsTypeEnum;
import cn.iocoder.yudao.module.system.util.redis.RedisUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.*;
@ -38,7 +47,7 @@ import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.*;
*/
@Service
@Validated
public class RobotInformationServiceImpl implements RobotInformationService {
public class RobotInformationServiceImpl extends ServiceImpl<RobotInformationMapper, RobotInformationDO> implements RobotInformationService {
@Resource
private RobotInformationMapper informationMapper;
@ -54,6 +63,10 @@ public class RobotInformationServiceImpl implements RobotInformationService {
@Resource
private RedisUtil redisUtil;
@Resource
private RequestProcessor processor;
// -- 获取所有的设备信息key
public static final String key = RobotTaskChcheConstant.ROBOT_GET_ROBOT_INFO;
@Override
public Long createInformation(RobotInformationSaveReqVO createReqVO) {
@ -281,7 +294,7 @@ public class RobotInformationServiceImpl implements RobotInformationService {
Integer fault = 0;
//0待命1任务中2锁定3离线4:充电中5:故障
for (RobotInformationDO v : existRobot) {
String pose2dKey = RobotTaskChcheConstant.ROBOT_INFORMATION_POSE_BAT_SOC +v.getMacAddress();
String pose2dKey = RobotTaskChcheConstant.ROBOT_INFORMATION_POSE_BAT_SOC + v.getMacAddress();
Object object = redisUtil.get(pose2dKey);
if (ObjectUtil.isEmpty(object)) {
@ -294,7 +307,7 @@ public class RobotInformationServiceImpl implements RobotInformationService {
doLock++;
}
//设置异常
String errorLevelKey = RobotTaskChcheConstant.ROBOT_ERROR_LEVEL +v.getMacAddress();
String errorLevelKey = RobotTaskChcheConstant.ROBOT_ERROR_LEVEL + v.getMacAddress();
Object errorLevel = redisUtil.get(errorLevelKey);
if (ObjectUtil.isNotEmpty(errorLevel) && Integer.valueOf(errorLevel.toString()).intValue() >= 3) {
fault++;
@ -303,10 +316,10 @@ public class RobotInformationServiceImpl implements RobotInformationService {
if (RobotStatusEnum.STAND_BY.getType().equals(v.getRobotStatus())) {
//待命中
standby++;
}else if (RobotStatusEnum.CHARGE.getType().equals(v.getRobotStatus())) {
} else if (RobotStatusEnum.CHARGE.getType().equals(v.getRobotStatus())) {
//充电中
charge++;
}else {
} else {
//任务中
inTask++;
}
@ -365,4 +378,66 @@ public class RobotInformationServiceImpl implements RobotInformationService {
return "";
}
@Override
public void test(RobotStatusDTO robotStatusDataDTO) {
TenantContextHolder.setTenantId(1L);
if (ObjectUtil.isEmpty(robotStatusDataDTO) || ObjectUtil.isEmpty(robotStatusDataDTO.getMac())) {
return;
}
// -- 通过mac 地址获取车辆信息 - (并且加入到缓存中)
Map<String, RobotInformationVO> robotInformationVOS = this.getAllRobotByRedis();
RobotInformationVO robotInformationVO = robotInformationVOS.get(robotStatusDataDTO.getMac());
if (robotInformationVO == null) {
robotInformationVO = this.getRobotByRedis(robotStatusDataDTO.getMac());
}
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());
robotInformationVO.setPose2d(robotStatusDataPoseDTO);
// 模拟请求
processor.handleRequest(robotStatusDataDTO.getData().getFloor_zone().getFloor() + "_" + robotStatusDataDTO.getData().getFloor_zone().getArea(),
robotStatusDataDTO.getMac(), JSONUtil.toJsonStr(robotInformationVO));
}
@Override
public Map<String, RobotInformationVO> getAllRobotByRedis() {
Object o = redisUtil.get(key);
if (ObjectUtil.isNotEmpty(o)) {
// 化作列表
List<RobotInformationVO> list = JSONUtil.toList(o.toString(), RobotInformationVO.class);
return list.stream().collect(Collectors.toMap(RobotInformationVO::getMacAddress, Function.identity()));
} else {
List<RobotInformationDO> allRobotInfoList = this.list();
List<RobotInformationVO> list = BeanUtil.copyToList(allRobotInfoList, RobotInformationVO.class);
redisUtil.set(key, JSONUtil.toJsonStr(list));
return list.stream().collect(Collectors.toMap(RobotInformationVO::getMacAddress, Function.identity()));
}
}
@Override
public RobotInformationVO getRobotByRedis(String macAddress) {
// todo -- 如果说有一个设备的mac 一直都不在库里 会出现缓存穿透的问题 - 后续如果出现这种情况的话 - 考虑将null值也存入到缓存中
RobotInformationDO item = this.getOne(new LambdaQueryWrapper<RobotInformationDO>().eq(RobotInformationDO::getMacAddress, macAddress));
// -- 将获取到的存入到redis中
if (ObjectUtil.isNotEmpty(item)) {
RobotInformationVO vo = BeanUtil.toBean(item, RobotInformationVO.class);
List<RobotInformationVO> list = new ArrayList<>();
Object o = redisUtil.get(key);
if (ObjectUtil.isNotEmpty(o)) {
list = JSONUtil.toList(o.toString(), RobotInformationVO.class);
}
list.add(vo);
redisUtil.set(key, JSONUtil.toJsonStr(list));
return vo;
}
return new RobotInformationVO();
}
}

View File

@ -24,6 +24,7 @@ import cn.iocoder.yudao.module.system.dal.mysql.positionmap.PositionMapItemMappe
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.common.ZeroOneEnum;
import cn.iocoder.yudao.module.system.enums.config.CommandConfigTypeEnum;
import cn.iocoder.yudao.module.system.enums.robot.*;
import cn.iocoder.yudao.module.system.enums.robot.charge.ChargeModelEnum;
@ -34,6 +35,7 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.tuple.ImmutablePair;
import org.apache.commons.lang3.tuple.Pair;
import org.bouncycastle.pqc.crypto.util.PQCOtherInfoGenerator;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
@ -116,7 +118,7 @@ public class DistributeTasksServiceImpl implements DistributeTasksService {
// List<RobotTaskDetailDO> cycleTaskDetails = robotTaskMapper.getCycleTaskDetails();
//任务下发给机器人
distributeTasks(robots,taskDetailDOS);
distributeTasks(robots, taskDetailDOS);
}
/**
@ -125,24 +127,21 @@ public class DistributeTasksServiceImpl implements DistributeTasksService {
@Override
@Transactional(rollbackFor = Exception.class)
public Pair<List<RobotInformationDO>, List<RobotTaskDetailDO>> getRobotAndTaskDetails() {
TenantContextHolder.setTenantId(1L);
Pair<List<RobotInformationDO>, List<RobotTaskDetailDO>> pair = Pair.of(new ArrayList<>(), new ArrayList<>());
CommonConfigDO commonConfigDO = configMapper.selectOne(new LambdaQueryWrapper<CommonConfigDO>()
.eq(CommonConfigDO::getConfigType, CommandConfigTypeEnum.CHARG_CONFIG.getType()));
CommonConfigVO chargeConfig= JSONUtil.toBean(commonConfigDO.getConfigStr(),CommonConfigVO.class);
LocalDateTime now = LocalDateTime.now();
if ((ObjectUtil.isNotEmpty(chargeConfig.getScheduleChargeEndTime()) &&
(ObjectUtil.isNotEmpty(chargeConfig.getScheduleChargeStartTime())))
&& (now.isBefore(chargeConfig.getScheduleChargeEndTime()) && now.isAfter(chargeConfig.getScheduleChargeStartTime()))) {
log.info("充电时间,不派发任务");
Boolean needDoCharge = needDoCharge(commonConfigDO);
if (needDoCharge) {
log.info("所有机器人都需要去执行充电任务");
return pair;
}
TenantContextHolder.setTenantId(1L);
List<RobotInformationDO> robots = robotInformationMapper.selectList(new LambdaQueryWrapperX<RobotInformationDO>()
.in(RobotInformationDO::getRobotStatus, RobotStatusEnum.STAND_BY.getType(),RobotStatusEnum.CHARGE.getType())
.eq(RobotInformationDO::getRobotTaskModel, RobotTaskModelEnum.NORMAL.getType())
.orderByDesc(RobotInformationDO::getUpdateTime));
.in(RobotInformationDO::getRobotStatus, RobotStatusEnum.STAND_BY.getType(), RobotStatusEnum.CHARGE.getType())
.eq(RobotInformationDO::getRobotTaskModel, RobotTaskModelEnum.NORMAL.getType()));
if (robots.isEmpty()) {
log.info("暂无空闲的机器人");
@ -150,8 +149,8 @@ public class DistributeTasksServiceImpl implements DistributeTasksService {
}
for (RobotInformationDO robot : robots) {
String taskStatusKey = RobotTaskChcheConstant.ROBOT_TASK_STATUS +robot.getMacAddress();
String cargoDetectedKey = RobotTaskChcheConstant.ROBOT_CARGO_DETECTED +robot.getMacAddress();
String taskStatusKey = RobotTaskChcheConstant.ROBOT_TASK_STATUS + robot.getMacAddress();
String cargoDetectedKey = RobotTaskChcheConstant.ROBOT_CARGO_DETECTED + robot.getMacAddress();
Object taskStatus = redisUtil.get(taskStatusKey);
if (ObjectUtil.isEmpty(taskStatus) || RobotStatusCodeConstant.TASK_STATUS_RUNNING.equals(taskStatus.toString())) {
robot.setRobotStatus(RobotStatusEnum.DOING.getType());
@ -164,9 +163,10 @@ public class DistributeTasksServiceImpl implements DistributeTasksService {
continue;
}
//手动充电的机器人状态是待命
//自动充电的车子电量到达设定的阀值也能执行充电任务
if (ChargeTypeEnum.AUTOMATIC.getType().equals(robot.getChargeType())
&& RobotStatusEnum.CHARGE.getType().equals(robot.getRobotStatus())) {
setRobotStatus(commonConfigDO,robot);
&& RobotStatusEnum.CHARGE.getType().equals(robot.getRobotStatus())) {
setRobotStatus(commonConfigDO, robot);
}
}
@ -175,23 +175,37 @@ public class DistributeTasksServiceImpl implements DistributeTasksService {
.collect(Collectors.toList());
if (robots.isEmpty()) {
log.info("暂无可用的机器人");
log.info("暂无可用的机器人,可能正在充电,可能机器人有任务");
return pair;
}
//拼接任务id
List<Long> detailDongIds = robotTaskDetailMapper.getDoingTaskIds();
List<Long> montageTaskIds = robotTaskMapper.getUnDoAndDoingTaskIds(MontageTaskEnum.YES.getType(),detailDongIds);
/*List<Long> detailDongIds = robotTaskDetailMapper.getDoingTaskIds();
List<Long> montageTaskIds = robotTaskMapper.getUnDoAndDoingTaskIds(MontageTaskEnum.YES.getType(), detailDongIds);
//不拼接的任务id
List<Long> singleTaskIds = robotTaskMapper.getUnDoAndDoingTaskIds(MontageTaskEnum.NO.getType(),new ArrayList<>());
List<Long> singleTaskIds = robotTaskMapper.getUnDoAndDoingTaskIds(MontageTaskEnum.NO.getType(), new ArrayList<>());*/
List<RobotTaskDO> taskDOList = robotTaskMapper.selectList(new LambdaQueryWrapper<RobotTaskDO>()
.in(RobotTaskDO::getTaskStatus, RobotTaskStatusEnum.DOING.getType(), RobotTaskStatusEnum.NEW.getType()));
//拼接
List<Long> montageTaskIds =taskDOList.stream()
.filter(v -> MontageTaskEnum.YES.getType().equals(v.getMontageTask()))
.map(RobotTaskDO::getId)
.collect(Collectors.toList());
//不拼接
List<Long> singleTaskIds =taskDOList.stream()
.filter(v -> MontageTaskEnum.YES.getType().equals(v.getMontageTask()))
.map(RobotTaskDO::getId)
.collect(Collectors.toList());
if (ObjectUtil.isEmpty(montageTaskIds) && ObjectUtil.isEmpty(singleTaskIds)) {
log.info("暂无需要处理的主任务");
return pair;
}
List<RobotTaskDetailDO> taskDetailDOS = getTaskDetail(montageTaskIds,singleTaskIds);
List<RobotTaskDetailDO> taskDetailDOS = getTaskDetail(montageTaskIds, singleTaskIds);
if (taskDetailDOS.isEmpty()) {
log.info("暂无需要处理的明细任务");
@ -200,24 +214,51 @@ public class DistributeTasksServiceImpl implements DistributeTasksService {
return ImmutablePair.of(robots, taskDetailDOS);
}
/**
* true 需要去充电
*
* @param commonConfigDO
* @return
*/
public Boolean needDoCharge(CommonConfigDO commonConfigDO) {
if (ObjectUtil.isEmpty(commonConfigDO) || ObjectUtil.isEmpty(commonConfigDO.getConfigStr())) {
return false;
}
CommonConfigVO chargeConfig = JSONUtil.toBean(commonConfigDO.getConfigStr(), CommonConfigVO.class);
LocalDateTime now = LocalDateTime.now();
if (ZeroOneEnum.ZERO.getType().equals(chargeConfig.getEveryDay())
&& now.isAfter(chargeConfig.getOnceStartTime()) && now.isBefore(chargeConfig.getOnceEndTime())) {
return true;
} else if (ZeroOneEnum.ONE.getType().equals(chargeConfig.getEveryDay())
&& now.isBefore(chargeConfig.getScheduleChargeEndTime())
&& now.isAfter(chargeConfig.getScheduleChargeStartTime())) {
return true;
}
return false;
}
/**
* 设置机器人的状态
*
* @param commonConfigDO
* @param robot
*/
private void setRobotStatus(CommonConfigDO commonConfigDO, RobotInformationDO robot) {
String pose2dKey = RobotTaskChcheConstant.ROBOT_INFORMATION_POSE_BAT_SOC +robot.getMacAddress();
String chargeModelKey = RobotTaskChcheConstant.ROBOT_CHARGE_MODEL +robot.getRobotNo();
String pose2dKey = RobotTaskChcheConstant.ROBOT_INFORMATION_POSE_BAT_SOC + robot.getMacAddress();
String chargeModelKey = RobotTaskChcheConstant.ROBOT_CHARGE_MODEL + robot.getRobotNo();
Object chargeModelCache = redisUtil.get(chargeModelKey);
Object poseCache = redisUtil.get(pose2dKey);
RobotStatusDataPoseDTO dataPoseDTO= JSON.parseObject((String)poseCache, RobotStatusDataPoseDTO.class);
log.info("机器人编号:{} ,信息: {}",robot.getRobotNo(),JSON.toJSONString(dataPoseDTO));
RobotStatusDataPoseDTO dataPoseDTO = JSON.parseObject((String) poseCache, RobotStatusDataPoseDTO.class);
log.info("机器人编号:{} ,信息: {}", robot.getRobotNo(), JSON.toJSONString(dataPoseDTO));
if (ObjectUtil.isEmpty(commonConfigDO) || ObjectUtil.isEmpty(poseCache) || ObjectUtil.isEmpty(dataPoseDTO.getBat_soc())) {
return;
}
CommonConfigVO chargeConfig=JSONUtil.toBean(commonConfigDO.getConfigStr(),CommonConfigVO.class);
CommonConfigVO chargeConfig = JSONUtil.toBean(commonConfigDO.getConfigStr(), CommonConfigVO.class);
//车子剩余电量
BigDecimal robotRemainingElectricity = new BigDecimal(dataPoseDTO.getBat_soc());
@ -230,7 +271,7 @@ public class DistributeTasksServiceImpl implements DistributeTasksService {
} else if (ObjectUtil.isNotEmpty(chargeModelCache) && ChargeModelEnum.FULL.getType().equals((Integer) chargeModelCache)) {
robotEndElectricity = new BigDecimal(fullElectricity);
} else if (ObjectUtil.isNotEmpty(chargeModelCache) && ChargeModelEnum.CHANCE.getType().equals((Integer) chargeModelCache)) {
robotEndElectricity = new BigDecimal(String.valueOf(chargeConfig.getChanceChargeEnd()));
robotEndElectricity = new BigDecimal(String.valueOf(chargeConfig.getChanceChargeEnd()));
} else {
robotEndElectricity = new BigDecimal(String.valueOf(chargeConfig.getEndAutoCharge()));
}
@ -242,14 +283,15 @@ public class DistributeTasksServiceImpl implements DistributeTasksService {
/**
* 获取明细
* @param montageTaskIds
* @param singleTaskIds
*
* @param montageTaskIds 拼接
* @param singleTaskIds 不拼接
* @return
*/
private List<RobotTaskDetailDO> getTaskDetail(List<Long> montageTaskIds, List<Long> singleTaskIds) {
if (ObjectUtil.isNotEmpty(montageTaskIds) && ObjectUtil.isEmpty(singleTaskIds)) {
return robotTaskDetailMapper.getMontageUnDoTask(montageTaskIds);
} else if (ObjectUtil.isEmpty(montageTaskIds) && ObjectUtil.isNotEmpty(singleTaskIds) ) {
} else if (ObjectUtil.isEmpty(montageTaskIds) && ObjectUtil.isNotEmpty(singleTaskIds)) {
return robotTaskDetailMapper.getSingleUnDoTask(singleTaskIds);
}
return robotTaskDetailMapper.getUnDoTaskDetail(montageTaskIds, singleTaskIds);
@ -257,6 +299,7 @@ public class DistributeTasksServiceImpl implements DistributeTasksService {
/**
* 下发任务给机器人
*
* @param robots
* @param taskDetailDOS
*/
@ -279,7 +322,7 @@ public class DistributeTasksServiceImpl implements DistributeTasksService {
RobotTaskTypeEnum robotTaskType = RobotTaskTypeEnum.getRobotTaskType(taskDetailDO.getTaskType());
switch (robotTaskType) {
case TAKE_RELEASE:
doTakeReleaseDistribute(taskDetailDO, robots,robotTaskDOS,taskIds,updateTaskDetails,robotNos,doingLocationIds);
doTakeReleaseDistribute(taskDetailDO, robots, robotTaskDOS, taskIds, updateTaskDetails, robotNos, doingLocationIds);
break;
/*case PARK:
doParkDistribute(taskDetailDO, robots,robotTaskDOS);
@ -326,67 +369,72 @@ public class DistributeTasksServiceImpl implements DistributeTasksService {
robotTaskDetailMapper.updateBatch(updateTaskDetails);
}
if (ObjectUtil.isNotEmpty(robotNos)) {
robotInformationMapper.updateRobotListStatus(robotNos,RobotStatusEnum.DOING.getType());
robotInformationMapper.updateRobotListStatus(robotNos, RobotStatusEnum.DOING.getType());
}
}
/**
* 检测托盘类型
*
* @param taskDetailDO
* @param robots
* @param robotTaskDOS
*/
@Transactional(rollbackFor = Exception.class)
public void doDetectingTraysDistribute(RobotTaskDetailDO taskDetailDO, List<RobotInformationDO> robots,
List<RobotAcceptTaskDTO> robotTaskDOS) {
List<RobotAcceptTaskDTO> robotTaskDOS) {
}
/**
* 扫描码
*
* @param taskDetailDO
* @param robots
* @param robotTaskDOS
*/
@Transactional(rollbackFor = Exception.class)
public void doScanDistribute(RobotTaskDetailDO taskDetailDO, List<RobotInformationDO> robots,
List<RobotAcceptTaskDTO> robotTaskDOS) {
List<RobotAcceptTaskDTO> robotTaskDOS) {
}
/**
* 仅放货
*
* @param taskDetailDO
* @param robots
* @param robotTaskDOS
*/
@Transactional(rollbackFor = Exception.class)
public void doReleaseDistribute(RobotTaskDetailDO taskDetailDO, List<RobotInformationDO> robots,
List<RobotAcceptTaskDTO> robotTaskDOS) {
List<RobotAcceptTaskDTO> robotTaskDOS) {
}
/**
* 取放货
*
* @param taskDetailDO
* @param robots
* @param robotTaskDOS
*/
@Transactional(rollbackFor = Exception.class)
public void doTakeDistribute(RobotTaskDetailDO taskDetailDO, List<RobotInformationDO> robots,
List<RobotAcceptTaskDTO> robotTaskDOS) {
List<RobotAcceptTaskDTO> robotTaskDOS) {
}
/**
* 移动
*
* @param taskDetailDO
* @param robots
* @param robotTaskDOS
*/
@Transactional(rollbackFor = Exception.class)
public void doMoveDistribute(RobotTaskDetailDO taskDetailDO, List<RobotInformationDO> robots,
List<RobotAcceptTaskDTO> robotTaskDOS) {
List<RobotAcceptTaskDTO> robotTaskDOS) {
String macAddress = "";
String robotNo = taskDetailDO.getRobotNo();
if (ObjectUtil.isNotEmpty(taskDetailDO.getRobotNo())) {
@ -395,7 +443,7 @@ public class DistributeTasksServiceImpl implements DistributeTasksService {
.map(RobotInformationDO::getMacAddress)
.findFirst()
.orElse("");
if (ObjectUtil.isEmpty(macAddress) ) {
if (ObjectUtil.isEmpty(macAddress)) {
return;
}
} else {
@ -406,7 +454,7 @@ public class DistributeTasksServiceImpl implements DistributeTasksService {
RobotAcceptTaskDTO robotTaskDO = new RobotAcceptTaskDTO();
robotTaskDO.setOrder_id(taskDetailDO.getId().toString());
robotTaskDO.setOrder_type("出库");//未定
robotTaskDO.setTopic(RobotTopicConstant.ROBOT_TASK_TOPIC+macAddress);
robotTaskDO.setTopic(RobotTopicConstant.ROBOT_TASK_TOPIC + macAddress);
//1
RobotAcceptTaskData taskOne = new RobotAcceptTaskData();
@ -434,30 +482,32 @@ public class DistributeTasksServiceImpl implements DistributeTasksService {
robotTaskDO.setData(data);
robotTaskDOS.add(robotTaskDO);
updateTaskStatus(robotNo,taskDetailDO);
updateTaskStatus(robotNo, taskDetailDO);
}
/**
* 充电
*
* @param taskDetailDO
* @param robots
* @param robotTaskDOS
*/
@Transactional(rollbackFor = Exception.class)
public void doChargeDistribute(RobotTaskDetailDO taskDetailDO, List<RobotInformationDO> robots,
List<RobotAcceptTaskDTO> robotTaskDOS) {
List<RobotAcceptTaskDTO> robotTaskDOS) {
}
/**
* 停车
*
* @param taskDetailDO
* @param robots
* @param robotTaskDOS
*/
@Transactional(rollbackFor = Exception.class)
public void doParkDistribute(RobotTaskDetailDO taskDetailDO, List<RobotInformationDO> robots,
List<RobotAcceptTaskDTO> robotTaskDOS) {
List<RobotAcceptTaskDTO> robotTaskDOS) {
String macAddress = "";
String robotNo = taskDetailDO.getRobotNo();
if (ObjectUtil.isNotEmpty(taskDetailDO.getRobotNo())) {
@ -466,7 +516,7 @@ public class DistributeTasksServiceImpl implements DistributeTasksService {
.map(RobotInformationDO::getMacAddress)
.findFirst()
.orElse("");
if (ObjectUtil.isEmpty(macAddress) ) {
if (ObjectUtil.isEmpty(macAddress)) {
return;
}
}
@ -474,7 +524,7 @@ public class DistributeTasksServiceImpl implements DistributeTasksService {
RobotAcceptTaskDTO robotTaskDO = new RobotAcceptTaskDTO();
robotTaskDO.setOrder_id(taskDetailDO.getId().toString());
robotTaskDO.setOrder_type("出库");//未定
robotTaskDO.setTopic(RobotTopicConstant.ROBOT_TASK_TOPIC+macAddress);
robotTaskDO.setTopic(RobotTopicConstant.ROBOT_TASK_TOPIC + macAddress);
RobotAcceptTaskData taskOne = new RobotAcceptTaskData();
taskOne.setSerial("1");
@ -490,28 +540,29 @@ public class DistributeTasksServiceImpl implements DistributeTasksService {
final String mac = macAddress;
robots.removeIf(v -> v.getMacAddress().equals(mac));
updateTaskStatus(robotNo,taskDetailDO);
updateTaskStatus(robotNo, taskDetailDO);
}
/**
* 取放货
*
* @param taskDetailDO
* @param robots
* @param robotTaskDOS
*/
@Transactional(rollbackFor = Exception.class)
public void doTakeReleaseDistribute(RobotTaskDetailDO taskDetailDO, List<RobotInformationDO> robots,
List<RobotAcceptTaskDTO> robotTaskDOS,Set<Long> taskIdSet,
List<RobotTaskDetailDO> updateTaskDetail, Set<String> robotNos
,Set<Long> doingLocationIds) {
List<RobotAcceptTaskDTO> robotTaskDOS, Set<Long> taskIdSet,
List<RobotTaskDetailDO> updateTaskDetail, Set<String> robotNos
, Set<Long> doingLocationIds) {
WareHouseLocationDO query = WareHouseLocationDO.builder().id(taskDetailDO.getFromLocationId()).build();
WareHouseLocationDO fromLocation = locationMapper.queryAllByLimit(query);
WareHouseLocationDO toQuery = WareHouseLocationDO.builder().id(taskDetailDO.getToLocationId()).build();
WareHouseLocationDO toLocation = locationMapper.queryAllByLimit(toQuery);
Pair<String,String> pair = getMadAddressRobotNo(taskDetailDO,robots,fromLocation,toLocation);
Pair<String, String> pair = getMadAddressRobotNo(taskDetailDO, robots, fromLocation, toLocation);
String macAddress = pair.getLeft();
String robotNo = pair.getRight();
@ -521,11 +572,11 @@ public class DistributeTasksServiceImpl implements DistributeTasksService {
}
// 取货/放货 校验有没有其他库位挡住
Boolean fromCanMove = checkCanMove(fromLocation,doingLocationIds);
Boolean fromCanMove = checkCanMove(fromLocation, doingLocationIds);
if (!fromCanMove) {
return;
}
Boolean toCanMove = checkCanMove(toLocation,doingLocationIds);
Boolean toCanMove = checkCanMove(toLocation, doingLocationIds);
if (!toCanMove) {
return;
}
@ -533,7 +584,7 @@ public class DistributeTasksServiceImpl implements DistributeTasksService {
RobotAcceptTaskDTO robotTaskDO = new RobotAcceptTaskDTO();
robotTaskDO.setOrder_id(taskDetailDO.getId().toString());
robotTaskDO.setOrder_type("出库");//未定
robotTaskDO.setTopic(RobotTopicConstant.ROBOT_TASK_TOPIC+macAddress);
robotTaskDO.setTopic(RobotTopicConstant.ROBOT_TASK_TOPIC + macAddress);
//1
RobotAcceptTaskData taskOne = new RobotAcceptTaskData();
@ -590,7 +641,6 @@ public class DistributeTasksServiceImpl implements DistributeTasksService {
taskSeven.setCommand_type(CommandTypeEnum.MOVE_TO_PALLET_POSE.getType());
//8
RobotAcceptTaskData taskEigth = new RobotAcceptTaskData();
taskEigth.setSerial("7");
@ -620,7 +670,7 @@ public class DistributeTasksServiceImpl implements DistributeTasksService {
.laneId(-2l)
.build();
List<WareHouseLocationDO> releaseStockList =
locationMapper.selectLocations(ware,new ArrayList<>(),new HashSet<>());
locationMapper.selectLocations(ware, new ArrayList<>(), new HashSet<>());
for (WareHouseLocationDO wareHouseLocationDO : releaseStockList) {
Pose2ds pose = positionMapItemMapper.selectByLocationId(wareHouseLocationDO.getId());
pose2dsNight.add(pose);
@ -720,6 +770,7 @@ public class DistributeTasksServiceImpl implements DistributeTasksService {
/**
* 校验当前库位能否取放
*
* @param fromLocation
* @return false : 有货不能移动 true: 没货 能移动
*/
@ -734,7 +785,7 @@ public class DistributeTasksServiceImpl implements DistributeTasksService {
.collect(Collectors.toList());
if (ObjectUtil.isNotEmpty(locationDOS)) {
// todo 后续记录到异常表
log.info("普通库位--库位上有其他货物, 库位号:{} ,无法进行移动 :{}",fromLocation.getLocationNo() ,locationDOS);
log.info("普通库位--库位上有其他货物, 库位号:{} ,无法进行移动 :{}", fromLocation.getLocationNo(), locationDOS);
return false;
}
} else {
@ -750,7 +801,7 @@ public class DistributeTasksServiceImpl implements DistributeTasksService {
.collect(Collectors.toList());
if (ObjectUtil.isNotEmpty(wareHouseLocationDOS)) {
// todo 后续记录到异常表
log.info("线库-当前库位上有其他货物, 库位号:{},无法进行移动 :{}",fromLocation.getLocationNo() ,wareHouseLocationDOS);
log.info("线库-当前库位上有其他货物, 库位号:{},无法进行移动 :{}", fromLocation.getLocationNo(), wareHouseLocationDOS);
return false;
}
}
@ -760,7 +811,7 @@ public class DistributeTasksServiceImpl implements DistributeTasksService {
}
public Pair<String, String> getMadAddressRobotNo(RobotTaskDetailDO taskDetailDO, List<RobotInformationDO> robots,
WareHouseLocationDO fromLocation, WareHouseLocationDO toLocation) {
WareHouseLocationDO fromLocation, WareHouseLocationDO toLocation) {
String macAddress = "";
String robotNo = taskDetailDO.getRobotNo();
if (ObjectUtil.isNotEmpty(robotNo)) {
@ -773,14 +824,14 @@ public class DistributeTasksServiceImpl implements DistributeTasksService {
RobotInformationDO robotInformationDO = robots.stream()
.filter(v ->
ObjectUtil.isNotEmpty(v.getMacAddress())
&& v.getFloorAreaJson().contains(fromLocation.getMapId())
&& v.getFloorAreaJson().contains(toLocation.getMapId()))
&& v.getFloorAreaJson().contains(fromLocation.getMapId())
&& v.getFloorAreaJson().contains(toLocation.getMapId()))
.findFirst()
.orElse(new RobotInformationDO());
macAddress = robotInformationDO.getMacAddress();
robotNo = robotInformationDO.getRobotNo();
}
Pair<String,String> pair = new ImmutablePair<>(macAddress,robotNo);
Pair<String, String> pair = new ImmutablePair<>(macAddress, robotNo);
return pair;
}

View File

@ -1,14 +1,20 @@
package cn.iocoder.yudao.module.system.service.robot.pathplanning;
import cn.hutool.core.util.ObjectUtil;
import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder;
import cn.iocoder.yudao.module.mqtt.api.task.RobotTaskApi;
import cn.iocoder.yudao.module.system.dal.dataobject.robot.RobotInformationDO;
import cn.iocoder.yudao.module.system.dal.dataobject.robot.RobotTaskDetailDO;
import cn.iocoder.yudao.module.system.dal.mysql.config.CommonConfigMapper;
import cn.iocoder.yudao.module.system.dal.mysql.houselocation.WareHouseLocationMapper;
import cn.iocoder.yudao.module.system.dal.mysql.positionmap.PositionMapItemMapper;
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.service.robot.job.DistributeTasksService;
import cn.iocoder.yudao.module.system.util.redis.RedisUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.tuple.Pair;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
@ -16,9 +22,11 @@ import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;
import javax.annotation.Resource;
import java.util.List;
@Service
@Validated
@Slf4j
public class RobotPathPlanningServiceImpl implements RobotPathPlanningService {
@Autowired
private RobotInformationMapper robotInformationMapper;
@ -63,6 +71,9 @@ public class RobotPathPlanningServiceImpl implements RobotPathPlanningService {
@Resource
private RedisUtil redisUtil;
@Autowired
private DistributeTasksService distributeTasksService;
/**
* 下发任务给PP
*/
@ -70,6 +81,20 @@ public class RobotPathPlanningServiceImpl implements RobotPathPlanningService {
@Transactional(rollbackFor = Exception.class)
public void sendTaskToPP() {
TenantContextHolder.setTenantId(1L);
Pair<List<RobotInformationDO>, List<RobotTaskDetailDO>> robotAndTaskDetails =
distributeTasksService.getRobotAndTaskDetails();
List<RobotInformationDO> robots = robotAndTaskDetails.getLeft();
if (ObjectUtil.isEmpty(robots)) {
return;
}
List<RobotTaskDetailDO> taskDetailDOS = robotAndTaskDetails.getRight();
if (ObjectUtil.isEmpty(taskDetailDOS)) {
log.info("--不存在需要执行的任务--");
return;
}
}