车辆匹配路网/远遥切换模式

This commit is contained in:
cbs 2025-04-23 14:08:54 +08:00
parent b0a5dc3b35
commit 55315e00d0
24 changed files with 669 additions and 51 deletions

View File

@ -0,0 +1,11 @@
package cn.iocoder.yudao.module.mqtt.api.path.dto.remote;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@Data
public class RemotePathPlanningDTO {
@Schema(description = "车辆编号")
private String robotNo;
}

View File

@ -159,6 +159,8 @@ public class MqttFactory {
return BeanUtils.getBean(PathPlanningMoveServiceImpl.class);
case PLANNING_ROUTE_DISPLAY:
return BeanUtils.getBean(PathRouteDisplayPlanningServiceImpl.class);
case PLANNING_GRAPH_MATCH_DATA:
return BeanUtils.getBean(PlanningGraphMatchDataServiceImpl.class);
default :
return BeanUtils.getBean(RobotTaskStatusServiceImpl.class);
}

View File

@ -27,7 +27,8 @@ public enum DefineSubTopicEnum {
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_ROUTE_DISPLAY("ROBOT_MOVE_POSE_PLANNING", 2,"路径规划上报实时路径"),
PLANNING_GRAPH_MATCH_DATA("GRAPH_MATCH_DATA", 2,"路网匹配实时数据");
private final String topic;

View File

@ -0,0 +1,25 @@
package cn.iododer.yudao.module.mqtt.service;
import cn.iocoder.yudao.module.system.api.path.PathApi;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
/**
* 路网匹配实时数据
*/
@Slf4j
@Service
public class PlanningGraphMatchDataServiceImpl implements MqttService{
@Resource
private PathApi pathApi;
@Override
public void analysisMessage(String message) {
log.info("匹配路网实时数据 :{}",message);
pathApi.graphMatchData(message);
}
}

View File

@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.remote.controller.admin.robot;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.module.remote.controller.admin.robot.dto.PositionMapRespDTO;
import cn.iocoder.yudao.module.remote.controller.admin.robot.dto.RemoteRobotChangeModeDTO;
import cn.iocoder.yudao.module.remote.service.robot.RemoteRobotService;
import cn.iocoder.yudao.module.system.api.remote.dto.RemoteRobotDTO;
import cn.iocoder.yudao.module.system.api.remote.dto.RemoteRobotStatusDTO;
@ -14,6 +15,7 @@ import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;
import java.util.List;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
@ -37,7 +39,7 @@ public class RemoteRobotController {
@GetMapping("/emergencyStopOrRecovery")
@Operation(summary = "一键急停or一键恢复地图上所有AGV")
@Parameter(name = "type", description = "类型(1:停止, 0:恢复)", required = true, example = "1024")
@PreAuthorize("@ss.hasPermission('system:position-map:emergencyStopOrRecovery')")
@PreAuthorize("@ss.hasPermission('remote:robot:emergencyStopOrRecovery')")
public CommonResult<Boolean> remoteEmergencyStopOrRecovery(@RequestParam("id") Long id, @RequestParam("type") Integer type) {
remoteRobotService.remoteEmergencyStopOrRecovery(id,type);
return success(true);
@ -45,6 +47,7 @@ public class RemoteRobotController {
@PostMapping("/getRobotRemoteStatus")
@Operation(summary = "获取机器人远遥模式/急停/协控状态")
@PreAuthorize("@ss.hasPermission('remote:robot:getRobotRemoteStatus')")
public CommonResult<RemoteRobotStatusDTO> getRobotRemoteStatus(HttpServletRequest request) {
return success(remoteRobotService.getRemoteRobotStatus(request));
}
@ -52,6 +55,7 @@ public class RemoteRobotController {
@GetMapping("/stop")
@Operation(summary = "暂停车辆")
@PreAuthorize("@ss.hasPermission('remote:robot:stop')")
public CommonResult<Boolean> robotStop(@RequestParam("robotNo") String robotNo) {
remoteRobotService.robotStop(robotNo);
return success(true);
@ -60,12 +64,19 @@ public class RemoteRobotController {
@GetMapping("/recovery")
@Operation(summary = "恢复车辆")
@PreAuthorize("@ss.hasPermission('remote:robot:recovery')")
public CommonResult<Boolean> recovery(@RequestParam("robotNo") String robotNo) {
remoteRobotService.recovery(robotNo);
return success(true);
}
@PostMapping("/robotChangeMode")
@Operation(summary = "获取机器人远遥模式/急停/协控状态")
@PreAuthorize("@ss.hasPermission('remote:robot:robotChangeMode')")
public CommonResult<Boolean> robotChangeMode(@Valid @RequestBody RemoteRobotChangeModeDTO data,HttpServletRequest request) {
remoteRobotService.robotChangeMode(data,request);
return success(true);
}
}

View File

@ -0,0 +1,18 @@
package cn.iocoder.yudao.module.remote.controller.admin.robot.dto;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
@Data
public class RemoteRobotChangeModeDTO {
@Schema(description = "远遥模式(0:自动模式, 1:手动模式, 2:自由模式)")
@NotNull(message = "请选择远遥模式")
private Integer remoteMode = 0;
@Schema(description = "车辆编号")
@NotEmpty(message = "请选择车辆编号")
private String robotNo ;
}

View File

@ -1,10 +1,12 @@
package cn.iocoder.yudao.module.remote.service.robot;
import cn.iocoder.yudao.module.remote.controller.admin.robot.dto.PositionMapRespDTO;
import cn.iocoder.yudao.module.remote.controller.admin.robot.dto.RemoteRobotChangeModeDTO;
import cn.iocoder.yudao.module.system.api.remote.dto.RemoteRobotDTO;
import cn.iocoder.yudao.module.system.api.remote.dto.RemoteRobotStatusDTO;
import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;
import java.util.List;
public interface RemoteRobotService {
@ -41,4 +43,11 @@ public interface RemoteRobotService {
* @param robotNo
*/
void recovery(String robotNo);
/**
* 切换远遥模式
* @param data
* @return
*/
void robotChangeMode( RemoteRobotChangeModeDTO data,HttpServletRequest request);
}

View File

@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.remote.service.robot;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.module.remote.controller.admin.robot.dto.PositionMapRespDTO;
import cn.iocoder.yudao.module.remote.controller.admin.robot.dto.RemoteRobotChangeModeDTO;
import cn.iocoder.yudao.module.remote.util.IpUtils;
import cn.iocoder.yudao.module.system.api.remote.RemoteRobotApi;
import cn.iocoder.yudao.module.system.api.remote.dto.RemoteRobotDTO;
@ -82,4 +83,18 @@ public class RemoteRobotServiceImpl implements RemoteRobotService{
throw exception0(TASK_COMMONG_FAIL.getCode(), result.getMsg());
}
}
/**
* 切换远遥模式
* @param data
* @return
*/
@Override
public void robotChangeMode(RemoteRobotChangeModeDTO data,HttpServletRequest request) {
String ip = IpUtils.getIp(request);
CommonResult<Boolean> result = remoteRobotApi.robotChangeMode(data.getRemoteMode(), ip, data.getRobotNo());
if (!result.isSuccess()){
throw exception0(TASK_COMMONG_FAIL.getCode(), result.getMsg());
}
}
}

View File

@ -36,4 +36,8 @@ public interface PathApi {
@PostMapping(PREFIX + "/simulationRobotPose")
@Operation(summary = "仿真初始化点位信息")
void simulationRobotPoseRequest(@RequestParam("message") String message);
@PostMapping(PREFIX + "/graphMatchData")
@Operation(summary = "路网匹配实时数据")
void graphMatchData(@RequestParam("message") String message);
}

View File

@ -20,11 +20,11 @@ public interface RemoteRobotApi {
@PostMapping(PREFIX + "/remoteGetAreaRobot")
@Operation(summary = "获取地图区域对应的机器人信息")
List<RemoteRobotDTO> remoteGetAreaRobot(@RequestParam(value = "mapId",defaultValue = "-1") Long mapId);
List<RemoteRobotDTO> remoteGetAreaRobot(@RequestParam(value = "mapId", defaultValue = "-1") Long mapId);
@PostMapping(PREFIX + "/remoteEmergencyStopOrRecovery")
@Operation(summary = "一键急停or一键恢复地图上所有AGV")
CommonResult<Boolean> remoteEmergencyStopOrRecovery(@RequestParam(value = "mapId") Long mapId, @RequestParam(value = "type") Integer type);
CommonResult<Boolean> remoteEmergencyStopOrRecovery(@RequestParam(value = "mapId") Long mapId, @RequestParam(value = "type") Integer type);
@PostMapping(PREFIX + "/getRemoteRobotStatus")
@Operation(summary = "获取机器人远遥模式/急停/协控状态")
@ -37,4 +37,10 @@ public interface RemoteRobotApi {
@PostMapping(PREFIX + "/recovery")
@Operation(summary = "恢复机器人")
CommonResult<Boolean> recovery(@RequestParam(value = "robotNo") String robotNo);
@PostMapping(PREFIX + "/robotChangeMode")
@Operation(summary = "切换模式")
CommonResult<Boolean> robotChangeMode(@RequestParam(value = "remoteMode") Integer remoteMode,
@RequestParam(value = "ip") String ip,
@RequestParam(value = "robotNo") String robotNo);
}

View File

@ -196,6 +196,8 @@ public interface ErrorCodeConstants {
ErrorCode ROBOT_HAVE_DOING_TASK = new ErrorCode(1-002-034-010, "车辆有处理中的任务,不允许修改/删除车辆编号和Mac地址");
ErrorCode ROBOT_REJECTION = new ErrorCode(1-002-034-011, "车辆已锁定");
ErrorCode ROBOT_DOING_REMOTE = new ErrorCode(1-002-034-012, "车辆目前远遥控制中,不能修改车辆信息");
ErrorCode ROBOT_NOT_STAND_BY = new ErrorCode(1-002-034-013, "车辆非空闲");
ErrorCode ROBOT_ELECTRICITY_INSUFFICIENT = new ErrorCode(1-002-034-014, "车辆电量不足");
// ========== 机器人任务主表 1-002-035-000 ==========
ErrorCode TASK_NOT_EXISTS = new ErrorCode(1-002-035-001, "车辆任务主表不存在");
@ -277,6 +279,14 @@ public interface ErrorCodeConstants {
ErrorCode ROBOT_ALREADY_RECOVERY = new ErrorCode(1_002_052_003, "车辆已经恢复");
// ========== 远遥设备信息 1_002_053_001 ==========
ErrorCode CONTROLLER_INFORMATION_NOT_EXISTS = new ErrorCode(1_002_053_001, "远遥设备信息不存在");
ErrorCode REMOTE_DEVICE_NOT_SET_UP = new ErrorCode(1_002_053_002, "远遥设备未设置通讯信息");
ErrorCode REMOTE_DEVICE_NEED_AUTOMATIC = new ErrorCode(1_002_053_003, "首次进入远遥设置,只能是自动模式");
ErrorCode REMOTE_DEVICE_CONTROLLER = new ErrorCode(1_002_053_004, "目前远遥设备控制的机器人是 ");
ErrorCode REMOTE_NOT_HAVE_TASK = new ErrorCode(1_002_053_005, "车辆没有处理中的任务,不能切换成手动模式");
ErrorCode REMOTE_HAVE_TASK = new ErrorCode(1_002_053_006, "车辆有处理中的任务,不能切换成自由模式");
ErrorCode REMOTE_NOT_HAVE_PATH_MATCH = new ErrorCode(1_002_053_007, "车辆未匹配路网");
ErrorCode REMOTE_AUTOMATIC_CAN_NOT_CHANGE_TO_FREE = new ErrorCode(1_002_053_008, "手动模式只能切换到自动模式");
ErrorCode REMOTE_FREE_CAN_NOT_CHANGE_TO_HAND_MOVEMENT = new ErrorCode(1_002_053_009, "自由模式只能切换到自动模式");
// ========== 车辆摄像头信息 1_002_054_001 ==========
ErrorCode CAMERA_NOT_EXISTS = new ErrorCode(1_002_054_001, "车辆摄像头信息不存在");

View File

@ -49,6 +49,7 @@ public class PathApiImpl implements PathApi {
taskExecutor.execute(() -> {
TenantContextHolder.setTenantId(1L);
log.info("初始化数据发送个PP---开始");
pathPlanningService.synchronousStart();
//同步点位信息
PositionMapSaveReqVO positionMapSaveReqVO = new PositionMapSaveReqVO();
pathPlanningService.synchronousAllItem(positionMapSaveReqVO);
@ -115,5 +116,15 @@ public class PathApiImpl implements PathApi {
pathPlanningService.simulationRobotPoseRequest();
}
/**
* 路网匹配实时数据
* @param message
*/
@Override
public void graphMatchData(String message) {
TenantContextHolder.setTenantId(1L);
pathPlanningService.graphMatchData(message);
}
}

View File

@ -16,7 +16,7 @@ import java.util.List;
@Slf4j
@RestController // 提供 RESTful API 接口 Feign 调用
@Validated
public class RemoteRobotApiImpl implements RemoteRobotApi{
public class RemoteRobotApiImpl implements RemoteRobotApi {
@Resource
private RobotMapStopService mapStopService;
@ -29,6 +29,7 @@ public class RemoteRobotApiImpl implements RemoteRobotApi{
/**
* 远遥获取地图和车辆信息
*
* @param mapId
* @return
*/
@ -39,17 +40,19 @@ public class RemoteRobotApiImpl implements RemoteRobotApi{
/**
* 远遥车辆暂停
*
* @param mapId
* @param type
*/
@Override
public CommonResult<Boolean> remoteEmergencyStopOrRecovery(Long mapId, Integer type) {
positionMapService.emergencyStopOrRecovery(mapId,type,true);
positionMapService.emergencyStopOrRecovery(mapId, type, true);
return CommonResult.success(true);
}
/**
* 获取机器人远遥模式/急停/协控状态
*
* @param ip
* @return
*/
@ -60,17 +63,19 @@ public class RemoteRobotApiImpl implements RemoteRobotApi{
/**
* 远遥暂停车辆
*
* @param robotNo
* @return
*/
@Override
public CommonResult<Boolean> robotStop(String robotNo) {
mapStopService.remoteStopRobot(robotNo);
mapStopService.remoteStopRobot(robotNo);
return CommonResult.success(true);
}
/**
* 远遥恢复车辆
*
* @param robotNo
* @return
*/
@ -80,5 +85,18 @@ public class RemoteRobotApiImpl implements RemoteRobotApi{
return CommonResult.success(true);
}
/**
* 远遥切换模式
*
* @param remoteMode
* @param remoteIp
* @return
*/
@Override
public CommonResult<Boolean> robotChangeMode(Integer remoteMode, String remoteIp, String robotNo) {
controllerInformationService.robotChangeMode(remoteMode, remoteIp, robotNo);
return CommonResult.success(true);
}
}

View File

@ -6,4 +6,7 @@ package cn.iocoder.yudao.module.system.constant.path;
public class PathPlanningChcheConstant {
//发送给路径规划的任务 (拼接的是任务id)
public static String PATH_PLANNING_TASK = "path:planning:task";
//路网匹配 true表示匹配成功 false表示匹配失败 (拼接的是robotNo)
public static String PATH_PLANNING_GRAPH_MATCH = "path:planning:graph:match";
}

View File

@ -89,5 +89,20 @@ public class PathPlanningTopicConstant {
*/
public static String UPDATE_BEHAVIOR = "UPDATE_BEHAVIOR";
/**
* 开始同步信息给PP的通知
*/
public static String SYNCHRONOUS_ALL_MAP_INIT = "SYNCHRONOUS_ALL_MAP_INIT";
/**
* 开启远遥
*/
public static String START_REMOTE_CONTROLLER = "START_REMOTE_CONTROLLER";
/**
* 关闭远遥
*/
public static String CLOSE_REMOTE_CONTROLLER = "CLOSE_REMOTE_CONTROLLER";
}

View File

@ -0,0 +1,19 @@
package cn.iocoder.yudao.module.system.controller.admin.path.dto;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@Data
public class GraphMatchDataDTO {
@Schema(description = "车辆编号")
private String robotNo;
@Schema(description = "true表示匹配成功 false表示匹配失败")
private Boolean isMatched;
@Schema(description = "LINE表示匹配到线段NODE表示匹配到节点")
private String matchedType;
@Schema(description = "匹配到的线段或者节点的snowflake")
private String matchedId;
}

View File

@ -0,0 +1,26 @@
package cn.iocoder.yudao.module.system.enums.robot.remote;
import lombok.AllArgsConstructor;
import lombok.Getter;
@Getter
@AllArgsConstructor
public enum RemoteModeEnum {
AUTOMATIC(0, "自动模式"),
HAND_MOVEMENT(1, "手动模式"),
FREE(2, "自由模式");
/**
* 类型
*/
private final Integer type;
private final String msg;
public static String getMsg(Integer type) {
if (AUTOMATIC.getType().equals(type)) {
return AUTOMATIC.getMsg();
} else if (HAND_MOVEMENT.getType().equals(type)) {
return HAND_MOVEMENT.getMsg();
}
return FREE.getMsg();
}
}

View File

@ -49,4 +49,15 @@ public interface PathPlanningService {
* 仿真点位信息
*/
void simulationRobotPoseRequest();
/**
* 路网匹配实时数据
* @param message
*/
void graphMatchData(String message);
/**
* 开始同步
*/
void synchronousStart();
}

View File

@ -14,10 +14,12 @@ import cn.iocoder.yudao.module.system.api.robot.dto.RobotPoseStatusDTO;
import cn.iocoder.yudao.module.system.api.robot.dto.RobotStatusDataPoseDTO;
import cn.iocoder.yudao.module.system.api.robot.vo.PathPlanningMovePoseVO;
import cn.iocoder.yudao.module.system.api.robot.vo.RobotInformationVO;
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.RobotTaskChcheConstant;
import cn.iocoder.yudao.module.system.constant.robot.RobotTopicConstant;
import cn.iocoder.yudao.module.system.constant.webSocket.WebSocketConstant;
import cn.iocoder.yudao.module.system.controller.admin.path.dto.GraphMatchDataDTO;
import cn.iocoder.yudao.module.system.controller.admin.path.dto.SimulationRobotPoseDTO;
import cn.iocoder.yudao.module.system.controller.admin.positionmap.vo.PositionMapItemSaveReqVO;
import cn.iocoder.yudao.module.system.controller.admin.positionmap.vo.PositionMapLineSaveReqVO;
@ -537,6 +539,27 @@ public class PathPlanningServiceImpl implements PathPlanningService {
commonApi.commonMethod(simulationList, PathPlanningTopicConstant.INIT_ROBOT_POSE);
}
/**
* 路网匹配实时数据
* @param message
*/
@Override
public void graphMatchData(String message) {
GraphMatchDataDTO graphMatchData = JSON.parseObject(message, GraphMatchDataDTO.class);
String key = PathPlanningChcheConstant.PATH_PLANNING_GRAPH_MATCH + graphMatchData.getRobotNo();
redisUtil.set(key,graphMatchData.getIsMatched());
}
@Override
public void synchronousStart() {
commonApi.commonMethodStr("开始同步点位信息", PathPlanningTopicConstant.SYNCHRONOUS_ALL_MAP_INIT);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
public PositionMapLineDTO setPositionMapLineDTOData(PositionMapLineDTO positionMapLineDO) {
PositionMapLineDTO build = PositionMapLineDTO.builder()
.id(positionMapLineDO.getId())

View File

@ -59,24 +59,28 @@ public interface RemoteControllerInformationService extends IService<RemoteContr
/**
* 保存远遥的IP和端口
*
* @param loginCheckDTO
*/
void saveIpAndPort(LoginCheckDTO loginCheckDTO);
/**
* 查询远遥默认IP和端口
*
* @return
*/
LoginCheckDTO getDefaultIpAndPort(String remoteIp);
/**
* 获取所有远遥信息
*
* @return
*/
List<RemoteControllerInformationDO> getAllRemoteController();
/**
* 获取机器人远遥模式/急停/协控状态
*
* @param ip
* @return
*/
@ -84,8 +88,17 @@ public interface RemoteControllerInformationService extends IService<RemoteContr
/**
* 根据机器人编号查询
*
* @param robotNo
* @return
*/
RemoteControllerInformationDO getRemoteControllerByRobotNo(String robotNo);
/**
* 远遥切换模式
*
* @param remoteMode
* @param remoteIp
*/
void robotChangeMode(Integer remoteMode, String remoteIp, String robotNo);
}

View File

@ -3,23 +3,40 @@ package cn.iocoder.yudao.module.system.service.remote;
import cn.hutool.core.util.ObjectUtil;
import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils;
import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils;
import cn.iocoder.yudao.module.mqtt.api.common.CommonApi;
import cn.iocoder.yudao.module.mqtt.api.path.dto.remote.RemotePathPlanningDTO;
import cn.iocoder.yudao.module.system.api.remote.dto.LoginCheckDTO;
import cn.iocoder.yudao.module.system.api.remote.dto.RemoteRobotStatusDTO;
import cn.iocoder.yudao.module.system.constant.path.PathPlanningChcheConstant;
import cn.iocoder.yudao.module.system.constant.path.PathPlanningTopicConstant;
import cn.iocoder.yudao.module.system.controller.admin.log.vo.UserOperationLogSaveReqVO;
import cn.iocoder.yudao.module.system.controller.admin.remote.vo.RemoteControllerInformationPageReqVO;
import cn.iocoder.yudao.module.system.controller.admin.remote.vo.RemoteControllerInformationSaveReqVO;
import cn.iocoder.yudao.module.system.dal.dataobject.config.CommonConfigDO;
import cn.iocoder.yudao.module.system.dal.dataobject.log.RobotTaskDetailActionLogDO;
import cn.iocoder.yudao.module.system.dal.dataobject.remote.RemoteControllerInformationDO;
import cn.iocoder.yudao.module.system.dal.dataobject.robot.RobotInformationDO;
import cn.iocoder.yudao.module.system.dal.dataobject.robot.RobotMapStopDO;
import cn.iocoder.yudao.module.system.dal.dataobject.robot.RobotTaskDO;
import cn.iocoder.yudao.module.system.dal.mysql.config.CommonConfigMapper;
import cn.iocoder.yudao.module.system.dal.mysql.remote.RemoteControllerInformationMapper;
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.path.PathTaskTypeEnum;
import cn.iocoder.yudao.module.system.enums.redis.RobotCacheLockEnum;
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.actionlog.ActionStatusEnum;
import cn.iocoder.yudao.module.system.enums.robot.remote.RemoteModeEnum;
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.robot.RobotInformationService;
import cn.iocoder.yudao.module.system.service.robot.mapstop.RobotMapStopService;
import cn.iocoder.yudao.module.system.util.redis.RedisUtil;
import cn.iocoder.yudao.module.system.util.redis.RedissonUtils;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RLock;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
@ -30,13 +47,13 @@ import org.springframework.transaction.annotation.Transactional;
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;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.CONTROLLER_INFORMATION_NOT_EXISTS;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception0;
import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.*;
/**
* 远遥设备信息 Service 实现类
@ -45,6 +62,7 @@ import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.CONTROLLER
*/
@Service
@Validated
@Slf4j
public class RemoteControllerInformationServiceImpl extends ServiceImpl<RemoteControllerInformationMapper, RemoteControllerInformationDO> implements RemoteControllerInformationService {
@Resource
@ -59,6 +77,21 @@ public class RemoteControllerInformationServiceImpl extends ServiceImpl<RemoteCo
@Resource
private RobotTaskDetailActionLogService taskDetailActionLogService;
@Resource
private RedissonUtils redissonUtils;
@Resource
private RobotInformationService informationService;
@Resource
private RedisUtil redisUtil;
@Resource
private CommonApi commonApi;
@Resource
private CommonConfigMapper configMapper;
@Override
public Long createControllerInformation(RemoteControllerInformationSaveReqVO createReqVO) {
// 插入
@ -107,6 +140,7 @@ public class RemoteControllerInformationServiceImpl extends ServiceImpl<RemoteCo
* @param loginCheck
*/
@Override
@Transactional(rollbackFor = Exception.class)
public void saveIpAndPort(LoginCheckDTO loginCheck) {
RemoteControllerInformationDO information = controllerInformationMapper.selectOne(new LambdaQueryWrapper<RemoteControllerInformationDO>()
.eq(RemoteControllerInformationDO::getRemoteIp, loginCheck.getRemoteIp())
@ -139,6 +173,7 @@ public class RemoteControllerInformationServiceImpl extends ServiceImpl<RemoteCo
/**
* 查询远遥默认IP和端口
*
* @return
*/
@Override
@ -163,6 +198,7 @@ public class RemoteControllerInformationServiceImpl extends ServiceImpl<RemoteCo
/**
* 获取机器人远遥模式/急停/协控状态
*
* @param remoteIp
* @return
*/
@ -180,10 +216,10 @@ public class RemoteControllerInformationServiceImpl extends ServiceImpl<RemoteCo
remoteRobotStatus.setIsStop(ZeroOneEnum.ZERO.getType());
}
RobotTaskDetailActionLogDO actionLog = taskDetailActionLogService.getLastTaskByRobotNo(information.getRobotNo());
if (ObjectUtil.isNotEmpty(actionLog) && !actionLog.getActionStatus().equals(ActionStatusEnum.DONE.getType())
&& (PathTaskTypeEnum.TAKE_RELEASE.getType().equals(actionLog.getCommandType())
if (ObjectUtil.isNotEmpty(actionLog) && !actionLog.getActionStatus().equals(ActionStatusEnum.DONE.getType())
&& (PathTaskTypeEnum.TAKE_RELEASE.getType().equals(actionLog.getCommandType())
|| PathTaskTypeEnum.TAKE.getType().equals(actionLog.getCommandType())
|| PathTaskTypeEnum.RELEASE.getType().equals(actionLog.getCommandType())) ) {
|| PathTaskTypeEnum.RELEASE.getType().equals(actionLog.getCommandType()))) {
remoteRobotStatus.setClickTaskDone(ZeroOneEnum.ZERO.getType());
}
@ -192,6 +228,7 @@ public class RemoteControllerInformationServiceImpl extends ServiceImpl<RemoteCo
/**
* 根据车辆编号查询
*
* @param robotNo
* @return
*/
@ -203,5 +240,209 @@ public class RemoteControllerInformationServiceImpl extends ServiceImpl<RemoteCo
return information;
}
/**
* 远遥切换模式
*
* @param remoteMode
* @param remoteIp
*/
@Override
@Transactional(rollbackFor = Exception.class)
public void robotChangeMode(Integer remoteMode, String remoteIp, String robotNo) {
RLock lock = redissonUtils.getLock(RobotCacheLockEnum.ROBOT_TASK_DISTRIBUTE_LOCK.getKey());
if (lock.tryLock()) {
try {
log.info("----远遥切换模式----");
try {
//避免有分配中的任务所以等待0.5秒
Thread.sleep(500);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
doRobotChangeMode(remoteMode, remoteIp, robotNo);
} finally {
lock.unlock();
}
} else {
log.info("----远遥切换模式----未获取到锁");
throw exception(REDISSON_NOT_OBTAIN_LOCK);
}
}
/**
* @param remoteMode
* @param remoteIp
* @param robotNo
*/
@Transactional(rollbackFor = Exception.class)
public void doRobotChangeMode(Integer remoteMode, String remoteIp, String robotNo) {
//后续判断下如果协控中能不能切换模式
RemoteControllerInformationDO information = controllerInformationMapper.selectOne(new LambdaQueryWrapper<RemoteControllerInformationDO>()
.eq(RemoteControllerInformationDO::getRemoteIp, remoteIp)
.last("limit 1"));
if (ObjectUtil.isEmpty(information)) {
throw exception(REMOTE_DEVICE_NOT_SET_UP);
}
if (ObjectUtil.isEmpty(information.getRobotNo()) && !RemoteModeEnum.AUTOMATIC.getType().equals(remoteMode)) {
throw exception(REMOTE_DEVICE_NEED_AUTOMATIC);
}
RobotInformationDO robotInformation = informationService.getInformationByRobotNo(robotNo);
if (ObjectUtil.isNotEmpty(information.getRobotNo()) && !information.getRobotNo().equals(robotNo)) {
String msg = "目前远遥设备控制的机器人是 " + information.getRobotNo() + " 需要先将此机器人退出远遥";
throw exception0(REMOTE_DEVICE_CONTROLLER.getCode(), msg, msg);
}
//第一次设置为自动模式
if (ObjectUtil.isEmpty(information.getRobotNo()) && RemoteModeEnum.AUTOMATIC.getType().equals(remoteMode)) {
String operateAction = information.getRemoteIp() + " 开启远遥为自动模式";
setRemoteChangeLog(information, robotNo, remoteMode, operateAction);
sendRemoteMsgToRobotAndPP(false,robotNo);
//todo 同步苏工和PP 包括车速
return;
}
if (ObjectUtil.isNotEmpty(information.getRobotNo()) && information.getRobotNo().equals(robotNo)
&& ObjectUtil.isNotEmpty(information.getRemoteMode()) && information.getRemoteMode().equals(remoteMode)) {
UserOperationLogSaveReqVO operationLog = UserOperationLogSaveReqVO.builder()
.operateAction(information.getRemoteIp() + " 重新进入远遥 " + RemoteModeEnum.getMsg(remoteMode))
.nickName(SecurityFrameworkUtils.getLoginUserNickname()).build();
userOperationLogService.createUserOperationLog(operationLog);
return;
}
//自动切手动
if (RemoteModeEnum.AUTOMATIC.getType().equals(information.getRemoteMode()) && RemoteModeEnum.HAND_MOVEMENT.getType().equals(remoteMode)) {
List<RobotTaskDO> doingTask = informationService.selectDoingTaskByRobotNo(robotNo);
if (ObjectUtil.isEmpty(doingTask)) {
throw exception(REMOTE_NOT_HAVE_TASK);
}
String operateAction = information.getRemoteIp() + " 切换远遥模式为 " + RemoteModeEnum.getMsg(remoteMode);
setRemoteChangeLog(information, robotNo, remoteMode, operateAction);
sendRemoteMsgToRobotAndPP(true,robotNo);
//todo 同步苏工和PP 包括车速
return;
}
//自动切自由
if (RemoteModeEnum.AUTOMATIC.getType().equals(information.getRemoteMode()) && RemoteModeEnum.FREE.getType().equals(remoteMode)) {
List<RobotTaskDO> doingTask = informationService.selectDoingTaskByRobotNo(robotNo);
if (ObjectUtil.isNotEmpty(doingTask)) {
throw exception(REMOTE_HAVE_TASK);
}
if (RobotTaskModelEnum.REJECTION.getType().equals(robotInformation.getRobotTaskModel())) {
throw exception(ROBOT_REJECTION);
}
if (!RobotStatusEnum.STAND_BY.getType().equals(robotInformation.getRobotStatus())) {
throw exception(ROBOT_NOT_STAND_BY);
}
//校验电量是否充足
checkElectricity(robotInformation);
String operateAction = information.getRemoteIp() + " 切换远遥模式为 " + RemoteModeEnum.getMsg(remoteMode);
setRemoteChangeLog(information, robotNo, remoteMode, operateAction);
sendRemoteMsgToRobotAndPP(true,robotNo);
//todo 同步苏工和PP 包括车速
return;
}
//手动切自动
if (RemoteModeEnum.HAND_MOVEMENT.getType().equals(information.getRemoteMode()) && RemoteModeEnum.AUTOMATIC.getType().equals(remoteMode)) {
String graphMatchKey = PathPlanningChcheConstant.PATH_PLANNING_GRAPH_MATCH + robotNo;
Object o = redisUtil.get(graphMatchKey);
if (ObjectUtil.isEmpty(o) || !Boolean.parseBoolean(String.valueOf(o))) {
throw exception(REMOTE_NOT_HAVE_PATH_MATCH);
}
String operateAction = information.getRemoteIp() + " 切换远遥模式为 " + RemoteModeEnum.getMsg(remoteMode);
setRemoteChangeLog(information, robotNo, remoteMode, operateAction);
sendRemoteMsgToRobotAndPP(false,robotNo);
//todo 同步苏工和PP 包括车速
return;
}
//手动切自由
if (RemoteModeEnum.HAND_MOVEMENT.getType().equals(information.getRemoteMode()) && RemoteModeEnum.FREE.getType().equals(remoteMode)) {
log.info("手动模式不能切换到自由模式 :{}", remoteIp);
throw exception(REMOTE_AUTOMATIC_CAN_NOT_CHANGE_TO_FREE);
}
//自由切手动
if (RemoteModeEnum.FREE.getType().equals(information.getRemoteMode()) && RemoteModeEnum.HAND_MOVEMENT.getType().equals(remoteMode)) {
log.info("自由模式不能切换到手动模式 :{}", remoteIp);
throw exception(REMOTE_FREE_CAN_NOT_CHANGE_TO_HAND_MOVEMENT);
}
//自由切自动
if (RemoteModeEnum.FREE.getType().equals(information.getRemoteMode()) && RemoteModeEnum.AUTOMATIC.getType().equals(remoteMode)) {
String graphMatchKey = PathPlanningChcheConstant.PATH_PLANNING_GRAPH_MATCH + robotNo;
Object o = redisUtil.get(graphMatchKey);
if (ObjectUtil.isEmpty(o) || !Boolean.parseBoolean(String.valueOf(o))) {
throw exception(REMOTE_NOT_HAVE_PATH_MATCH);
}
String operateAction = information.getRemoteIp() + " 切换远遥模式为 " + RemoteModeEnum.getMsg(remoteMode);
setRemoteChangeLog(information, robotNo, remoteMode, operateAction);
sendRemoteMsgToRobotAndPP(false,robotNo);
//todo 同步苏工和PP 包括车速
}
}
/**
* 发送远遥信息给PP和车机
* @param isAuto
* @param robotNo
*/
public void sendRemoteMsgToRobotAndPP(Boolean isAuto, String robotNo){
RemotePathPlanningDTO remotePathPlanning = new RemotePathPlanningDTO();
remotePathPlanning.setRobotNo(robotNo);
commonApi.commonMethod(remotePathPlanning, PathPlanningTopicConstant.START_REMOTE_CONTROLLER);
}
/**
* 远遥切换添加记录
*/
public void setRemoteChangeLog(RemoteControllerInformationDO information, String robotNo, Integer remoteMode, String operateAction) {
information.setRobotNo(robotNo);
information.setRemoteMode(remoteMode);
// information.setCollaborativeControl(ZeroOneEnum.ZERO.getType());
controllerInformationMapper.updateById(information);
UserOperationLogSaveReqVO operationLog = UserOperationLogSaveReqVO.builder()
.operateAction(operateAction)
.nickName(SecurityFrameworkUtils.getLoginUserNickname()).build();
userOperationLogService.createUserOperationLog(operationLog);
}
/**
* 校验电量是否充足
*
* @param robotNo
*/
private void checkElectricity(RobotInformationDO information) {
CommonConfigDO commonConfig = configMapper.selectOne(new LambdaQueryWrapper<CommonConfigDO>()
.eq(CommonConfigDO::getConfigType, CommandConfigTypeEnum.CHARG_CONFIG.getType()));
//校验机器人是否到达设定的电量
Boolean canDoTask = informationService.checkRobotElectricity(information, commonConfig);
if (!canDoTask) {
log.info("车辆电量不足");
throw exception(ROBOT_ELECTRICITY_INSUFFICIENT);
}
}
}

View File

@ -5,7 +5,9 @@ import cn.iocoder.yudao.module.mqtt.api.task.dto.RobotSimulationPoseDTO;
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.config.CommonConfigDO;
import cn.iocoder.yudao.module.system.dal.dataobject.robot.RobotInformationDO;
import cn.iocoder.yudao.module.system.dal.dataobject.robot.RobotTaskDO;
import com.baomidou.mybatisplus.extension.service.IService;
import javax.validation.Valid;
@ -175,4 +177,26 @@ public interface RobotInformationService extends IService<RobotInformationDO> {
* @param str
*/
void sendEmergencyStopOrRecoveryToRobot(RobotSimulationPoseDTO robotSimulationPose, List<String> robotNos, String str);
/**
* 查询机器人处理中的任务
* @param robotNo
* @return
*/
List<RobotTaskDO> selectDoingTaskByRobotNo(String robotNo);
/**
* 根据机器人编号查询
* @param robotNo
* @return
*/
RobotInformationDO getInformationByRobotNo(String robotNo);
/**
* 校验机器人是否到达设定的电量
* @param robotNo
* @param commonConfig
* @return
*/
Boolean checkRobotElectricity(RobotInformationDO information, CommonConfigDO commonConfig);
}

View File

@ -30,12 +30,14 @@ import cn.iocoder.yudao.module.system.constant.path.PathPlanningTopicConstant;
import cn.iocoder.yudao.module.system.constant.robot.RobotStatusCodeConstant;
import cn.iocoder.yudao.module.system.constant.robot.RobotTaskChcheConstant;
import cn.iocoder.yudao.module.system.constant.robot.RobotTopicConstant;
import cn.iocoder.yudao.module.system.controller.admin.config.vo.CommonConfigVO;
import cn.iocoder.yudao.module.system.controller.admin.log.vo.UserOperationLogSaveReqVO;
import cn.iocoder.yudao.module.system.controller.admin.robot.camera.RobotCameraAddVO;
import cn.iocoder.yudao.module.system.controller.admin.robot.proceed.RobotTaskProceedSaveReqVO;
import cn.iocoder.yudao.module.system.controller.admin.robot.vo.*;
import cn.iocoder.yudao.module.system.controller.admin.tool.dto.CleanAgvDTO;
import cn.iocoder.yudao.module.system.controller.admin.user.vo.user.UserSaveReqVO;
import cn.iocoder.yudao.module.system.dal.dataobject.config.CommonConfigDO;
import cn.iocoder.yudao.module.system.dal.dataobject.houselocation.WareHouseLocationDO;
import cn.iocoder.yudao.module.system.dal.dataobject.information.DeviceInformationDO;
import cn.iocoder.yudao.module.system.dal.dataobject.informationmapassociation.InformationMapAssociationDO;
@ -68,6 +70,7 @@ import cn.iocoder.yudao.module.system.enums.robot.RobotStatusEnum;
import cn.iocoder.yudao.module.system.enums.robot.RobotTaskDetailStatusEnum;
import cn.iocoder.yudao.module.system.enums.robot.RobotTaskModelEnum;
import cn.iocoder.yudao.module.system.enums.robot.actionlog.ActionStatusEnum;
import cn.iocoder.yudao.module.system.enums.robot.charge.ChargeModelEnum;
import cn.iocoder.yudao.module.system.enums.robot.information.RobotStatisticsTypeEnum;
import cn.iocoder.yudao.module.system.enums.robot.task.RobotTaskStageEnum;
import cn.iocoder.yudao.module.system.service.informationmapassociation.InformationMapAssociationService;
@ -94,6 +97,7 @@ import org.springframework.validation.annotation.Validated;
import javax.annotation.Resource;
import javax.validation.ConstraintViolationException;
import java.math.BigDecimal;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
@ -175,6 +179,9 @@ public class RobotInformationServiceImpl extends ServiceImpl<RobotInformationMap
@Value("${zn.restore_task_restart:true}")
private Boolean restoreTaskRestart;
@Value("${zn.full_electricity:95}")
private String fullElectricity;
@Resource
private RobotCameraService cameraService;
@ -211,7 +218,7 @@ public class RobotInformationServiceImpl extends ServiceImpl<RobotInformationMap
if (ObjectUtil.isNotEmpty(createReqVO.getCameraAddVOList())) {
List<RobotCameraAddVO> cameraAddVOList = createReqVO.getCameraAddVOList();
cameraService.checkCameraExist(cameraAddVOList);
cameraService.createCameraList(cameraAddVOList,createReqVO.getRobotNo());
cameraService.createCameraList(cameraAddVOList, createReqVO.getRobotNo());
}
RobotModelDO robotModelDO = modelMapper.selectById(createReqVO.getRobotModelId());
createReqVO.setRobotModelNumber(robotModelDO.getRobotModelNumber());
@ -301,7 +308,7 @@ public class RobotInformationServiceImpl extends ServiceImpl<RobotInformationMap
if (ObjectUtil.isNotEmpty(updateReqVO.getCameraAddVOList())) {
List<RobotCameraAddVO> cameraAddVOList = updateReqVO.getCameraAddVOList();
cameraService.checkCameraExist(cameraAddVOList);
cameraService.createCameraList(cameraAddVOList,updateReqVO.getRobotNo());
cameraService.createCameraList(cameraAddVOList, updateReqVO.getRobotNo());
}
// 更新
RobotInformationDO updateObj = BeanUtils.toBean(updateReqVO, RobotInformationDO.class);
@ -327,21 +334,21 @@ public class RobotInformationServiceImpl extends ServiceImpl<RobotInformationMap
}
if (!robotInformationDO.getMacAddress().equals(updateReqVO.getMacAddress())
|| !robotInformationDO.getRobotNo().equals(updateReqVO.getRobotNo())) {
|| !robotInformationDO.getRobotNo().equals(updateReqVO.getRobotNo())) {
//地图相关
String floorAreaKey = RobotTaskChcheConstant.ROBOT_FLOOR_AREA + robotInformationDO.getMacAddress();
Object o = redisUtil.get(floorAreaKey);
FloorZoneDTO floorZone = JSON.parseObject((String) o, FloorZoneDTO.class);
String oldFloorArea = floorZone.getFloor()+"-"+floorZone.getArea();
redisUtil.hdel(oldFloorArea,robotInformationDO.getRobotNo());
String oldFloorArea = floorZone.getFloor() + "-" + floorZone.getArea();
redisUtil.hdel(oldFloorArea, robotInformationDO.getRobotNo());
redisUtil.del(floorAreaKey);
if (ObjectUtil.isNotEmpty(o)) {
String newFloorAreaKey = RobotTaskChcheConstant.ROBOT_FLOOR_AREA + updateReqVO.getMacAddress();
redisUtil.set(newFloorAreaKey, JSON.toJSONString(floorZone));
Map<String, Object> map = new HashMap<>();
String value = floorZone.getFloor() + "-" + floorZone.getArea();
map.put(updateReqVO.getRobotNo(),value);
redisUtil.hmset(value,map);
map.put(updateReqVO.getRobotNo(), value);
redisUtil.hmset(value, map);
}
}
@ -387,8 +394,8 @@ public class RobotInformationServiceImpl extends ServiceImpl<RobotInformationMap
String floorAreaKey = RobotTaskChcheConstant.ROBOT_FLOOR_AREA + robotInformationDO.getMacAddress();
Object o = redisUtil.get(floorAreaKey);
FloorZoneDTO floorZone = JSON.parseObject((String) o, FloorZoneDTO.class);
String oldFloorArea = floorZone.getFloor()+"-"+floorZone.getArea();
redisUtil.hdel(oldFloorArea,robotInformationDO.getRobotNo());
String oldFloorArea = floorZone.getFloor() + "-" + floorZone.getArea();
redisUtil.hdel(oldFloorArea, robotInformationDO.getRobotNo());
redisUtil.del(floorAreaKey);
}
@ -745,14 +752,14 @@ public class RobotInformationServiceImpl extends ServiceImpl<RobotInformationMap
@Override
public RobotInformationVO getRobotByRedis(String macAddress) {
String addressKey = RobotTaskChcheConstant.ROBOT_ADDRESS+macAddress;
String addressKey = RobotTaskChcheConstant.ROBOT_ADDRESS + macAddress;
if (ObjectUtil.isNotEmpty(redisUtil.get(addressKey))) {
return new RobotInformationVO();
}
// todo -- 如果说有一个设备的mac 一直都不在库里 会出现缓存穿透的问题 - 后续如果出现这种情况的话 - 考虑将null值也存入到缓存中
RobotInformationDO item = this.getOne(new LambdaQueryWrapper<RobotInformationDO>().eq(RobotInformationDO::getMacAddress, macAddress));
if (ObjectUtil.isEmpty(item)) {
redisUtil.set(addressKey, macAddress, 30*1000);
redisUtil.set(addressKey, macAddress, 30 * 1000);
}
// -- 将获取到的存入到redis中
if (ObjectUtil.isNotEmpty(item)) {
@ -935,16 +942,16 @@ public class RobotInformationServiceImpl extends ServiceImpl<RobotInformationMap
String taskStatusKey = RobotTaskChcheConstant.ROBOT_TASK_STATUS + robotInformationDO.getMacAddress();
Object taskStatus = redisUtil.get(taskStatusKey);
if (ObjectUtil.isEmpty(taskStatus) || !RobotStatusCodeConstant.CAN_DO_TASK.equals(Boolean.parseBoolean(String.valueOf(taskStatus)))) {
log.info("车机上报不允许接任务 :{}",robotNo);
log.info("车机上报不允许接任务 :{}", robotNo);
throw exception(ROBOT_DO_TASK_FAIL);
}
TaskToPathPlanningDTO pathPlanning = JSONUtil.toBean((String) o, TaskToPathPlanningDTO.class);
RLock lock = redissonUtils.getLock(RobotCacheLockEnum.ROBOT_TASK_DISTRIBUTE_LOCK.getKey());
if (lock.tryLock()){
if (lock.tryLock()) {
try {
resendToPP(pathPlanning,actionLog);
resendToPP(pathPlanning, actionLog);
/*if (PathTaskTypeEnum.CHARGE.getType().equals(pathPlanning.getOrderType())
|| PathTaskTypeEnum.AUTO_CHARGE.getType().equals(pathPlanning.getOrderType())) {
@ -956,7 +963,7 @@ public class RobotInformationServiceImpl extends ServiceImpl<RobotInformationMap
} finally {
lock.unlock();
}
}else {
} else {
log.info("下发任务给路径规划未获取到锁");
throw exception(REDISSON_NOT_OBTAIN_LOCK);
}
@ -965,6 +972,7 @@ public class RobotInformationServiceImpl extends ServiceImpl<RobotInformationMap
/**
* 将任务重新发给PP
*
* @param pathPlanning
* @param actionLog
*/
@ -978,7 +986,7 @@ public class RobotInformationServiceImpl extends ServiceImpl<RobotInformationMap
pathPlanning.setRobotNoLimitationAreaDTOS(robotNoLimitions);
if (!isSimulation || !restoreTaskRestart) {
resendToPPData(pathPlanning,actionLog,robotInformationDO);
resendToPPData(pathPlanning, actionLog, robotInformationDO);
}
List<TaskToPathPlanningDTO> pathPlanningList = new ArrayList<>();
@ -993,20 +1001,21 @@ public class RobotInformationServiceImpl extends ServiceImpl<RobotInformationMap
moveToWaitTask(pathPlanning, actionLog.getRobotNo());
} else if (PathTaskTypeEnum.CHARGE.getType().equals(actionLog.getCommandType())
|| PathTaskTypeEnum.AUTO_CHARGE.getType().equals(actionLog.getCommandType())) {
chargeTask(pathPlanning,robotInformationDO);
chargeTask(pathPlanning, robotInformationDO);
} else if (PathTaskTypeEnum.TAKE_RELEASE.getType().equals(actionLog.getCommandType())) {
takeReleaseTask(pathPlanning);
} else if (PathTaskTypeEnum.TAKE.getType().equals(actionLog.getCommandType())) {
takeTask(pathPlanning);
}else if (PathTaskTypeEnum.RELEASE.getType().equals(actionLog.getCommandType())) {
} else if (PathTaskTypeEnum.RELEASE.getType().equals(actionLog.getCommandType())) {
releaseTask(pathPlanning);
}else if (PathTaskTypeEnum.MOVE.getType().equals(actionLog.getCommandType())) {
} else if (PathTaskTypeEnum.MOVE.getType().equals(actionLog.getCommandType())) {
}
}
/**
* 仅放货
*
* @param pathPlanning
*/
private void releaseTask(TaskToPathPlanningDTO pathPlanning) {
@ -1016,14 +1025,15 @@ public class RobotInformationServiceImpl extends ServiceImpl<RobotInformationMap
/**
* 仅取货
*
* @param pathPlanning
*/
private void takeTask(TaskToPathPlanningDTO pathPlanning) {
RobotTaskDetailDO robotTaskDetail = checkTaskDone(pathPlanning.getOrderId());
takeCheck(robotTaskDetail.getFromLocationId(),robotTaskDetail.getRobotTaskId());
takeCheck(robotTaskDetail.getFromLocationId(), robotTaskDetail.getRobotTaskId());
}
public RobotTaskDetailDO checkTaskDone(String id){
public RobotTaskDetailDO checkTaskDone(String id) {
RobotTaskDetailDO robotTaskDetail = taskDetailMapper.selectById(id);
if (RobotTaskStageEnum.DONE.getType().equals(robotTaskDetail.getTaskStage())) {
throw exception(ROBOT_LAST_TASK_NO_EXISTS);
@ -1033,13 +1043,14 @@ public class RobotInformationServiceImpl extends ServiceImpl<RobotInformationMap
/**
* 取放货
*
* @param pathPlanning
*/
private void takeReleaseTask(TaskToPathPlanningDTO pathPlanning) {
RobotTaskDetailDO robotTaskDetail = checkTaskDone(pathPlanning.getOrderId());
if (!RobotTaskStageEnum.TAKEING.getType().equals(robotTaskDetail.getTaskStage())
&& !RobotTaskStageEnum.GO_TAKE.getType().equals(robotTaskDetail.getTaskStage())
&& !RobotTaskStageEnum.UN_START.getType().equals(robotTaskDetail.getTaskStage())) {
&& !RobotTaskStageEnum.GO_TAKE.getType().equals(robotTaskDetail.getTaskStage())
&& !RobotTaskStageEnum.UN_START.getType().equals(robotTaskDetail.getTaskStage())) {
//只要放货
pathPlanning.setTakeLevel(null);
pathPlanning.setTakeGroupId(null);
@ -1048,10 +1059,10 @@ public class RobotInformationServiceImpl extends ServiceImpl<RobotInformationMap
pathPlanning.setTakeOffsetHeight(null);
pathPlanning.setTakeOffsetHeight(null);
pathPlanning.setTaskType(PathTaskTypeToRobotEnum.DROP_OFF_GOODS.getType());
}else {
} else {
takeCheck(robotTaskDetail.getFromLocationId(), robotTaskDetail.getRobotTaskId());
}
releaseCheck(robotTaskDetail.getToLocationId(),robotTaskDetail.getRobotTaskId());
releaseCheck(robotTaskDetail.getToLocationId(), robotTaskDetail.getRobotTaskId());
}
/**
@ -1070,7 +1081,7 @@ public class RobotInformationServiceImpl extends ServiceImpl<RobotInformationMap
}
List<WareHouseLocationDO> locations = wareHouseLocationMapper.selectList(new LambdaQueryWrapperX<WareHouseLocationDO>()
.eq(WareHouseLocationDO::getMapItemId, wareHouseLocation.getMapItemId())
.ne(WareHouseLocationDO::getId,id));
.ne(WareHouseLocationDO::getId, id));
if (ObjectUtil.isEmpty(locations)) {
return;
}
@ -1101,7 +1112,7 @@ public class RobotInformationServiceImpl extends ServiceImpl<RobotInformationMap
List<WareHouseLocationDO> locations = wareHouseLocationMapper.selectList(new LambdaQueryWrapperX<WareHouseLocationDO>()
.eq(WareHouseLocationDO::getMapItemId, wareHouseLocation.getMapItemId())
.ne(WareHouseLocationDO::getId,id));
.ne(WareHouseLocationDO::getId, id));
if (ObjectUtil.isEmpty(locations)) {
return;
}
@ -1117,6 +1128,7 @@ public class RobotInformationServiceImpl extends ServiceImpl<RobotInformationMap
/**
* 充电任务
*
* @param pathPlanning
* @param robot
*/
@ -1126,7 +1138,7 @@ public class RobotInformationServiceImpl extends ServiceImpl<RobotInformationMap
.eq(DeviceInformationDO::getDeviceUseStatus, DeviceUseStatusEnum.IDLE.getType())
.eq(DeviceInformationDO::getDeviceType, DeviceTypeEnum.CHARGING_STATION.getType()));
if (ObjectUtil.isEmpty(deviceInformations)) {
log.info("没有空闲的充电桩 :{}",robot.getRobotNo());
log.info("没有空闲的充电桩 :{}", robot.getRobotNo());
throw exception(ROBOT_NOT_FOUND_FREE_CHARGING_STATION);
}
@ -1136,7 +1148,7 @@ public class RobotInformationServiceImpl extends ServiceImpl<RobotInformationMap
.findFirst()
.orElse(new DeviceInformationDO());
if (ObjectUtil.isEmpty(deviceInformationDO.getDeviceNo())) {
log.info("当前机器人查不到对应的充电桩类型、或者机器人不能在此区域充电 :{}",robot.getRobotNo());
log.info("当前机器人查不到对应的充电桩类型、或者机器人不能在此区域充电 :{}", robot.getRobotNo());
throw exception(ROBOT_NOT_FOUND_FREE_CHARGING_STATION);
}
@ -1214,6 +1226,7 @@ public class RobotInformationServiceImpl extends ServiceImpl<RobotInformationMap
/**
* 获取楼层区域对应的机器人编号
*
* @param floor
* @param area
* @return
@ -1229,15 +1242,15 @@ public class RobotInformationServiceImpl extends ServiceImpl<RobotInformationMap
List<String> robotNos = robots.stream().map(RobotInformationDO::getRobotNo).collect(Collectors.toList());
List<String> list = new ArrayList<>();
String floorArea = floor+"-"+area;
String floorArea = floor + "-" + area;
Map<Object, Object> hmget = redisUtil.hmget(floorArea);
if (ObjectUtil.isEmpty(hmget)) {
return new ArrayList<>();
}
hmget.forEach((k,v) ->{
hmget.forEach((k, v) -> {
if (robotNos.contains(k)) {
list.add((String)k );
list.add((String) k);
}
});
@ -1246,6 +1259,7 @@ public class RobotInformationServiceImpl extends ServiceImpl<RobotInformationMap
/**
* 车辆一键暂停或启动
*
* @param robotSimulationPose
* @param robotNos
* @param str
@ -1262,5 +1276,90 @@ public class RobotInformationServiceImpl extends ServiceImpl<RobotInformationMap
}
}
@Override
public List<RobotTaskDO> selectDoingTaskByRobotNo(String robotNo) {
List<RobotTaskDO> list = taskMapper.selectDoingTaskByRobotNo(robotNo);
return list;
}
@Override
public RobotInformationDO getInformationByRobotNo(String robotNo) {
return informationMapper.selectOne(new LambdaQueryWrapper<RobotInformationDO>()
.eq(RobotInformationDO::getRobotNo, robotNo)
.last("limit 1"));
}
/**
* 校验机器人是否到达设定的电量
* false 不能做任务
*
* @param robotInformation
* @param commonConfig
* @return
*/
@Override
public Boolean checkRobotElectricity(RobotInformationDO robotInformation, CommonConfigDO commonConfig) {
if (ObjectUtil.isEmpty(commonConfig) || ObjectUtil.isEmpty(commonConfig.getConfigStr())) {
log.info("没有配置电量,不能做任务");
return false;
}
CommonConfigVO chargeConfig = JSONUtil.toBean(commonConfig.getConfigStr(), CommonConfigVO.class);
String pose2dKey = RobotTaskChcheConstant.ROBOT_INFORMATION_POSE_BAT_SOC + robotInformation.getMacAddress();
Object poseCache = redisUtil.get(pose2dKey);
if (ObjectUtil.isEmpty(poseCache)) {
log.info("车机没有电量信息 :{}", robotInformation.getRobotNo());
return false;
}
RobotStatusDataPoseDTO dataPoseDTO = JSON.parseObject((String) poseCache, RobotStatusDataPoseDTO.class);
if (ObjectUtil.isEmpty(dataPoseDTO.getBatSoc())) {
log.info("车机没有电量信息 :{}", robotInformation.getRobotNo());
return false;
}
if (ObjectUtil.isNotEmpty(chargeConfig) && ObjectUtil.isNotEmpty(chargeConfig.getStartAutoCharge())) {
BigDecimal robotRemainingElectricity = new BigDecimal(dataPoseDTO.getBatSoc());
BigDecimal robotEndElectricity = new BigDecimal(chargeConfig.getStartAutoCharge() + "");
if (robotRemainingElectricity.compareTo(robotEndElectricity) < 0) {
log.info("机器人的电量少于自动充电电量,不能接任务 :{}", robotInformation.getRobotNo());
return false;
}
}
return checkElectricity(chargeConfig,robotInformation,dataPoseDTO);
}
private Boolean checkElectricity(CommonConfigVO chargeConfig, RobotInformationDO robot, RobotStatusDataPoseDTO dataPoseDTO) {
String chargeModelKey = RobotTaskChcheConstant.ROBOT_CHARGE_MODEL + robot.getRobotNo();
Object chargeModelCache = redisUtil.get(chargeModelKey);
log.info("充电机器人编号:{} ,信息: {}", robot.getRobotNo(), JSON.toJSONString(dataPoseDTO));
//车子剩余电量
BigDecimal robotRemainingElectricity = new BigDecimal(dataPoseDTO.getBatSoc());
//设置离开的电量
BigDecimal robotEndElectricity = new BigDecimal("10");
if (ObjectUtil.isNotEmpty(robot.getAutoCharge()) && ObjectUtil.isNotEmpty(chargeModelCache)
&& !ChargeModelEnum.FULL.getType().equals((Integer) chargeModelCache)) {
robotEndElectricity = new BigDecimal(String.valueOf(robot.getAutoCharge()));
} 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)
&& ObjectUtil.isNotEmpty(chargeConfig.getChanceChargeEnd())) {
robotEndElectricity = new BigDecimal(String.valueOf(chargeConfig.getChanceChargeEnd()));
} else if (ObjectUtil.isNotEmpty(chargeConfig.getEndAutoCharge())){
robotEndElectricity = new BigDecimal(String.valueOf(chargeConfig.getEndAutoCharge()));
}
if (robotRemainingElectricity.compareTo(robotEndElectricity) >= 0) {
return true;
}else {
log.info("机器人正在充电,还没达到充电设置的电量,暂不能接任务:{} ", robot.getRobotNo());
}
return false;
}
}

View File

@ -54,7 +54,7 @@ public class DistributeTasksServiceImpl implements DistributeTasksService {
@Autowired
private RobotTaskDetailMapper robotTaskDetailMapper;
@Value("${zn.full_electricity:100}")
@Value("${zn.full_electricity:95}")
private String fullElectricity;
@Resource
@ -111,6 +111,7 @@ public class DistributeTasksServiceImpl implements DistributeTasksService {
}
Object cargoDetected = redisUtil.get(cargoDetectedKey);
//取货的先执行放货再去充电
if (ObjectUtil.isNotEmpty(lastTaskDetailMap) && ObjectUtil.isNotEmpty(lastTaskDetailMap.get(robot.getRobotNo()))) {
robot.setRobotStatus(RobotStatusEnum.LAST_TASK_IS_TAKE.getType());
continue;
@ -140,10 +141,11 @@ public class DistributeTasksServiceImpl implements DistributeTasksService {
continue;
}
//自动充电的车子电量到达设定的阀值也能执行任务
if (ChargeTypeEnum.AUTOMATIC.getType().equals(robot.getChargeType())
/*if (ChargeTypeEnum.AUTOMATIC.getType().equals(robot.getChargeType())
&& RobotStatusEnum.CHARGE.getType().equals(robot.getRobotStatus())) {
setRobotStatus(commonConfigDO, robot);
}
}*/
setRobotStatus(commonConfigDO, robot);
}
robots = robots.stream()
@ -238,16 +240,17 @@ public class DistributeTasksServiceImpl implements DistributeTasksService {
//车子剩余电量
BigDecimal robotRemainingElectricity = new BigDecimal(dataPoseDTO.getBatSoc());
//设置离开的电量
BigDecimal robotEndElectricity = null;
BigDecimal robotEndElectricity = new BigDecimal("10");
if (ObjectUtil.isNotEmpty(robot.getAutoCharge()) && ObjectUtil.isNotEmpty(chargeModelCache)
&& !ChargeModelEnum.FULL.getType().equals((Integer) chargeModelCache)) {
robotEndElectricity = new BigDecimal(String.valueOf(robot.getAutoCharge()));
} 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)) {
} else if (ObjectUtil.isNotEmpty(chargeModelCache) && ChargeModelEnum.CHANCE.getType().equals((Integer) chargeModelCache)
&& ObjectUtil.isNotEmpty(chargeConfig.getEndAutoCharge())) {
robotEndElectricity = new BigDecimal(String.valueOf(chargeConfig.getChanceChargeEnd()));
} else {
} else if (ObjectUtil.isNotEmpty(chargeConfig.getEndAutoCharge())){
robotEndElectricity = new BigDecimal(String.valueOf(chargeConfig.getEndAutoCharge()));
}