Merge branch 'dev' of http://git.znkjfw.com/ak/zn-cloud-wcs into aikai
This commit is contained in:
commit
22f58ed6b0
@ -1,7 +1,9 @@
|
||||
package cn.iocoder.yudao.framework.common.util.date;
|
||||
|
||||
import cn.hutool.core.date.LocalDateTimeUtil;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.time.*;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.Calendar;
|
||||
@ -33,6 +35,21 @@ public class DateUtils {
|
||||
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMdd");
|
||||
return currentDate.format(formatter);
|
||||
}
|
||||
|
||||
public static String getYearMonthDayHourMinuteSecon() {
|
||||
LocalDateTime currentDate = LocalDateTime.now();
|
||||
DateTimeFormatter formatter = DateTimeFormatter.ofPattern(FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND);
|
||||
return currentDate.format(formatter);
|
||||
}
|
||||
|
||||
public static String getYYYMMDD(Date date) {
|
||||
if (ObjectUtil.isEmpty(date)) {
|
||||
date = new Date();
|
||||
}
|
||||
SimpleDateFormat simpleDateFormat=new SimpleDateFormat("yyyy-MM-dd");
|
||||
return simpleDateFormat.format(date);
|
||||
}
|
||||
|
||||
/**
|
||||
* 将 LocalDateTime 转换成 Date
|
||||
*
|
||||
|
@ -251,6 +251,7 @@ public class GlobalExceptionHandler {
|
||||
for (StackTraceElement stackTrace : stackTraces) {
|
||||
if (ObjUtil.notEqual(stackTrace.getClassName(), ServiceExceptionUtil.class.getName())) {
|
||||
log.warn("[serviceExceptionHandler]\n\t{}", stackTrace);
|
||||
log.warn("异常信息 :{}",ex.getMessage());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -17,7 +17,7 @@ import java.util.List;
|
||||
public interface PathPlanningApi {
|
||||
String PREFIX = ApiConstants.PREFIX + "/config";
|
||||
|
||||
@PostMapping(PREFIX + "/synchronousPoint")
|
||||
/* @PostMapping(PREFIX + "/synchronousPoint")
|
||||
@Operation(summary = "同步ware_position_map_line的点位信息")
|
||||
void synchronousPointToPP(@RequestBody PositionMapLinePathDTO relatedPathNode, @RequestParam("topic") String topic);
|
||||
|
||||
@ -28,5 +28,5 @@ public interface PathPlanningApi {
|
||||
|
||||
@PostMapping(PREFIX + "/synchronousLineObject")
|
||||
@Operation(summary = "同步Object信息给PP")
|
||||
void synchronousLineObject(@RequestBody Object obj, @RequestParam("topic") String topic);
|
||||
void synchronousLineObject(@RequestBody Object obj, @RequestParam("topic") String topic);*/
|
||||
}
|
||||
|
@ -0,0 +1,13 @@
|
||||
package cn.iocoder.yudao.module.mqtt.api.path.dto;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class PathToRobotArgDTO {
|
||||
private Long floor;
|
||||
private String areaId;
|
||||
private String mapName;
|
||||
private String poseId;
|
||||
private PathToRobotArgPoseDTO pose2d;
|
||||
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
package cn.iocoder.yudao.module.mqtt.api.path.dto;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class PathToRobotArgPoseDTO {
|
||||
private Double x;
|
||||
|
||||
private Double y;
|
||||
|
||||
private Double yaw;
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
package cn.iocoder.yudao.module.mqtt.api.path.dto;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class PathToRobotDTO {
|
||||
|
||||
//这个实体类的信息,不能修改
|
||||
//这个实体类的信息,不能修改
|
||||
//这个实体类的信息,不能修改
|
||||
//这个实体类的信息,不能修改
|
||||
//这个实体类的信息,不能修改
|
||||
//这个实体类的信息,不能修改
|
||||
private String orderType;
|
||||
private Integer isCommandEnd;
|
||||
private String robotNo;
|
||||
private String commandType;
|
||||
private PathToRobotArgDTO arg;
|
||||
}
|
@ -15,7 +15,7 @@ import java.util.List;
|
||||
public class PositionMapItemSynDTO {
|
||||
|
||||
@Schema(description = "主键ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "31007")
|
||||
private Long id;
|
||||
private String id;
|
||||
|
||||
@Schema(description = "坐标x轴")
|
||||
private Double x;
|
||||
|
@ -18,7 +18,7 @@ public interface RobotTaskApi {
|
||||
|
||||
String PREFIX = ApiConstants.PREFIX + "/config";
|
||||
|
||||
@PostMapping(PREFIX + "/distribute/tasks")
|
||||
/*@PostMapping(PREFIX + "/distribute/tasks")
|
||||
@Operation(summary = "下发任务给车机")
|
||||
void sendTaskToRobot(@Valid @RequestBody List<RobotAcceptTaskDTO> robotTaskDOS );
|
||||
void sendTaskToRobot(@Valid @RequestBody List<RobotAcceptTaskDTO> robotTaskDOS );*/
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
package cn.iododer.yudao.module.mqtt.api.common;
|
||||
|
||||
import cn.iocoder.yudao.module.mqtt.api.common.CommonApi;
|
||||
import cn.iododer.yudao.module.mqtt.config.MqttFactory;
|
||||
import cn.iododer.yudao.module.mqtt.util.MqttUtils;
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
@ -26,7 +26,7 @@ public class PathPlanningApiImpl implements PathPlanningApi {
|
||||
* @param relatedPathNode
|
||||
* @param topic
|
||||
*/
|
||||
@Override
|
||||
/*@Override
|
||||
public void synchronousPointToPP(PositionMapLinePathDTO relatedPathNode, String topic) {
|
||||
try {
|
||||
mqttUtils.pub(topic, JSON.toJSONString(relatedPathNode));
|
||||
@ -36,11 +36,11 @@ public class PathPlanningApiImpl implements PathPlanningApi {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*//**
|
||||
* 同步ware_position_map_item的点位信息
|
||||
* @param positionMapItemSynDTOS
|
||||
* @param topic
|
||||
*/
|
||||
*//*
|
||||
@Override
|
||||
public void synchronousAllItemToPP(List<PositionMapItemSynDTO> positionMapItemSynDTOS, String topic) {
|
||||
try {
|
||||
@ -59,5 +59,5 @@ public class PathPlanningApiImpl implements PathPlanningApi {
|
||||
} catch (MqttException e) {
|
||||
log.info("同步信息给PP--完成--异常 :{}",e);
|
||||
}
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
@ -23,7 +23,7 @@ public class RobotTaskApiImpl implements RobotTaskApi {
|
||||
@Autowired
|
||||
private MqttUtils mqttUtils;
|
||||
|
||||
@Override
|
||||
/*@Override
|
||||
public void sendTaskToRobot(List<RobotAcceptTaskDTO> robotTaskDOS) {
|
||||
for (RobotAcceptTaskDTO robotTaskDO : robotTaskDOS) {
|
||||
log.info("发送MQTT消息 :{}",JSON.toJSONString(robotTaskDO));
|
||||
@ -33,5 +33,5 @@ public class RobotTaskApiImpl implements RobotTaskApi {
|
||||
log.info("消息发送异常 :{}",e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
@ -1,15 +1,15 @@
|
||||
package cn.iododer.yudao.module.mqtt.config;
|
||||
|
||||
import cn.iododer.yudao.module.mqtt.service.MqttService;
|
||||
import cn.iododer.yudao.module.mqtt.service.RobotTaskStatusServiceImpl;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.eclipse.paho.client.mqttv3.IMqttAsyncClient;
|
||||
import org.eclipse.paho.client.mqttv3.IMqttDeliveryToken;
|
||||
import org.eclipse.paho.client.mqttv3.MqttCallback;
|
||||
import org.eclipse.paho.client.mqttv3.MqttMessage;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
/**
|
||||
* MQTT回调
|
||||
*/
|
||||
@ -35,7 +35,7 @@ public class MqttCallBack implements MqttCallback {
|
||||
*/
|
||||
@Override
|
||||
public void messageArrived(String topic, MqttMessage mqttMessage) throws Exception {
|
||||
String msg = new String(mqttMessage.getPayload());
|
||||
String msg = new String(mqttMessage.getPayload(), StandardCharsets.UTF_8);
|
||||
// log.info("[MQTT]接收当前消息为 :{}", msg);
|
||||
|
||||
try {
|
||||
|
@ -147,6 +147,8 @@ public class MqttFactory {
|
||||
return BeanUtils.getBean(RobotUpdatePalletHeightServiceImpl.class);
|
||||
case ROBOT_OBSTACLES_STATUS:
|
||||
return BeanUtils.getBean(RobotObstaclesStatusServiceImpl.class);
|
||||
case ROBOT_WIRELESS_SIGNAL_STATUS:
|
||||
return BeanUtils.getBean(RobotWirelessSignalStatusServiceImpl.class);
|
||||
case PLANNING_INIT_DATA:
|
||||
return BeanUtils.getBean(PathPlanningInitDataServiceImpl.class);
|
||||
case PLANNING_DISTRIBUTION_TASK:
|
||||
|
@ -22,6 +22,7 @@ public enum DefineSubTopicEnum {
|
||||
ROBOT_WORK_STATUS("ROBOT_WORK_STATUS", 2,"作业实时行为上报"),
|
||||
ROBOT_UPDATE_PALLET_HEIGHT("UPDATE_PALLET_HEIGHT", 2,"放货后货物高度反馈和取货后货物高度反馈"),
|
||||
ROBOT_OBSTACLES_STATUS("ROBOT_OBSTACLES_STATUS", 2,"障碍物状态上报"),
|
||||
ROBOT_WIRELESS_SIGNAL_STATUS("ROBOT_WIRELESS_SIGNAL_STATUS", 2,"信号强度上报"),
|
||||
PLANNING_INIT_DATA("SYNCHRONOUS_ALL_MAP_REQUEST", 2,"路径规划需要初始数据上报"),
|
||||
PLANNING_DISTRIBUTION_TASK("TASK_ASSIGNMENT_FEEDBACK", 2,"路径规划任务分配上报"),
|
||||
PLANNING_DISTRIBUTION_FAIL("TASK_ASSIGNMENT_FAIL", 2,"路径规划失败上报"),
|
||||
|
@ -22,7 +22,7 @@ public class RobotStatusServiceImpl implements MqttService {
|
||||
*/
|
||||
@Override
|
||||
public void analysisMessage(String message) {
|
||||
log.info("处理RobotStatusServiceImpl的消息 :{}", message);
|
||||
// log.info("处理RobotStatusServiceImpl的消息 :{}", message);
|
||||
RobotPoseStatusDTO robotStatusData = JSON.parseObject(message, RobotPoseStatusDTO.class);
|
||||
robotStatusApi.robotStatusUpdate(robotStatusData);
|
||||
}
|
||||
|
@ -0,0 +1,22 @@
|
||||
package cn.iododer.yudao.module.mqtt.service;
|
||||
|
||||
|
||||
import cn.iocoder.yudao.module.remote.api.path.RemotePathApi;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
@Slf4j
|
||||
@Service
|
||||
public class RobotWirelessSignalStatusServiceImpl implements MqttService{
|
||||
|
||||
@Resource
|
||||
private RemotePathApi remotePathApi;
|
||||
|
||||
@Override
|
||||
public void analysisMessage(String message) {
|
||||
log.info("车辆信号上报 :{}",message);
|
||||
remotePathApi.wirelessSignalStatus(message);
|
||||
}
|
||||
}
|
@ -12,6 +12,8 @@ spring:
|
||||
config: # 【注册中心】配置项
|
||||
namespace: dev # 命名空间。这里使用 dev 开发环境
|
||||
group: DEFAULT_GROUP # 使用的 Nacos 配置分组,默认为 DEFAULT_GROUP
|
||||
mqtt:
|
||||
charset: UTF-8
|
||||
|
||||
# Lock4j 配置项
|
||||
lock4j:
|
||||
|
@ -12,6 +12,8 @@ spring:
|
||||
config: # 【注册中心】配置项
|
||||
namespace: dev # 命名空间。这里使用 dev 开发环境
|
||||
group: DEFAULT_GROUP # 使用的 Nacos 配置分组,默认为 DEFAULT_GROUP
|
||||
mqtt:
|
||||
charset: UTF-8
|
||||
|
||||
# Lock4j 配置项
|
||||
lock4j:
|
||||
@ -33,6 +35,7 @@ management:
|
||||
mqtt:
|
||||
# host: tcp://123.57.12.40:1883
|
||||
host: tcp://127.0.0.1:1883
|
||||
# host: tcp://10.10.7.195:1883
|
||||
username: adminuser
|
||||
password: adminuser
|
||||
qos: 2
|
||||
|
@ -12,6 +12,8 @@ spring:
|
||||
config: # 【注册中心】配置项
|
||||
namespace: dev # 命名空间。这里使用 dev 开发环境
|
||||
group: DEFAULT_GROUP # 使用的 Nacos 配置分组,默认为 DEFAULT_GROUP
|
||||
mqtt:
|
||||
charset: UTF-8
|
||||
|
||||
# Lock4j 配置项
|
||||
lock4j:
|
||||
@ -31,7 +33,7 @@ management:
|
||||
|
||||
# MQTT
|
||||
mqtt:
|
||||
# host: tcp://192.168.0.54:1883
|
||||
# host: tcp://123.57.12.40:1883
|
||||
host: tcp://127.0.0.1:1883
|
||||
username: adminuser
|
||||
password: adminuser
|
||||
|
@ -31,7 +31,7 @@
|
||||
<!-- 启动服务时,是否清理历史日志,一般不建议清理 -->
|
||||
<cleanHistoryOnStart>${LOGBACK_ROLLINGPOLICY_CLEAN_HISTORY_ON_START:-false}</cleanHistoryOnStart>
|
||||
<!-- 日志文件,到达多少容量,进行滚动 -->
|
||||
<maxFileSize>${LOGBACK_ROLLINGPOLICY_MAX_FILE_SIZE:-10MB}</maxFileSize>
|
||||
<maxFileSize>50MB</maxFileSize>
|
||||
<!-- 日志文件的总大小,0 表示不限制 -->
|
||||
<totalSizeCap>${LOGBACK_ROLLINGPOLICY_TOTAL_SIZE_CAP:-0}</totalSizeCap>
|
||||
<!-- 日志文件的保留天数 -->
|
||||
|
@ -16,4 +16,7 @@ public interface RemotePathApi {
|
||||
@Operation(summary = "远遥同步车辆导航行走路程信息")
|
||||
void remoteDistanceInformation(@RequestParam("message") String message);
|
||||
|
||||
@PostMapping(PREFIX + "/wirelessSignalStatus")
|
||||
@Operation(summary = "车辆信号信息")
|
||||
void wirelessSignalStatus(@RequestParam("message") String message);
|
||||
}
|
||||
|
@ -0,0 +1,15 @@
|
||||
package cn.iocoder.yudao.module.remote.api.path.dto;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class RemoteRobotWirelessSignalDTO {
|
||||
|
||||
private String mac;
|
||||
|
||||
/**
|
||||
* 整型,单位dBm
|
||||
*/
|
||||
private String wirelessSignal;
|
||||
|
||||
}
|
@ -1,6 +1,7 @@
|
||||
package cn.iocoder.yudao.module.remote.api.path;
|
||||
|
||||
import cn.iocoder.yudao.module.remote.api.path.dto.RemoteRobotDistanceInformationDTO;
|
||||
import cn.iocoder.yudao.module.remote.api.path.dto.RemoteRobotWirelessSignalDTO;
|
||||
import cn.iocoder.yudao.module.remote.service.robot.RemoteRobotService;
|
||||
import cn.iocoder.yudao.module.remote.util.redis.RedisUtil;
|
||||
import com.alibaba.fastjson.JSON;
|
||||
@ -31,5 +32,15 @@ public class RemotePathApiImpl implements RemotePathApi{
|
||||
remoteRobotService.remoteDistanceInformation(data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 车辆信号信息
|
||||
* @param message
|
||||
*/
|
||||
@Override
|
||||
public void wirelessSignalStatus(String message) {
|
||||
RemoteRobotWirelessSignalDTO data = JSON.parseObject(message, RemoteRobotWirelessSignalDTO.class);
|
||||
remoteRobotService.sendRobotWirelessSignalStatus(data);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -1,13 +1,14 @@
|
||||
package cn.iocoder.yudao.module.remote.api.robot;
|
||||
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import cn.iocoder.yudao.module.remote.config.ip.IpProperties;
|
||||
import cn.iocoder.yudao.module.remote.controller.admin.robot.dto.Cockpit;
|
||||
import cn.iocoder.yudao.module.remote.controller.admin.robot.dto.RemoteControllerSocketDTO;
|
||||
import cn.iocoder.yudao.module.remote.enums.robot.RemoteIpTypeEnum;
|
||||
import cn.iocoder.yudao.module.remote.util.crc.CRCUtil;
|
||||
import cn.iocoder.yudao.module.system.api.remote.dto.RemoteRobotTransferDTO;
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import lombok.SneakyThrows;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@ -28,18 +29,13 @@ import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.REMOTE_ROB
|
||||
@Component
|
||||
@Slf4j
|
||||
public class RemoteControllerProcessor {
|
||||
private final ConcurrentHashMap<String, RemoteControllerSocketDTO> cache = new ConcurrentHashMap<>();
|
||||
public final ConcurrentHashMap<String, RemoteControllerSocketDTO> cache = new ConcurrentHashMap<>();
|
||||
|
||||
private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
|
||||
public final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
|
||||
|
||||
@Value("${remote.msg}")
|
||||
private String defaultMsg;
|
||||
|
||||
@Value("${remote.controller-ip}")
|
||||
private String remoteControllerIp;
|
||||
|
||||
@Value("${remote.controller-port}")
|
||||
private int remoteControllerPort;
|
||||
|
||||
@Value("${remote.cockpit-time-out}")
|
||||
private int cockpitTimeOut;
|
||||
@ -53,35 +49,43 @@ public class RemoteControllerProcessor {
|
||||
private final String ONE = "01";
|
||||
private final String TWO = "02";
|
||||
|
||||
public void addCache(RemoteRobotTransferDTO dto) {
|
||||
RemoteControllerSocketDTO remoteControllerSocketDTO = cache.get(remoteControllerIp);
|
||||
log.info("缓存的数据 :{}", JSON.toJSONString(remoteControllerSocketDTO));
|
||||
@Autowired
|
||||
private IpProperties ipProperties;
|
||||
|
||||
public void addCache(RemoteRobotTransferDTO dto,String ip) {
|
||||
Cockpit cockpit = ipProperties.getCockpitByIp(ip);
|
||||
String cockpitIp = cockpit.getControllerIp();
|
||||
int cockpitPort = cockpit.getControllerPort();
|
||||
|
||||
RemoteControllerSocketDTO remoteControllerSocketDTO = cache.get(cockpitIp);
|
||||
log.info("是否为空 :{}",ObjectUtil.isEmpty(remoteControllerSocketDTO));
|
||||
if (ObjectUtil.isNotEmpty(remoteControllerSocketDTO)) {
|
||||
try {
|
||||
Socket socket = remoteControllerSocketDTO.getSocket();
|
||||
if (socket != null && !socket.isClosed()) {
|
||||
socket.close();
|
||||
}
|
||||
log.info("关闭socket :{}", remoteControllerIp);
|
||||
log.info("关闭socket :{}", cockpitIp);
|
||||
} catch (IOException e) {
|
||||
log.error("关闭socket出现异常 :{}", remoteControllerIp);
|
||||
log.error("关闭socket出现异常 :{}", cockpitIp);
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
} else {
|
||||
remoteControllerSocketDTO = new RemoteControllerSocketDTO();
|
||||
}
|
||||
remoteControllerSocketDTO.setHost(remoteControllerIp);
|
||||
remoteControllerSocketDTO.setPort(remoteControllerPort);
|
||||
remoteControllerSocketDTO.setControllerIp(cockpitIp);
|
||||
remoteControllerSocketDTO.setControllerPort(cockpitPort);
|
||||
Socket socket = new Socket();
|
||||
try {
|
||||
socket.connect(new InetSocketAddress(remoteControllerIp, remoteControllerPort), 1000);
|
||||
socket.setKeepAlive(true);
|
||||
socket.connect(new InetSocketAddress(cockpitIp, cockpitPort), 500);
|
||||
remoteControllerSocketDTO.setSocket(socket);
|
||||
} catch (IOException e) {
|
||||
log.error("添加socket失败 :{}", e);
|
||||
throw exception(REMOTE_ROBOT_CONNECT_FAIL);
|
||||
}
|
||||
setMsg(remoteControllerSocketDTO, RemoteIpTypeEnum.ONE.getType(), dto);
|
||||
cache.put(remoteControllerIp, remoteControllerSocketDTO);
|
||||
cache.put(cockpitIp, remoteControllerSocketDTO);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -108,7 +112,7 @@ public class RemoteControllerProcessor {
|
||||
String portHex = Integer.toHexString(dto.getRobotPort().intValue());
|
||||
String portHexOne = portHex.substring(0, 2);
|
||||
String portHexTwo = portHex.substring(2);
|
||||
msg = msg + " " + portHexOne + " " + portHexTwo;
|
||||
msg = msg + " " + portHexTwo + " " + portHexOne;
|
||||
if (cockpitTimeOut > 0) {
|
||||
msg = msg + " " + ONE + " " + Integer.toHexString(cockpitTimeOut);
|
||||
} else {
|
||||
@ -136,34 +140,38 @@ public class RemoteControllerProcessor {
|
||||
remoteControllerSocket.setMsg(msg);
|
||||
}
|
||||
|
||||
public void remoteCache(RemoteRobotTransferDTO dto) {
|
||||
RemoteControllerSocketDTO remoteControllerSocketDTO = cache.get(remoteControllerIp);
|
||||
public void remoteCache(RemoteRobotTransferDTO dto,String ip) {
|
||||
Cockpit cockpit = ipProperties.getCockpitByIp(ip);
|
||||
String cockpitIp = cockpit.getControllerIp();
|
||||
RemoteControllerSocketDTO remoteControllerSocketDTO = cache.get(cockpitIp);
|
||||
if (ObjectUtil.isEmpty(remoteControllerSocketDTO)) {
|
||||
return;
|
||||
}
|
||||
setMsg(remoteControllerSocketDTO, RemoteIpTypeEnum.THREE.getType(), dto);
|
||||
cache.remove(remoteControllerIp);
|
||||
cache.remove(cockpitIp);
|
||||
|
||||
Socket socket = remoteControllerSocketDTO.getSocket();
|
||||
if (socket == null ||socket.isClosed()) {
|
||||
if (socket == null || socket.isClosed()) {
|
||||
try {
|
||||
socket = new Socket();
|
||||
socket.connect(new InetSocketAddress(remoteControllerIp, remoteControllerPort), 1000);
|
||||
log.info("连接新的的socket");
|
||||
socket.setKeepAlive(true);
|
||||
socket.connect(new InetSocketAddress(cockpitIp, cockpit.getControllerPort()), 1000);
|
||||
} catch (IOException e) {
|
||||
log.error("连接socket出现异常 :{}", remoteControllerIp);
|
||||
log.error("连接socket出现异常 :{}", cockpitIp);
|
||||
}
|
||||
}
|
||||
|
||||
OutputStream os = null;
|
||||
try {
|
||||
os = socket.getOutputStream();
|
||||
log.info("断开连接 :{} ,对应的IP :{}", remoteControllerSocketDTO.getMsg(), remoteControllerSocketDTO.getHost());
|
||||
log.info("断开连接 :{} ,对应的IP :{}", remoteControllerSocketDTO.getMsg(), remoteControllerSocketDTO.getControllerIp());
|
||||
os.write(remoteControllerSocketDTO.getMsg().getBytes());
|
||||
socket.shutdownInput();
|
||||
socket.close();
|
||||
log.info("关闭socket :{}", remoteControllerIp);
|
||||
log.info("关闭socket :{}", cockpitIp);
|
||||
} catch (IOException e) {
|
||||
log.error("关闭socket出现异常 :{}", remoteControllerIp);
|
||||
log.error("关闭socket出现异常 :{}", cockpitIp);
|
||||
} finally {
|
||||
if (ObjectUtil.isNotEmpty(os)) {
|
||||
try {
|
||||
@ -173,41 +181,28 @@ public class RemoteControllerProcessor {
|
||||
}
|
||||
}
|
||||
|
||||
remoteCache(dto);
|
||||
remoteCache(dto,ip);
|
||||
}
|
||||
|
||||
|
||||
public RemoteControllerProcessor() {
|
||||
/*public RemoteControllerProcessor() {
|
||||
// 每秒执行一次 - 处理并发送数据 - 避免数据丢失
|
||||
scheduler.scheduleAtFixedRate(this::processAndSend, 150, 150, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
}*/
|
||||
|
||||
private void processAndSend() {
|
||||
public void processAndSend() {
|
||||
if (ObjectUtil.isEmpty(cache)) {
|
||||
return;
|
||||
}
|
||||
log.info("socket发送数据开始");
|
||||
// log.info("socket发送数据开始");
|
||||
for (Map.Entry<String, RemoteControllerSocketDTO> v : cache.entrySet()) {
|
||||
RemoteControllerSocketDTO remoteControllerSocketDTO = v.getValue();
|
||||
if (ObjectUtil.isEmpty(remoteControllerSocketDTO)) {
|
||||
remoteControllerSocketDTO = new RemoteControllerSocketDTO();
|
||||
remoteControllerSocketDTO.setHost(v.getKey());
|
||||
remoteControllerSocketDTO.setPort(remoteControllerPort);
|
||||
try {
|
||||
Socket socket = new Socket();
|
||||
socket.connect(new InetSocketAddress(v.getKey(), remoteControllerPort), 1000);
|
||||
remoteControllerSocketDTO.setSocket(socket);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
cache.put(v.getKey(), remoteControllerSocketDTO);
|
||||
}
|
||||
|
||||
Socket socket = remoteControllerSocketDTO.getSocket();
|
||||
if (socket == null || socket.isClosed()) {
|
||||
socket = new Socket();
|
||||
try {
|
||||
socket.connect(new InetSocketAddress(v.getKey(), remoteControllerPort), 1000);
|
||||
socket.connect(new InetSocketAddress(v.getKey(), remoteControllerSocketDTO.getControllerPort()), 1000);
|
||||
remoteControllerSocketDTO.setSocket(socket);
|
||||
} catch (IOException e) {
|
||||
log.error("socket重连异常 :{}", e);
|
||||
@ -218,8 +213,8 @@ public class RemoteControllerProcessor {
|
||||
try {
|
||||
os = socket.getOutputStream();
|
||||
String str = remoteControllerSocketDTO.getMsg();
|
||||
log.info("socket推送的数据 :{}", str);
|
||||
os.write(remoteControllerSocketDTO.getMsg().getBytes());
|
||||
log.info("socket推送的数据 :{}", str);
|
||||
} catch (IOException e) {
|
||||
log.error("socket发送异常 :{}", e);
|
||||
} finally {
|
||||
@ -230,7 +225,6 @@ public class RemoteControllerProcessor {
|
||||
}
|
||||
}
|
||||
}
|
||||
log.info("socket发送数据成功");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,36 @@
|
||||
package cn.iocoder.yudao.module.remote.api.robot;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.scheduling.annotation.EnableScheduling;
|
||||
import org.springframework.scheduling.annotation.Scheduled;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
@EnableScheduling
|
||||
@Component
|
||||
@Slf4j
|
||||
public class RemoteScheduledTasks {
|
||||
|
||||
private static final ExecutorService fixedThreadPool = Executors.newFixedThreadPool(3);
|
||||
|
||||
@Resource
|
||||
private RemoteControllerProcessor remoteControllerProcessor;
|
||||
|
||||
// 这个方法将每200毫秒执行一次
|
||||
@Scheduled(fixedDelay = 300, timeUnit = TimeUnit.MILLISECONDS)
|
||||
public void executeTask() {
|
||||
fixedThreadPool.execute(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
remoteControllerProcessor.processAndSend();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,31 @@
|
||||
package cn.iocoder.yudao.module.remote.config.ip;
|
||||
|
||||
|
||||
import cn.iocoder.yudao.module.remote.controller.admin.robot.dto.Cockpit;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Component
|
||||
@ConfigurationProperties(prefix ="remote",ignoreInvalidFields = true)
|
||||
@Getter
|
||||
@Setter
|
||||
public class IpProperties {
|
||||
|
||||
private List<Cockpit> cockpit;
|
||||
|
||||
public Cockpit getCockpitByIp(String ip) {
|
||||
for (Cockpit v : cockpit) {
|
||||
if (ip.equals(v.getIpcIp())){
|
||||
return v;
|
||||
}
|
||||
}
|
||||
Cockpit data = new Cockpit();
|
||||
data.setControllerIp("127.0.0.1");
|
||||
data.setControllerPort(9000);
|
||||
return data;
|
||||
}
|
||||
}
|
@ -8,4 +8,6 @@ public class RobotTaskChcheConstant {
|
||||
//机器人编号和mac地址映射(通过机器人编号。查询mac地址) (拼接的是机器人编号)
|
||||
public static String ROBOT_GET_MAC_BY_NO = "robot:information:getMac:ByNo";
|
||||
|
||||
//机器人mac地址和机器人编号映射(通过mac地址。查询机器人编号) (拼接的是mac地址)
|
||||
public static String ROBOT_GET_ROBOTNO_BY_MAC = "robot:information:getRobotNo:ByMac";
|
||||
}
|
||||
|
@ -0,0 +1,14 @@
|
||||
package cn.iocoder.yudao.module.remote.controller.admin.robot.dto;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class Cockpit {
|
||||
@Schema(description = "工控机IP")
|
||||
private String ipcIp;
|
||||
@Schema(description = "驾舱端口")
|
||||
private int controllerPort;
|
||||
@Schema(description = "驾舱IP")
|
||||
private String controllerIp;
|
||||
}
|
@ -1,13 +1,16 @@
|
||||
package cn.iocoder.yudao.module.remote.controller.admin.robot.dto;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.net.Socket;
|
||||
|
||||
@Data
|
||||
public class RemoteControllerSocketDTO {
|
||||
private String host;
|
||||
private int port;
|
||||
@Schema(description = "驾舱IP")
|
||||
private String controllerIp;
|
||||
@Schema(description = "驾舱端口")
|
||||
private int controllerPort;
|
||||
private Socket socket;
|
||||
private String msg;
|
||||
}
|
||||
|
@ -3,6 +3,8 @@ 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.Max;
|
||||
import javax.validation.constraints.Min;
|
||||
import javax.validation.constraints.NotEmpty;
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
@ -10,6 +12,8 @@ import javax.validation.constraints.NotNull;
|
||||
public class RemoteRobotChangeModeDTO {
|
||||
@Schema(description = "远遥模式(0:自动模式, 1:手动模式, 2:自由模式)")
|
||||
@NotNull(message = "请选择远遥模式")
|
||||
@Max(value = 2,message = "请选择远遥模式")
|
||||
@Min(value = 0,message = "请选择远遥模式")
|
||||
private Integer remoteMode = 0;
|
||||
|
||||
@Schema(description = "车辆编号")
|
||||
|
@ -37,7 +37,7 @@ public class LoginServiceImpl implements LoginService {
|
||||
@Override
|
||||
public Boolean checkCommunication(LoginCheckDTO loginCheckDTO) {
|
||||
HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory();
|
||||
factory.setConnectTimeout(5 * 1000);
|
||||
factory.setConnectTimeout(2 * 1000);
|
||||
RestTemplate restTemplate = new RestTemplate(factory);
|
||||
String url = "http://" + loginCheckDTO.getSystemIp() + ":" + loginCheckDTO.getSystemPort() + checkUrl;
|
||||
LinkedMultiValueMap<String, String> headers = new LinkedMultiValueMap<>();
|
||||
|
@ -1,6 +1,7 @@
|
||||
package cn.iocoder.yudao.module.remote.service.robot;
|
||||
|
||||
import cn.iocoder.yudao.module.remote.api.path.dto.RemoteRobotDistanceInformationDTO;
|
||||
import cn.iocoder.yudao.module.remote.api.path.dto.RemoteRobotWirelessSignalDTO;
|
||||
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.controller.admin.robot.dto.RemoteRobotTaskDoneDTO;
|
||||
@ -76,4 +77,10 @@ public interface RemoteRobotService {
|
||||
* @param data
|
||||
*/
|
||||
void remoteDistanceInformation(RemoteRobotDistanceInformationDTO data);
|
||||
|
||||
/**
|
||||
* 上报车辆信号信息
|
||||
* @param data
|
||||
*/
|
||||
void sendRobotWirelessSignalStatus(RemoteRobotWirelessSignalDTO data);
|
||||
}
|
||||
|
@ -5,9 +5,12 @@ import cn.hutool.json.JSONUtil;
|
||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||
import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder;
|
||||
import cn.iocoder.yudao.module.remote.api.path.dto.RemoteRobotDistanceInformationDTO;
|
||||
import cn.iocoder.yudao.module.remote.api.path.dto.RemoteRobotWirelessSignalDTO;
|
||||
import cn.iocoder.yudao.module.remote.api.robot.RemoteControllerProcessor;
|
||||
import cn.iocoder.yudao.module.remote.api.webSocket.RequestProcessor;
|
||||
import cn.iocoder.yudao.module.remote.config.ip.IpProperties;
|
||||
import cn.iocoder.yudao.module.remote.constant.robot.RobotTaskChcheConstant;
|
||||
import cn.iocoder.yudao.module.remote.controller.admin.robot.dto.Cockpit;
|
||||
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.controller.admin.robot.dto.RemoteRobotTaskDoneDTO;
|
||||
@ -22,6 +25,7 @@ import cn.iocoder.yudao.module.system.api.remote.dto.RemoteRobotTransferDTO;
|
||||
import cn.iocoder.yudao.module.system.api.robot.dto.FloorZoneDTO;
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@ -42,17 +46,11 @@ public class RemoteRobotServiceImpl implements RemoteRobotService {
|
||||
@Resource
|
||||
private RedisUtil redisUtil;
|
||||
|
||||
@Resource
|
||||
private RequestProcessor processor;
|
||||
|
||||
@Resource
|
||||
private RemoteControllerProcessor remoteControllerProcessor;
|
||||
|
||||
@Value("${remote.controller-port}")
|
||||
private int remoteControllerPort;
|
||||
|
||||
@Value("${remote.controller-ip}")
|
||||
private String remoteControllerIp;
|
||||
@Autowired
|
||||
private IpProperties ipProperties;
|
||||
|
||||
/**
|
||||
* 获取地图区域对应的机器人信息
|
||||
@ -127,15 +125,16 @@ public class RemoteRobotServiceImpl implements RemoteRobotService {
|
||||
@Override
|
||||
public void robotChangeMode(RemoteRobotChangeModeDTO data, HttpServletRequest request) {
|
||||
String ip = IpUtils.getIp(request);
|
||||
CommonResult<RemoteRobotTransferDTO> result = remoteRobotApi.robotChangeMode(data.getRemoteMode(), ip, data.getRobotNo(),remoteControllerPort,remoteControllerIp);
|
||||
Cockpit cockpit = ipProperties.getCockpitByIp(ip);
|
||||
CommonResult<RemoteRobotTransferDTO> result = remoteRobotApi.robotChangeMode(data.getRemoteMode(), ip, data.getRobotNo(),cockpit.getControllerPort(),cockpit.getControllerIp());
|
||||
if (!result.isSuccess()) {
|
||||
throw exception0(TASK_COMMONG_FAIL.getCode(), result.getMsg());
|
||||
}
|
||||
//非自动模式
|
||||
if (0!= data.getRemoteMode()) {
|
||||
remoteControllerProcessor.addCache(result.getData());
|
||||
remoteControllerProcessor.addCache(result.getData(),ip);
|
||||
}else {
|
||||
remoteControllerProcessor.remoteCache(result.getData());
|
||||
remoteControllerProcessor.remoteCache(result.getData(),ip);
|
||||
}
|
||||
}
|
||||
|
||||
@ -162,7 +161,7 @@ public class RemoteRobotServiceImpl implements RemoteRobotService {
|
||||
return;
|
||||
}
|
||||
|
||||
remoteControllerProcessor.remoteCache(result.getData());
|
||||
remoteControllerProcessor.remoteCache(result.getData(),ip);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -203,8 +202,23 @@ public class RemoteRobotServiceImpl implements RemoteRobotService {
|
||||
RobotDistanceInformationDTO build =
|
||||
RobotDistanceInformationDTO.builder().linearSpeed(floorZone.getLinearSpeed()).robotNo(data.getRobotNo())
|
||||
.endDistance(data.getEndDistance()).nextRadian(data.getNextRadian()).message(msg).build();
|
||||
processor.handleRequest(floorZone.getFloor() + "_" + floorZone.getArea(),
|
||||
mac, JSONUtil.toJsonStr(build));
|
||||
/*processor.handleRequest(floorZone.getFloor() + "_" + floorZone.getArea(),
|
||||
mac, JSONUtil.toJsonStr(build));*/
|
||||
}
|
||||
|
||||
/**
|
||||
* 上报车辆信息信息
|
||||
* @param data
|
||||
*/
|
||||
@Override
|
||||
public void sendRobotWirelessSignalStatus(RemoteRobotWirelessSignalDTO data) {
|
||||
TenantContextHolder.setTenantId(1L);
|
||||
String robotNo = (String) redisUtil.get(RobotTaskChcheConstant.ROBOT_GET_ROBOTNO_BY_MAC + data.getMac());
|
||||
if (ObjectUtil.isEmpty(robotNo)) {
|
||||
robotNo = remoteRobotApi.getRobotNoByMac(data.getMac());
|
||||
}
|
||||
log.info("车辆编号 :{}",robotNo);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1,14 +1,20 @@
|
||||
package cn.iocoder.yudao.module.remote.service.speed;
|
||||
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import cn.iocoder.yudao.module.system.api.remote.RemoteRobotMaxSpeedApi;
|
||||
import cn.iocoder.yudao.module.system.api.remote.dto.RemoteRobotMaxSpeedDTO;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
|
||||
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception0;
|
||||
import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.*;
|
||||
|
||||
@Slf4j
|
||||
@Service
|
||||
public class RemoteRobotMaxSpeedServiceImpl implements RemoteRobotMaxSpeedService{
|
||||
@ -16,6 +22,9 @@ public class RemoteRobotMaxSpeedServiceImpl implements RemoteRobotMaxSpeedServic
|
||||
@Resource
|
||||
private RemoteRobotMaxSpeedApi remoteRobotMaxSpeedApi;
|
||||
|
||||
@Value("${remote.robot-max-speed:5}")
|
||||
private int robotMaxSpeed;
|
||||
|
||||
@Override
|
||||
public List<RemoteRobotMaxSpeedDTO> getRobotMaxSpeedPage() {
|
||||
return remoteRobotMaxSpeedApi.getRobotMaxSpeedPage();
|
||||
@ -23,6 +32,15 @@ public class RemoteRobotMaxSpeedServiceImpl implements RemoteRobotMaxSpeedServic
|
||||
|
||||
@Override
|
||||
public void updateRobotMaxSpeedPage(List<RemoteRobotMaxSpeedDTO> list) {
|
||||
for (RemoteRobotMaxSpeedDTO remoteRobotMaxSpeedDTO : list) {
|
||||
int speed = ObjectUtil.isEmpty(remoteRobotMaxSpeedDTO.getMaxSpeed()) ? 0 : Integer.parseInt(remoteRobotMaxSpeedDTO.getMaxSpeed());
|
||||
if (speed <= 0) {
|
||||
throw exception(REMOTE_ROBOT_SPEED_EMPTY);
|
||||
}else if (speed > robotMaxSpeed) {
|
||||
String str = REMOTE_ROBOT_MAX_SPEED_LIMIT.getMsg() + " 最大限速为 " +robotMaxSpeed +" m/s";
|
||||
throw exception0(REMOTE_ROBOT_MAX_SPEED_LIMIT.getCode(),str);
|
||||
}
|
||||
}
|
||||
remoteRobotMaxSpeedApi.updateRobotMaxSpeedPage(list);
|
||||
}
|
||||
|
||||
|
@ -53,9 +53,15 @@ logging:
|
||||
name: ${user.home}/logs/${spring.application.name}.log # 日志文件名,全路径
|
||||
|
||||
remote:
|
||||
controller-port: 9000
|
||||
controller-ip: 127.0.0.1
|
||||
cockpit: # 远遥控制车辆IP和端口
|
||||
- controllerPort: 9002
|
||||
controllerIp: 127.0.0.2
|
||||
ipcIp: 127.0.0.1
|
||||
- controllerPort: 9001
|
||||
controllerIp: 127.0.0.3
|
||||
ipcIp: 127.0.0.1
|
||||
msg: AA 55 13 04 01 88 88 # 驾舱socket头信息
|
||||
cockpit-time-out: 120 # 驾舱超时报警时间
|
||||
industrial-control-time-out: 120 # 工控通信超时报警时间
|
||||
robot-communication-time-out: 120 # 车辆通信超时报警时间
|
||||
robot-communication-time-out: 120 # 车辆通信超时报警时间
|
||||
robot-max-speed: 5 # 远遥控制车辆最大速度 m/s
|
@ -53,10 +53,16 @@ logging:
|
||||
name: C:\system\install\log/${spring.application.name}.log
|
||||
|
||||
remote:
|
||||
controller-port: 9000
|
||||
controller-ip: 127.0.0.1
|
||||
cockpit: # 远遥控制车辆IP和端口
|
||||
- controllerPort: 9002
|
||||
controllerIp: 127.0.0.2
|
||||
ipcIp: 127.0.0.1
|
||||
- controllerPort: 9001
|
||||
controllerIp: 127.0.0.3
|
||||
ipcIp: 127.0.0.1
|
||||
msg: AA 55 13 04 01 88 88 # 驾舱socket头信息
|
||||
cockpit-time-out: 120 # 驾舱超时报警时间
|
||||
industrial-control-time-out: 120 # 工控通信超时报警时间
|
||||
robot-communication-time-out: 120 # 车辆通信超时报警时间
|
||||
robot-max-speed: 5 # 远遥控制车辆最大速度 m/s
|
||||
|
||||
|
@ -34,9 +34,15 @@ logging:
|
||||
name: D:/project/rcs/logs/${spring.application.name}.log
|
||||
|
||||
remote:
|
||||
controller-port: 9000
|
||||
controller-ip: 10.10.110.17
|
||||
cockpit: # 远遥控制车辆IP和端口
|
||||
- controllerPort: 9002
|
||||
controllerIp: 127.0.0.2
|
||||
ipcIp: 127.0.0.1
|
||||
- controllerPort: 9001
|
||||
controllerIp: 127.0.0.3
|
||||
ipcIp: 127.0.0.1
|
||||
msg: AA 55 13 04 01 88 88 # 驾舱socket头信息
|
||||
cockpit-time-out: 120 # 驾舱超时报警时间
|
||||
industrial-control-time-out: 120 # 工控通信超时报警时间
|
||||
robot-communication-time-out: 120 # 车辆通信超时报警时间
|
||||
robot-communication-time-out: 120 # 车辆通信超时报警时间
|
||||
robot-max-speed: 5 # 远遥控制车辆最大速度 m/s
|
@ -62,4 +62,8 @@ public interface RemoteRobotApi {
|
||||
@PostMapping(PREFIX + "/getMacByRobotNo")
|
||||
@Operation(summary = "根据车辆编号获取MAC地址")
|
||||
String getMacByRobotNo( @RequestParam(value = "robotNo") String robotNo);
|
||||
|
||||
@PostMapping(PREFIX + "/getRobotNoByMac")
|
||||
@Operation(summary = "根据车辆MAC地址获取车辆编号")
|
||||
String getRobotNoByMac( @RequestParam(value = "mac") String mac);
|
||||
}
|
||||
|
@ -18,7 +18,7 @@ public class RemoteRobotStatusDTO {
|
||||
private Integer remoteMode = 0;
|
||||
|
||||
@Schema(description = "协控(0:关闭协控, 1:开启协控, 2:不显示协控)")
|
||||
private Integer collaborativeControl = 0;
|
||||
private Integer collaborativeControl = 2;
|
||||
|
||||
@Schema(description = "车辆任务状态(3:待命 , 其他都是任务中)")
|
||||
private Integer robotStatus = 2;
|
||||
|
@ -14,4 +14,29 @@ public class RobotObstaclesStatusDTO {
|
||||
* true表示有障碍物,false表示没有障碍物
|
||||
*/
|
||||
public Boolean obstacles;
|
||||
|
||||
/**
|
||||
* 左前方障碍物距离 float,单位是米
|
||||
*/
|
||||
private String frontLeft;
|
||||
|
||||
/**
|
||||
* 右前方障碍物距离 float,单位是米
|
||||
*/
|
||||
private String frontRight;
|
||||
|
||||
/**
|
||||
* 左后方障碍物距离 float,单位是米
|
||||
*/
|
||||
private String reaLeft;
|
||||
|
||||
/**
|
||||
* 右后方障碍物距离 float,单位是米
|
||||
*/
|
||||
private String reaRight;
|
||||
|
||||
/**
|
||||
* 正后方障碍物距离 float,单位是米
|
||||
*/
|
||||
private String rearCenter;
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
package cn.iocoder.yudao.module.system.api.robot.dto;
|
||||
|
||||
import cn.iocoder.yudao.module.system.api.robot.websocket.RobotStatusDataPoseDTO;
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
|
@ -1,5 +1,6 @@
|
||||
package cn.iocoder.yudao.module.system.api.robot.dto;
|
||||
|
||||
import cn.iocoder.yudao.module.system.api.robot.websocket.RobotStatusDataPoseDTO;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
@ -11,8 +11,5 @@ public class RobotStatusDataErrorDTO {
|
||||
* 错误码
|
||||
*/
|
||||
public String errorCode;
|
||||
/**
|
||||
* 错误等级
|
||||
*/
|
||||
public String codeLevel;
|
||||
|
||||
}
|
||||
|
@ -1,6 +1,5 @@
|
||||
package cn.iocoder.yudao.module.system.api.robot.vo;
|
||||
package cn.iocoder.yudao.module.system.api.robot.websocket;
|
||||
|
||||
import cn.iocoder.yudao.module.system.api.robot.dto.RobotStatusDataPoseDTO;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
@ -31,4 +30,9 @@ public class RobotInformationVO {
|
||||
* 车辆即将走的点位
|
||||
*/
|
||||
private List<String> data;
|
||||
|
||||
/**
|
||||
* 车辆身上的物料信息和数量
|
||||
*/
|
||||
private Object skuInfo;
|
||||
}
|
@ -0,0 +1,27 @@
|
||||
package cn.iocoder.yudao.module.system.api.robot.websocket;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class RobotSkuInfoDTO {
|
||||
|
||||
/**
|
||||
* 1:有物料, 0:没有物料
|
||||
*/
|
||||
private Integer haveSku = 1;
|
||||
|
||||
/**
|
||||
* 物料信息
|
||||
*/
|
||||
private String skuInfo;
|
||||
|
||||
/**
|
||||
* 物料数量
|
||||
*/
|
||||
private Long skuNumber;
|
||||
|
||||
/**
|
||||
* 层数
|
||||
*/
|
||||
private Integer locationStorey;
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
package cn.iocoder.yudao.module.system.api.robot.dto;
|
||||
package cn.iocoder.yudao.module.system.api.robot.websocket;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
@ -16,6 +16,8 @@ public class RobotStatusDataPoseDTO {
|
||||
public String floor;
|
||||
//区域
|
||||
public String area;
|
||||
//电池剩余容量
|
||||
public String batSoc;
|
||||
//货叉高度
|
||||
public Double forkHeight;
|
||||
//电池剩余容量 废弃 从ROBOT_INFORMATION_SOC 获取电量
|
||||
// public String batSoc;
|
||||
}
|
@ -0,0 +1,23 @@
|
||||
package cn.iocoder.yudao.module.system.api.robot.websocket;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class WsWareHouseLocationDTO {
|
||||
|
||||
@Schema(description = "实际坐标x轴")
|
||||
private String actualLocationX;
|
||||
|
||||
@Schema(description = "实际坐标y轴")
|
||||
private String actualLocationY;
|
||||
|
||||
@Schema(description = "类型: 1:添加, 0:减少")
|
||||
private Integer type = 1;
|
||||
|
||||
@Schema(description = "所在楼")
|
||||
public String floor;
|
||||
|
||||
@Schema(description = "所在区")
|
||||
public String area;
|
||||
}
|
@ -224,26 +224,29 @@ public interface ErrorCodeConstants {
|
||||
ErrorCode TASK_CREATE_FAIL = new ErrorCode(1-002-035-110, "任务创建失败:");
|
||||
ErrorCode ROBOT_DO_TASK_FAIL = new ErrorCode(1-002-035-112, "车机反馈不能接任务");
|
||||
ErrorCode TASK_COMMONG_FAIL = new ErrorCode(1-002-035-113, "下发失败");
|
||||
ErrorCode TASK_ASSIGN_OTHER_ROBOT = new ErrorCode(1-002-035-114, "此任务已经转移给其他车辆");
|
||||
|
||||
// ========== 机器人任务明细 1-002-036-000 ==========
|
||||
ErrorCode TASK_DETAIL_NOT_EXISTS = new ErrorCode(1-002-036-001, "车辆任务明细不存在");
|
||||
ErrorCode TASK_DETAIL_CHANGE_ROBOT = new ErrorCode(1-002-036-002, "非新单据不能修改车辆");
|
||||
ErrorCode TASK_NOT_TAKE_RELEASE = new ErrorCode(1-002-036-003, "非取货任务,不能点击取货完成");
|
||||
ErrorCode TASK_NOT_TAKE_RELEASE = new ErrorCode(1-002-036-003, "已经取完货,不能点击取货完成,只能点击任务完成");
|
||||
|
||||
// ========== 机器人任务明细 1-002-037-000 ==========
|
||||
ErrorCode REDISSON_NOT_OBTAIN_LOCK = new ErrorCode(1-002-037-001, "有正在下发中的任务请稍后重试!");
|
||||
ErrorCode PATH_PLANNING_DOING_DISTRIBUTE = new ErrorCode(1-002-037-002, "有正在分配的PP任务!");
|
||||
|
||||
// ========== 地图信息 1-002-038-000 ==========
|
||||
ErrorCode AGV_UPLOAD_INFORMATION_DOES_NOT_INCLUDE_FLOOR_OR_AREA_INFORMATION = new ErrorCode(1_002_038_001, "AGV上传信息未包含楼层或区域信息");
|
||||
ErrorCode AGV_FILE_UPLOAD_CONTENT_IS_EMPTY = new ErrorCode(1_002_038_002, "AGV文件上传内容为空");
|
||||
ErrorCode AGV_UPLOAD_INFORMATION_DOES_NOT_INCLUDE_FLOOR_OR_AREA_INFORMATION = new ErrorCode(1_002_038_001, "车辆上传信息未包含楼层或区域信息");
|
||||
ErrorCode AGV_FILE_UPLOAD_CONTENT_IS_EMPTY = new ErrorCode(1_002_038_002, "车辆文件上传内容为空");
|
||||
ErrorCode PLEASE_UPLOAD_PNG_AND_YAML_FILES = new ErrorCode(1_002_038_003, "请上传png和yaml两个文件并且文件内容不为空");
|
||||
ErrorCode AGV_MAP_NOT_FOUND = new ErrorCode(1_002_038_004, "找不到AGV地图信息");
|
||||
ErrorCode AGV_IMAGE_CONVERSION_TO_BASE64_FAILED = new ErrorCode(1_002_038_005, "AGV图片转base64失败");
|
||||
ErrorCode AGV_MAP_NOT_FOUND = new ErrorCode(1_002_038_004, "找不到车辆地图信息");
|
||||
ErrorCode AGV_IMAGE_CONVERSION_TO_BASE64_FAILED = new ErrorCode(1_002_038_005, "车辆图片转base64失败");
|
||||
ErrorCode THE_LINE_LIBRARY_POINTS_ARE_NOT_LOCATED_IN_THE_SAME_AREA = new ErrorCode(1_002_038_006, "线库点位不在同一区域内");
|
||||
ErrorCode THERE_ARE_ALREADY_STORAGE_LOCATIONS_IN_OTHER_LINE_WAREHOUSES = new ErrorCode(1_002_038_007, "已有库位在其他线库内");
|
||||
ErrorCode THERE_ARE_ALREADY_STORAGE_LOCATIONS_IN_OTHER_STORAGE_AREAS = new ErrorCode(1_002_038_008, "已有库位在其它区域内");
|
||||
ErrorCode MAP_DOES_NOT_EXIST_AGV = new ErrorCode(1_002_038_009, "此楼层区域不存在车辆需要暂停或恢复");
|
||||
ErrorCode MAP_EXIST_TASK_EXIST_TASK = new ErrorCode(1_002_038_010, "修改地图:此楼层区域存在处理中的任务或者库位上还有货物");
|
||||
ErrorCode MAP_EXIST_BINDING_POINT = new ErrorCode(1_002_038_011, "修改地图:此楼层区域的地图交换点尚未解绑");
|
||||
|
||||
// ========== 机器人自动移库 1-002-039-000 ==========
|
||||
ErrorCode TASK_AUTO_MOVE_NOT_EXISTS = new ErrorCode(1_002_039_001, "车辆自动移库不存在");
|
||||
@ -292,7 +295,6 @@ public interface ErrorCodeConstants {
|
||||
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, "自由模式只能切换到自动模式");
|
||||
ErrorCode REMOTE_NOT_HAVE_BINDING_ROBOT = new ErrorCode(1_002_053_010, "远遥设备未选择车辆");
|
||||
ErrorCode REMOTE_TASK_HAVE_CHOOSE = new ErrorCode(1_002_053_011, "此任务已经被远遥设备选中");
|
||||
ErrorCode REMOTE_TASK_NOT_OCCUR_ERROR = new ErrorCode(1_002_053_012, "此任务未发发生4级异常");
|
||||
ErrorCode REMOTE_TASK_NOT_TAKE_RELEASE = new ErrorCode(1_002_053_013, "非取货或者放货任务,不能转移");
|
||||
@ -300,6 +302,12 @@ public interface ErrorCodeConstants {
|
||||
ErrorCode REMOTE_ROBOT_HAVE_MORE_TASK = new ErrorCode(1_002_053_015, "此车辆有一个以上的处理中任务,请先检查数据");
|
||||
ErrorCode REMOTE_ROBOT_HAVE_NOT_TASK = new ErrorCode(1_002_053_016, "此车辆没有处理中的任务");
|
||||
ErrorCode REMOTE_ROBOT_CONNECT_FAIL = new ErrorCode(1_002_053_017, "与远遥工控机连接失败");
|
||||
ErrorCode REMOTE_TRANSFER_NOT_SAME_ROBOT = new ErrorCode(1_002_053_018, "任务转移车辆与发生异常的车辆,不能是同一台车");
|
||||
ErrorCode REMOTE_ROBOT_HAVE_TASK = new ErrorCode(1_002_053_019, "此车辆有处理中的任务,不能进行任务转移。请选择其他车辆");
|
||||
ErrorCode REMOTE_ROBOT_SPEED_EMPTY = new ErrorCode(1_002_053_020, "车辆速度必须大于0m/s");
|
||||
ErrorCode REMOTE_ROBOT_MAX_SPEED_LIMIT = new ErrorCode(1_002_053_021, "车辆速度超过最大速度限制");
|
||||
ErrorCode REMOTE_NOT_HAVE_SPEED = new ErrorCode(1_002_053_022, "查询不到车辆速度信息");
|
||||
ErrorCode REMOTE_SPEED_MORE_THAN_ZERO = new ErrorCode(1_002_053_023, "车辆未停稳");
|
||||
|
||||
// ========== 车辆摄像头信息 1_002_054_001 ==========
|
||||
ErrorCode CAMERA_NOT_EXISTS = new ErrorCode(1_002_054_001, "车辆摄像头信息不存在");
|
||||
@ -317,4 +325,7 @@ public interface ErrorCodeConstants {
|
||||
ErrorCode POSITION_CHANGE_POINT_BINDING_NOT_EXISTS = new ErrorCode(1_002_057_001, "区域变更点绑定不存在");
|
||||
ErrorCode POSITION_CHANGE_POINT_SAME_MAP = new ErrorCode(1_002_057_002, "区域变更点绑定,不能是同一张地图");
|
||||
ErrorCode POSITION_CHANGE_POINT_ALREADY_BINDING = new ErrorCode(1_002_057_003, "请勿重复绑定区域变更点");
|
||||
|
||||
// ========== 车辆工作时长统计 1_002_058_001 ==========
|
||||
ErrorCode ROBOT_WORKING_HOURS_STATISTICS_NOT_EXISTS = new ErrorCode(1_002_058_001, "车辆工作时长统计不存在");
|
||||
}
|
||||
|
@ -8,5 +8,6 @@ package cn.iocoder.yudao.module.system.enums.oauth2;
|
||||
public interface OAuth2ClientConstants {
|
||||
|
||||
String CLIENT_ID_DEFAULT = "default";
|
||||
String CLIENT_ID_REMOTE = "remote";
|
||||
|
||||
}
|
||||
|
@ -4,13 +4,18 @@ package cn.iocoder.yudao.module.system.api.path;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder;
|
||||
import cn.iocoder.yudao.module.system.config.ratelimiter.SystemRateLimiter;
|
||||
import cn.iocoder.yudao.module.system.constant.CommonConstant;
|
||||
import cn.iocoder.yudao.module.system.controller.admin.path.dto.GraphMatchDataDTO;
|
||||
import cn.iocoder.yudao.module.system.controller.admin.positionmap.vo.PositionMapSaveReqVO;
|
||||
import cn.iocoder.yudao.module.system.controller.admin.robot.vo.RobotWarnMsgSaveReqVO;
|
||||
import cn.iocoder.yudao.module.system.service.path.PathPlanningService;
|
||||
import cn.iocoder.yudao.module.system.service.positionmap.PositionChangePointBindingService;
|
||||
import cn.iocoder.yudao.module.system.service.robot.RobotTaskService;
|
||||
import cn.iocoder.yudao.module.system.service.robot.RobotWarnMsgService;
|
||||
import cn.iocoder.yudao.module.system.service.tool.ToolsService;
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.slf4j.MDC;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.scheduling.annotation.Async;
|
||||
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
|
||||
@ -18,6 +23,7 @@ import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.UUID;
|
||||
|
||||
@Slf4j
|
||||
@RestController // 提供 RESTful API 接口,给 Feign 调用
|
||||
@ -40,12 +46,11 @@ public class PathApiImpl implements PathApi {
|
||||
private RobotWarnMsgService warnMsgService;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 发送初始化信息给PP
|
||||
*/
|
||||
@Override
|
||||
@SystemRateLimiter(time = 10, count = 1, keyArg = "pathInitData",message = "路径规划初始化数据频繁")
|
||||
@SystemRateLimiter(time = 10, count = 1, keyArg = "pathInitData", message = "路径规划初始化数据频繁")
|
||||
public void pathInitData() {
|
||||
taskExecutor.execute(() -> {
|
||||
TenantContextHolder.setTenantId(1L);
|
||||
@ -69,26 +74,36 @@ public class PathApiImpl implements PathApi {
|
||||
|
||||
/**
|
||||
* PP分配任务
|
||||
*
|
||||
* @param message
|
||||
*/
|
||||
@Override
|
||||
public void ppDistributionTask(String message) {
|
||||
taskExecutor.execute(() -> {
|
||||
TenantContextHolder.setTenantId(1L);
|
||||
taskService.assignTasks(message);
|
||||
// taskService.ppDistributionTask(message); 废弃了
|
||||
String requestId = UUID.randomUUID().toString().replace("-", "");
|
||||
MDC.put(CommonConstant.REQUEST_ID, requestId);
|
||||
try {
|
||||
taskService.assignTasks(message);
|
||||
} finally {
|
||||
MDC.clear();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* PP处理任务失败
|
||||
*
|
||||
* @param message
|
||||
*/
|
||||
@Override
|
||||
public void ppDistributionTaskFail(String message) {
|
||||
TenantContextHolder.setTenantId(1L);
|
||||
warnMsgService.addWarnMsg(message);
|
||||
warnMsgService.sendWarnMsgToWebsocket(message);
|
||||
RobotWarnMsgSaveReqVO data = JSON.parseObject(message, RobotWarnMsgSaveReqVO.class);
|
||||
warnMsgService.createWarnMsg(data);
|
||||
if (ObjectUtil.isNotEmpty(data.getWarnLevel()) && data.getWarnLevel() > 3) {
|
||||
warnMsgService.sendWarnMsgToWebsocket(message);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -102,6 +117,7 @@ public class PathApiImpl implements PathApi {
|
||||
|
||||
/**
|
||||
* 车辆即将走的点位
|
||||
*
|
||||
* @param message
|
||||
*/
|
||||
@Override
|
||||
@ -112,6 +128,7 @@ public class PathApiImpl implements PathApi {
|
||||
|
||||
/**
|
||||
* 仿真点位信息
|
||||
*
|
||||
* @param message
|
||||
*/
|
||||
@Override
|
||||
@ -122,11 +139,13 @@ public class PathApiImpl implements PathApi {
|
||||
|
||||
/**
|
||||
* 路网匹配实时数据
|
||||
*
|
||||
* @param message
|
||||
*/
|
||||
@Override
|
||||
public void graphMatchData(String message) {
|
||||
TenantContextHolder.setTenantId(1L);
|
||||
log.info("匹配路网的消息 :{}",message);
|
||||
pathPlanningService.graphMatchData(message);
|
||||
}
|
||||
|
||||
|
@ -142,5 +142,10 @@ public class RemoteRobotApiImpl implements RemoteRobotApi {
|
||||
return robotInformationService.getMacByRobotNo(robotNo);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRobotNoByMac(String mac) {
|
||||
return robotInformationService.getRobotNoByMac(mac);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -3,15 +3,11 @@ package cn.iocoder.yudao.module.system.api.robot;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import cn.iocoder.yudao.module.system.api.robot.dto.RobotGenericsDataDTO;
|
||||
import cn.iocoder.yudao.module.system.api.robot.dto.RobotStatusDataPoseDTO;
|
||||
import cn.iocoder.yudao.module.system.config.ratelimiter.SystemRateLimiter;
|
||||
import cn.iocoder.yudao.module.system.constant.robot.RobotTaskChcheConstant;
|
||||
import cn.iocoder.yudao.module.system.util.redis.RedisUtil;
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
@ -26,8 +22,6 @@ public class RobotGenericsStatusApiImpl implements RobotGenericsStatusApi {
|
||||
@Resource
|
||||
private RedisUtil redisUtil;
|
||||
|
||||
@Resource@Value("${zn.robot_position_cache_time:10}")
|
||||
private Long robotPositionCacheTime;
|
||||
|
||||
@Override
|
||||
@SystemRateLimiter(time = 1, count = 20, keyArg = "updateRobotCommonStatus",message = "机器人上报车辆其他信息")
|
||||
@ -36,24 +30,27 @@ public class RobotGenericsStatusApiImpl implements RobotGenericsStatusApi {
|
||||
}
|
||||
|
||||
public void doUpdateRobotCommonStatus(RobotGenericsDataDTO robotStatusData) {
|
||||
log.info("车机每3秒上报其他状态信息 :{}", JSONUtil.toJsonStr(robotStatusData));
|
||||
// log.info("车机每3秒上报其他状态信息 :{}", JSONUtil.toJsonStr(robotStatusData));
|
||||
if (ObjectUtil.isEmpty(robotStatusData) || ObjectUtil.isEmpty(robotStatusData.getHwStates())
|
||||
|| ObjectUtil.isEmpty(robotStatusData.getMac())) {
|
||||
log.info("参数不全 :{}", JSON.toJSONString(robotStatusData));
|
||||
}
|
||||
|
||||
String mac = robotStatusData.getMac();
|
||||
String pose2dKey = RobotTaskChcheConstant.ROBOT_INFORMATION_POSE_BAT_SOC +mac;
|
||||
String socKey = RobotTaskChcheConstant.ROBOT_INFORMATION_SOC +mac;
|
||||
|
||||
Object object = redisUtil.get(pose2dKey);
|
||||
RobotStatusDataPoseDTO robotStatusDataPoseDTO= JSONUtil.toBean((String)object, RobotStatusDataPoseDTO.class);
|
||||
String batSoc = robotStatusData.getHwStates().getBatSoc();
|
||||
if (ObjectUtil.isNotEmpty(batSoc)) {
|
||||
String[] split = batSoc.split("\\.");
|
||||
batSoc = split[1].substring(0,2);
|
||||
robotStatusDataPoseDTO.setBatSoc(batSoc);
|
||||
}
|
||||
batSoc = split[1];
|
||||
if (batSoc.length() > 2) {
|
||||
batSoc = batSoc.substring(0,2);
|
||||
}
|
||||
|
||||
redisUtil.set(pose2dKey,JSON.toJSONString(robotStatusDataPoseDTO),robotPositionCacheTime);
|
||||
if (batSoc.startsWith("0")) {
|
||||
batSoc = batSoc.substring(1);
|
||||
}
|
||||
redisUtil.set(socKey,batSoc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -5,6 +5,7 @@ import cn.iocoder.yudao.module.infra.api.websocket.WebSocketSenderApi;
|
||||
import cn.iocoder.yudao.module.system.api.robot.dto.FloorZoneDTO;
|
||||
import cn.iocoder.yudao.module.system.api.robot.dto.RobotObstaclesStatusDTO;
|
||||
import cn.iocoder.yudao.module.system.api.robot.vo.RobotUpdatePalletHeightDTO;
|
||||
import cn.iocoder.yudao.module.system.constant.CommonConstant;
|
||||
import cn.iocoder.yudao.module.system.constant.robot.RobotTaskChcheConstant;
|
||||
import cn.iocoder.yudao.module.system.constant.webSocket.WebSocketConstant;
|
||||
import cn.iocoder.yudao.module.system.controller.admin.robot.vo.RobotWarnMsgSaveReqVO;
|
||||
@ -51,7 +52,6 @@ public class RobotObstaclesStatusApiImpl implements RobotObstaclesStatusApi{
|
||||
Object floorAreaObject = redisUtil.get(floorAreaKey);
|
||||
FloorZoneDTO floorZoneDTO = JSONUtil.toBean((String) floorAreaObject, FloorZoneDTO.class);
|
||||
|
||||
|
||||
String robotNo = robotInformationService.getRobotNoByMac(data.getMac());
|
||||
|
||||
RobotWarnMsgSaveReqVO warnMsg = new RobotWarnMsgSaveReqVO();
|
||||
@ -61,7 +61,7 @@ public class RobotObstaclesStatusApiImpl implements RobotObstaclesStatusApi{
|
||||
warnMsg.setWarnMsg(robotNo +" 机器人遇到障碍物");
|
||||
warnMsgService.createWarnMsg(warnMsg);
|
||||
|
||||
webSocketSenderApi.sendObject(floorZoneDTO.getFloor() + "_" + floorZoneDTO.getArea(),
|
||||
webSocketSenderApi.sendObject(floorZoneDTO.getFloor() + CommonConstant.SYMBOL + floorZoneDTO.getArea(),
|
||||
WebSocketConstant.AGV_WARN, warnMsg.getWarnMsg());
|
||||
}
|
||||
}
|
||||
|
@ -1,12 +1,12 @@
|
||||
package cn.iocoder.yudao.module.system.api.robot;
|
||||
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder;
|
||||
import cn.iocoder.yudao.module.system.api.robot.dto.FloorZoneDTO;
|
||||
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.RobotReactiveStatusDTO;
|
||||
import cn.iocoder.yudao.module.system.constant.CommonConstant;
|
||||
import cn.iocoder.yudao.module.system.constant.area.FloorAreaConstant;
|
||||
import cn.iocoder.yudao.module.system.constant.robot.RobotTaskChcheConstant;
|
||||
import cn.iocoder.yudao.module.system.dal.dataobject.log.RobotTaskDetailActionLogDO;
|
||||
import cn.iocoder.yudao.module.system.dal.dataobject.robot.RobotWarnCodeMappingDO;
|
||||
@ -15,6 +15,7 @@ import cn.iocoder.yudao.module.system.dal.mysql.robot.RobotWarnCodeMappingMapper
|
||||
import cn.iocoder.yudao.module.system.dal.mysql.robot.RobotWarnMsgMapper;
|
||||
import cn.iocoder.yudao.module.system.enums.robot.RobotWarnType;
|
||||
import cn.iocoder.yudao.module.system.enums.robot.actionlog.ActionStatusEnum;
|
||||
import cn.iocoder.yudao.module.system.enums.robot.actionlog.CommandIdEnum;
|
||||
import cn.iocoder.yudao.module.system.service.log.RobotTaskDetailActionLogService;
|
||||
import cn.iocoder.yudao.module.system.service.robot.RobotInformationService;
|
||||
import cn.iocoder.yudao.module.system.service.robot.RobotTaskDetailService;
|
||||
@ -24,16 +25,12 @@ import com.alibaba.fastjson.JSON;
|
||||
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.data.redis.core.StringRedisTemplate;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.*;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Slf4j
|
||||
@ -65,6 +62,7 @@ public class RobotReactiveStatusApiImpl implements RobotReactiveStatusApi {
|
||||
@Override
|
||||
public void robotReactiveStatus(String message) {
|
||||
TenantContextHolder.setTenantId(1L);
|
||||
// log.info("车辆所在楼层和异常信息 :{}", message);
|
||||
RobotReactiveStatusDTO data = JSON.parseObject(message, RobotReactiveStatusDTO.class);
|
||||
String floorAreaKey = RobotTaskChcheConstant.ROBOT_FLOOR_AREA + data.getMac();
|
||||
String robotNo = robotInformationService.getRobotNoByMac(data.getMac());
|
||||
@ -73,8 +71,14 @@ public class RobotReactiveStatusApiImpl implements RobotReactiveStatusApi {
|
||||
FloorZoneDTO floorZone = new FloorZoneDTO();
|
||||
if (ObjectUtil.isNotEmpty(o)) {
|
||||
floorZone = JSON.parseObject((String) o, FloorZoneDTO.class);
|
||||
String oldFloorArea = floorZone.getFloor()+"-"+floorZone.getArea();
|
||||
redisUtil.hdel(oldFloorArea,robotNo);
|
||||
String oldFloorArea = floorZone.getFloor() + CommonConstant.SYMBOL + floorZone.getArea();
|
||||
redisUtil.hdel(oldFloorArea, robotNo);
|
||||
|
||||
String newFloorArea = data.getFloorZone().getFloor() + CommonConstant.SYMBOL + data.getFloorZone().getArea();
|
||||
String key = FloorAreaConstant.FLOOR_AREA_ROBOT + floorZone.getFloor() + CommonConstant.SYMBOL + floorZone.getArea();
|
||||
if (!oldFloorArea.equals(newFloorArea)) {
|
||||
redisUtil.hdel(key, robotNo);
|
||||
}
|
||||
}
|
||||
|
||||
floorZone.setArea(data.getFloorZone().getArea());
|
||||
@ -83,9 +87,12 @@ public class RobotReactiveStatusApiImpl implements RobotReactiveStatusApi {
|
||||
|
||||
redisUtil.set(floorAreaKey, JSON.toJSONString(floorZone));
|
||||
Map<String, Object> map = new HashMap<>();
|
||||
String value = floorZone.getFloor() + "-" + floorZone.getArea();
|
||||
map.put(robotNo,value);
|
||||
redisUtil.hmset(value,map);
|
||||
String value = floorZone.getFloor() + CommonConstant.SYMBOL + floorZone.getArea();
|
||||
map.put(robotNo, value);
|
||||
redisUtil.hmset(value, map);
|
||||
|
||||
String speedKey = RobotTaskChcheConstant.ROBOT_SPEED_FORK_HEIGHT + robotNo;
|
||||
redisUtil.set(speedKey, message);
|
||||
|
||||
// -- get 老的数据 - 看有没有 - 有的话 - 对比下 - 如果相同 - 更新hashMap中key的value
|
||||
// - 如果不相同的话 - 更新当前redis数据 - 然后 - 根据老的数据 去 hashMapRedis 中删除 这个key的数据
|
||||
@ -110,46 +117,41 @@ public class RobotReactiveStatusApiImpl implements RobotReactiveStatusApi {
|
||||
private void addRobotErrorMsg(RobotReactiveStatusDTO data) {
|
||||
String robotNo = robotInformationService.getRobotNoByMac(data.getMac());
|
||||
List<RobotStatusDataErrorDTO> errCode = data.getErrCode();
|
||||
List<String> warnCodes =
|
||||
errCode.stream().map(RobotStatusDataErrorDTO::getErrorCode).collect(Collectors.toList());
|
||||
Set<String> warnCodes =
|
||||
errCode.stream().map(RobotStatusDataErrorDTO::getErrorCode).collect(Collectors.toSet());
|
||||
List<RobotWarnCodeMappingDO> robotWarnCodeMappingDOS =
|
||||
warnCodeMappingMapper.selectList(new LambdaQueryWrapper<RobotWarnCodeMappingDO>()
|
||||
.in(RobotWarnCodeMappingDO::getWarnCode, warnCodes));
|
||||
if (ObjectUtil.isEmpty(robotWarnCodeMappingDOS)) {
|
||||
log.info("查不对应编号的告警信息 :{}", JSON.toJSONString(warnCodes));
|
||||
log.info("查不对应编号的告警信息 :{}", JSON.toJSONString(data));
|
||||
return;
|
||||
}
|
||||
|
||||
Map<String, List<RobotWarnCodeMappingDO>> warnCodeMapping =
|
||||
robotWarnCodeMappingDOS.stream().collect(Collectors.groupingBy(RobotWarnCodeMappingDO::getWarnCode));
|
||||
Map<String, RobotWarnCodeMappingDO> warnCodeMapping =
|
||||
robotWarnCodeMappingDOS.stream().collect(Collectors.toMap(RobotWarnCodeMappingDO::getWarnCode, Function.identity()));
|
||||
|
||||
List<RobotWarnMsgDO> warnMsgDOS = new ArrayList<>();
|
||||
|
||||
//机器人异常等级
|
||||
String errorLevelKey = RobotTaskChcheConstant.ROBOT_ERROR_LEVEL + data.getMac();
|
||||
Object errorLevel = redisUtil.get(errorLevelKey);
|
||||
|
||||
String errorMsgKey = RobotTaskChcheConstant.ROBOT_ERROR_MSG + data.getMac();
|
||||
Object errorMsg = redisUtil.get(errorMsgKey);
|
||||
|
||||
Integer level = ObjectUtil.isEmpty(errorLevel) ? 0 : Integer.valueOf(errorLevel.toString());
|
||||
|
||||
RobotTaskDetailActionLogDO lastTaskByRobotNo = taskDetailActionLogService.getLastTaskByRobotNo(robotNo);
|
||||
RobotTaskDetailActionLogDO lastTaskByRobotNo = taskDetailActionLogService.getLastTaskByRobotNo(robotNo, CommandIdEnum.TASK.getType());
|
||||
|
||||
int level = 0;
|
||||
String msg = "";
|
||||
int i = 0;
|
||||
for (RobotStatusDataErrorDTO robotStatusData : errCode) {
|
||||
List<RobotWarnCodeMappingDO> mappingDOS = warnCodeMapping.get(robotStatusData.getErrorCode());
|
||||
RobotWarnCodeMappingDO mappingDOS = warnCodeMapping.get(robotStatusData.getErrorCode());
|
||||
if (ObjectUtil.isEmpty(mappingDOS)) {
|
||||
log.info("当前告警类型查不到对应的告警信息 :{}", robotStatusData.getErrorCode());
|
||||
continue;
|
||||
}
|
||||
RobotWarnMsgDO warnMsg = RobotWarnMsgDO.builder().warnLevel(Integer.valueOf(robotStatusData.getCodeLevel()))
|
||||
RobotWarnMsgDO warnMsg = RobotWarnMsgDO.builder().warnLevel(mappingDOS.getWarnLevel())
|
||||
.warnCode(robotStatusData.getErrorCode())
|
||||
.robotNo(robotNo)
|
||||
.warnType(RobotWarnType.ROBOT_WARN.getType())
|
||||
.warnMsg(robotNo + "_" + mappingDOS.get(0).getWarnMsg())
|
||||
.warnSolve(mappingDOS.get(0).getWarnSolve())
|
||||
.warnMsg(robotNo + CommonConstant.SYMBOL + mappingDOS.getWarnMsg())
|
||||
.warnSolve(mappingDOS.getWarnSolve())
|
||||
.build();
|
||||
|
||||
if (ObjectUtil.isNotEmpty(lastTaskByRobotNo) && ActionStatusEnum.DOING.getType().equals(lastTaskByRobotNo.getActionStatus())) {
|
||||
@ -159,20 +161,16 @@ public class RobotReactiveStatusApiImpl implements RobotReactiveStatusApi {
|
||||
|
||||
warnMsgDOS.add(warnMsg);
|
||||
|
||||
if (level.intValue() < Integer.valueOf(robotStatusData.getCodeLevel()).intValue()) {
|
||||
level = Integer.valueOf(robotStatusData.getCodeLevel());
|
||||
errorMsg = warnMsg.getWarnMsg();
|
||||
}
|
||||
if (i < Integer.valueOf(robotStatusData.getCodeLevel()).intValue()) {
|
||||
i = Integer.valueOf(robotStatusData.getCodeLevel());
|
||||
if (level < mappingDOS.getWarnLevel()) {
|
||||
level = mappingDOS.getWarnLevel();
|
||||
msg = warnMsg.getWarnMsg();
|
||||
}
|
||||
}
|
||||
redisUtil.set(errorLevelKey, level);
|
||||
redisUtil.set(errorMsgKey, errorMsg);
|
||||
redisUtil.set(errorMsgKey, msg);
|
||||
|
||||
if (ObjectUtil.isNotEmpty(lastTaskByRobotNo) && ActionStatusEnum.DOING.getType().equals(lastTaskByRobotNo.getActionStatus())
|
||||
&& 4 == i && ObjectUtil.isNotEmpty(lastTaskByRobotNo.getTaskDetailId())) {
|
||||
&& 4 == level && ObjectUtil.isNotEmpty(lastTaskByRobotNo.getTaskDetailId())) {
|
||||
taskDetailService.setTaskDetailError(lastTaskByRobotNo.getTaskDetailId());
|
||||
}
|
||||
|
||||
|
@ -3,35 +3,32 @@ package cn.iocoder.yudao.module.system.api.robot;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder;
|
||||
import cn.iocoder.yudao.module.mqtt.api.path.PathPlanningApi;
|
||||
import cn.iocoder.yudao.module.mqtt.api.common.CommonApi;
|
||||
import cn.iocoder.yudao.module.system.api.robot.dto.*;
|
||||
import cn.iocoder.yudao.module.system.api.robot.vo.RobotInformationVO;
|
||||
import cn.iocoder.yudao.module.system.api.robot.processor.RequestProcessor;
|
||||
import cn.iocoder.yudao.module.system.api.robot.websocket.RobotInformationVO;
|
||||
import cn.iocoder.yudao.module.system.api.robot.vo.RobotReactiveStatusDTO;
|
||||
import cn.iocoder.yudao.module.system.api.robot.websocket.RobotStatusDataPoseDTO;
|
||||
import cn.iocoder.yudao.module.system.config.ratelimiter.SystemRateLimiter;
|
||||
import cn.iocoder.yudao.module.system.constant.CommonConstant;
|
||||
import cn.iocoder.yudao.module.system.constant.area.FloorAreaConstant;
|
||||
import cn.iocoder.yudao.module.system.constant.path.PathPlanningTopicConstant;
|
||||
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;
|
||||
import cn.iocoder.yudao.module.system.dal.mysql.robot.RobotWarnCodeMappingMapper;
|
||||
import cn.iocoder.yudao.module.system.dal.mysql.robot.RobotWarnMsgMapper;
|
||||
import cn.iocoder.yudao.module.system.enums.robot.RobotWarnType;
|
||||
import cn.iocoder.yudao.module.system.service.robot.RobotInformationService;
|
||||
import cn.iocoder.yudao.module.system.service.robot.RobotWarnMsgService;
|
||||
import cn.iocoder.yudao.module.system.util.redis.RedisUtil;
|
||||
import com.alibaba.fastjson.JSON;
|
||||
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.data.redis.core.StringRedisTemplate;
|
||||
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
@Slf4j
|
||||
@RestController // 提供 RESTful API 接口,给 Feign 调用
|
||||
@ -50,11 +47,10 @@ public class RobotStatusApiImpl implements RobotStatusApi {
|
||||
@Resource
|
||||
private RequestProcessor processor;
|
||||
|
||||
@Resource
|
||||
private PathPlanningApi pathPlanningApi;
|
||||
private static final ExecutorService executorService = Executors.newFixedThreadPool(5);
|
||||
|
||||
@Autowired
|
||||
private ThreadPoolTaskExecutor taskExecutor;
|
||||
@Resource
|
||||
private CommonApi commonApi;
|
||||
|
||||
/**
|
||||
* 更新机器人点位/异常/能否做任务
|
||||
@ -63,13 +59,16 @@ public class RobotStatusApiImpl implements RobotStatusApi {
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
@SystemRateLimiter(time = 1, count = 150, keyArg = "robotStatusUpdate",message = "机器人上报点位超过限流")
|
||||
@SystemRateLimiter(time = 1, count = 150, keyArg = "robotStatusUpdate", message = "机器人上报点位超过限流")
|
||||
public void robotStatusUpdate(RobotPoseStatusDTO robotStatusDataDTO) {
|
||||
updateRobotPosed(robotStatusDataDTO);
|
||||
executorService.execute(() -> {
|
||||
updateRobotPosed(robotStatusDataDTO);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新点位信息
|
||||
*
|
||||
* @param robotStatusDataDTO
|
||||
*/
|
||||
private void updateRobotPosed(RobotPoseStatusDTO robotStatusDataDTO) {
|
||||
@ -82,18 +81,32 @@ public class RobotStatusApiImpl implements RobotStatusApi {
|
||||
Object floorAreaObject = redisUtil.get(floorAreaKey);
|
||||
FloorZoneDTO floorZoneDTO = JSONUtil.toBean((String) floorAreaObject, FloorZoneDTO.class);
|
||||
String robotNo = robotInformationService.getRobotNoByMac(robotStatusDataDTO.getMac());
|
||||
String pose2dKey = RobotTaskChcheConstant.ROBOT_INFORMATION_POSE_BAT_SOC + robotStatusDataDTO.getMac();
|
||||
String pose2dKey = RobotTaskChcheConstant.ROBOT_INFORMATION_POSE_BAT + robotStatusDataDTO.getMac();
|
||||
Object object = redisUtil.get(pose2dKey);
|
||||
RobotStatusDataPoseDTO robotStatusDataPoseDTO = JSONUtil.toBean((String) object, RobotStatusDataPoseDTO.class);
|
||||
|
||||
if (ObjectUtil.isNotEmpty(robotStatusDataDTO.getPose2d())) {
|
||||
robotStatusDataPoseDTO.setX(robotStatusDataDTO.getPose2d().getX());
|
||||
robotStatusDataPoseDTO.setY(robotStatusDataDTO.getPose2d().getY());
|
||||
robotStatusDataPoseDTO.setYaw(robotStatusDataDTO.getPose2d().getYaw());
|
||||
if (robotStatusDataDTO.getPose2d().getYaw().length()>7) {
|
||||
String yaw = robotStatusDataDTO.getPose2d().getYaw().substring(0, 7);
|
||||
robotStatusDataPoseDTO.setYaw(yaw);
|
||||
}else {
|
||||
robotStatusDataPoseDTO.setYaw(robotStatusDataDTO.getPose2d().getYaw());
|
||||
}
|
||||
|
||||
}
|
||||
robotStatusDataPoseDTO.setRobotNo(robotNo);
|
||||
robotStatusDataPoseDTO.setFloor(floorZoneDTO.getFloor());
|
||||
robotStatusDataPoseDTO.setArea(floorZoneDTO.getArea());
|
||||
|
||||
String speedKey = RobotTaskChcheConstant.ROBOT_SPEED_FORK_HEIGHT + robotNo;
|
||||
Object speedObject = redisUtil.get(speedKey);
|
||||
if (ObjectUtil.isNotEmpty(speedObject)) {
|
||||
RobotReactiveStatusDTO data = JSON.parseObject(speedObject.toString(), RobotReactiveStatusDTO.class);
|
||||
robotStatusDataPoseDTO.setForkHeight(data.getForkHeight());
|
||||
}
|
||||
|
||||
redisUtil.set(pose2dKey, JSON.toJSONString(robotStatusDataPoseDTO), robotPositionCacheTime);
|
||||
|
||||
//机器人身上是否有货
|
||||
@ -110,15 +123,18 @@ public class RobotStatusApiImpl implements RobotStatusApi {
|
||||
}
|
||||
robotInformationVO.setPose2d(robotStatusDataPoseDTO);
|
||||
|
||||
Map<String, Object> map = new HashMap<>();
|
||||
String value = FloorAreaConstant.FLOOR_AREA_ROBOT + floorZoneDTO.getFloor() + CommonConstant.SYMBOL + floorZoneDTO.getArea();
|
||||
map.put(robotStatusDataDTO.getMac(), JSON.toJSONString(robotInformationVO));
|
||||
redisUtil.hmset(value, map, 20);
|
||||
|
||||
// 合并请求 - 这里接受到的数据都丢给 RequestProcessor - 再整合数据通过WebSocket丢给前端
|
||||
processor.handleRequest(floorZoneDTO.getFloor() + "_" + floorZoneDTO.getArea(),
|
||||
processor.handleRequest(floorZoneDTO.getFloor() + CommonConstant.SYMBOL + floorZoneDTO.getArea(),
|
||||
robotStatusDataDTO.getMac(), JSONUtil.toJsonStr(robotInformationVO));
|
||||
sendToPP(robotStatusDataPoseDTO);
|
||||
}
|
||||
|
||||
private void sendToPP(RobotStatusDataPoseDTO robotStatusDataPoseDTO) {
|
||||
taskExecutor.execute(()->{
|
||||
pathPlanningApi.synchronousLineObject(robotStatusDataPoseDTO, PathPlanningTopicConstant.AGV_POSE);
|
||||
});
|
||||
commonApi.commonMethod(robotStatusDataPoseDTO, PathPlanningTopicConstant.AGV_POSE);
|
||||
}
|
||||
}
|
||||
|
@ -1,16 +1,26 @@
|
||||
package cn.iocoder.yudao.module.system.api.robot;
|
||||
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import cn.iocoder.yudao.framework.common.util.date.DateUtils;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
|
||||
import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder;
|
||||
import cn.iocoder.yudao.module.infra.api.websocket.WebSocketSenderApi;
|
||||
import cn.iocoder.yudao.module.mqtt.api.common.CommonApi;
|
||||
import cn.iocoder.yudao.module.system.api.path.vo.RobotClosePathPlantingDTO;
|
||||
import cn.iocoder.yudao.module.system.api.robot.dto.FloorZoneDTO;
|
||||
import cn.iocoder.yudao.module.system.api.robot.dto.RobotCommandStateDTO;
|
||||
import cn.iocoder.yudao.module.system.api.robot.dto.RobotCompleteTaskDTO;
|
||||
import cn.iocoder.yudao.module.system.api.robot.websocket.RobotSkuInfoDTO;
|
||||
import cn.iocoder.yudao.module.system.api.robot.websocket.WsWareHouseLocationDTO;
|
||||
import cn.iocoder.yudao.module.system.constant.CommonConstant;
|
||||
import cn.iocoder.yudao.module.system.constant.area.FloorAreaConstant;
|
||||
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.RobotExecutionStateConstant;
|
||||
import cn.iocoder.yudao.module.system.constant.robot.RobotTaskChcheConstant;
|
||||
import cn.iocoder.yudao.module.system.constant.webSocket.WebSocketConstant;
|
||||
import cn.iocoder.yudao.module.system.controller.admin.log.vo.RobotTaskDetailActionLogSaveReqVO;
|
||||
import cn.iocoder.yudao.module.system.dal.dataobject.log.RobotTaskDetailActionLogDO;
|
||||
import cn.iocoder.yudao.module.system.dal.dataobject.houselocation.WareHouseLocationDO;
|
||||
import cn.iocoder.yudao.module.system.dal.dataobject.robot.*;
|
||||
@ -26,14 +36,12 @@ import cn.iocoder.yudao.module.system.enums.robot.actionlog.ActionStatusEnum;
|
||||
import cn.iocoder.yudao.module.system.enums.robot.charge.ChargeTaskStatusEnum;
|
||||
import cn.iocoder.yudao.module.system.enums.robot.task.RobotStatusCodeEnum;
|
||||
import cn.iocoder.yudao.module.system.enums.robot.task.RobotTaskStageEnum;
|
||||
import cn.iocoder.yudao.module.system.enums.wait.WaitStatusEnum;
|
||||
import cn.iocoder.yudao.module.system.service.information.DeviceInformationService;
|
||||
import cn.iocoder.yudao.module.system.service.log.RobotTaskDetailActionLogService;
|
||||
import cn.iocoder.yudao.module.system.service.path.PathPlanningService;
|
||||
import cn.iocoder.yudao.module.system.service.robot.RobotInformationService;
|
||||
import cn.iocoder.yudao.module.system.service.robot.RobotTaskDetailService;
|
||||
import cn.iocoder.yudao.module.system.service.robot.RobotWarnMsgService;
|
||||
import cn.iocoder.yudao.module.system.service.wait.MoveToWaitService;
|
||||
import cn.iocoder.yudao.module.system.util.redis.RedisUtil;
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
@ -50,6 +58,8 @@ import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
import static cn.iocoder.yudao.module.system.service.robot.RobotInformationServiceImpl.key;
|
||||
|
||||
@Slf4j
|
||||
@RestController // 提供 RESTful API 接口,给 Feign 调用
|
||||
@Validated
|
||||
@ -92,6 +102,9 @@ public class RobotTaskStatusApiImpl implements RobotTaskStatusApi {
|
||||
@Resource
|
||||
private CommonApi commonApi;
|
||||
|
||||
@Resource
|
||||
public WebSocketSenderApi webSocketSenderApi;
|
||||
|
||||
@Resource
|
||||
private RobotTaskDetailService taskDetailService;
|
||||
|
||||
@ -101,9 +114,6 @@ public class RobotTaskStatusApiImpl implements RobotTaskStatusApi {
|
||||
@Resource
|
||||
private RobotWarnMsgService warnMsgService;
|
||||
|
||||
@Resource
|
||||
private MoveToWaitService moveToWaitService;
|
||||
|
||||
@Resource
|
||||
private PathPlanningService pathPlanningService;
|
||||
|
||||
@ -113,6 +123,9 @@ public class RobotTaskStatusApiImpl implements RobotTaskStatusApi {
|
||||
@Value("${zn.robot_doing_action.doing_action_cache_time:2*24*60*60}")
|
||||
private Long doingActionCacheTime;
|
||||
|
||||
@Value("${zn.is_simulation:false}")
|
||||
private Boolean isSimulation;
|
||||
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void doRobotDoneTask(RobotCompleteTaskDTO robotCompleteTaskDTO) {
|
||||
log.info("机器人完成任务上报 :{}", JSON.toJSONString(robotCompleteTaskDTO));
|
||||
@ -138,6 +151,10 @@ public class RobotTaskStatusApiImpl implements RobotTaskStatusApi {
|
||||
} else if (RobotExecutionStateConstant.DONE.equals(robotCompleteTaskDTO.getExecutionState())) {
|
||||
robotTaskDone(robotCompleteTaskDTO);
|
||||
redisUtil.del(robotDoingActionKey);
|
||||
String robotNo = robotInformationService.getRobotNoByMac(robotCompleteTaskDTO.getMac());
|
||||
String freeTimeKey = RobotTaskChcheConstant.ROBOT_LAST_FREE_TIME + robotNo;
|
||||
String timeStr = DateUtils.getYearMonthDayHourMinuteSecon();
|
||||
redisUtil.set(freeTimeKey, timeStr);
|
||||
} else if (RobotExecutionStateConstant.DOING.equals(robotCompleteTaskDTO.getExecutionState())) {
|
||||
robotTaskDoing(robotCompleteTaskDTO, robotDoingActionKey);
|
||||
}
|
||||
@ -156,27 +173,8 @@ public class RobotTaskStatusApiImpl implements RobotTaskStatusApi {
|
||||
* @param robotCompleteTaskDTO
|
||||
*/
|
||||
private void robotTaskDoing(RobotCompleteTaskDTO robotCompleteTaskDTO, String robotDoingActionKey) {
|
||||
String robotNo = robotInformationService.getRobotNoByMac(robotCompleteTaskDTO.getMac());
|
||||
RobotTaskDetailActionLogDO lastLog = setLastLogDone(robotCompleteTaskDTO.getOrderId());
|
||||
|
||||
if (PathTaskTypeEnum.AUTO_CHARGE.getType().equals(robotCompleteTaskDTO.getOrderType())) {
|
||||
chargeDoing(robotCompleteTaskDTO, robotDoingActionKey, lastLog);
|
||||
} else if (PathTaskTypeEnum.MOVE_TO_WAIT.getType().equals(robotCompleteTaskDTO.getOrderType())) {
|
||||
RobotTaskDetailActionLogDO logOne = new RobotTaskDetailActionLogDO();
|
||||
logOne.setActionMsg("车辆正在前往等待点");
|
||||
logOne.setRobotNo(robotNo);
|
||||
logOne.setStartTime(LocalDateTime.now());
|
||||
logOne.setTaskDetailId(robotCompleteTaskDTO.getOrderId());
|
||||
if (ObjectUtil.isNotEmpty(lastLog)) {
|
||||
logOne.setCommandType(lastLog.getCommandType());
|
||||
logOne.setTaskNo(lastLog.getTaskNo());
|
||||
}
|
||||
taskDetailActionLogMapper.insert(logOne);
|
||||
redisUtil.set(robotDoingActionKey, logOne.getActionMsg(), doingActionCacheTime);
|
||||
moveToWaitService.updateWaitStatus(robotCompleteTaskDTO.getOrderId(), WaitStatusEnum.GO_TO_WAIT.getType());
|
||||
} else {
|
||||
taskDoing(robotCompleteTaskDTO, robotDoingActionKey);
|
||||
}
|
||||
taskDoing(robotCompleteTaskDTO, robotDoingActionKey);
|
||||
|
||||
if ((PathTaskTypeEnum.AUTO_CHARGE.getType().equals(robotCompleteTaskDTO.getOrderType())
|
||||
|| PathTaskTypeEnum.CHARGE.getType().equals(robotCompleteTaskDTO.getOrderType()))
|
||||
@ -193,6 +191,11 @@ public class RobotTaskStatusApiImpl implements RobotTaskStatusApi {
|
||||
|
||||
taskDetailActionLogMapper.updateActionStatus(robotCompleteTaskDTO.getOrderId(), ActionStatusEnum.DOING.getType()
|
||||
, null);
|
||||
|
||||
if (PathTaskTypeEnum.AUTO_CHARGE.getType().equals(robotCompleteTaskDTO.getOrderType())
|
||||
|| PathTaskTypeEnum.CHARGE.getType().equals(robotCompleteTaskDTO.getOrderType()) ) {
|
||||
chargeDoing(robotCompleteTaskDTO);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -218,9 +221,24 @@ public class RobotTaskStatusApiImpl implements RobotTaskStatusApi {
|
||||
*/
|
||||
private void robotTaskDone(RobotCompleteTaskDTO robotCompleteTaskDTO) {
|
||||
setLastLogDone(robotCompleteTaskDTO.getOrderId());
|
||||
|
||||
//释放库位数据
|
||||
if (PathTaskTypeEnum.TAKE.getType().equals(robotCompleteTaskDTO.getOrderType())
|
||||
|| (PathTaskTypeEnum.TAKE_RELEASE.getType().equals(robotCompleteTaskDTO.getOrderType())
|
||||
&& CommandTypeEnum.WORK_PICK_UP_GOODS.getType().equals(robotCompleteTaskDTO.getCommandStatus().getCommandType()))) {
|
||||
releaseFromLocationAndSetRobotSkuInfo(robotCompleteTaskDTO);
|
||||
} else if (PathTaskTypeEnum.RELEASE.getType().equals(robotCompleteTaskDTO.getOrderType())
|
||||
|| PathTaskTypeEnum.TAKE_RELEASE.getType().equals(robotCompleteTaskDTO.getOrderType())) {
|
||||
releaseToLocation(robotCompleteTaskDTO);
|
||||
redisUtil.del(RobotTaskChcheConstant.ROBOT_TASK_SKU_INFO + robotCompleteTaskDTO.getMac());
|
||||
} else {
|
||||
redisUtil.del(RobotTaskChcheConstant.ROBOT_TASK_SKU_INFO + robotCompleteTaskDTO.getMac());
|
||||
}
|
||||
//todo 后面考虑下充电,车机目前对充电的逻辑未定义
|
||||
if (PathTaskTypeEnum.MOVE.getType().equals(robotCompleteTaskDTO.getOrderType())
|
||||
|| PathTaskTypeEnum.MOVE_TO_WAIT_STOP.getType().equals(robotCompleteTaskDTO.getOrderType())
|
||||
|| PathTaskTypeEnum.MOVE_TO_POINT.getType().equals(robotCompleteTaskDTO.getOrderType())
|
||||
|| PathTaskTypeEnum.MOVE_TO_WAIT.getType().equals(robotCompleteTaskDTO.getOrderType())
|
||||
|| PathTaskTypeEnum.TAKE.getType().equals(robotCompleteTaskDTO.getOrderType())
|
||||
|| PathTaskTypeEnum.CHARGE.getType().equals(robotCompleteTaskDTO.getOrderType())
|
||||
|| PathTaskTypeEnum.RELEASE.getType().equals(robotCompleteTaskDTO.getOrderType())) {
|
||||
@ -238,17 +256,114 @@ public class RobotTaskStatusApiImpl implements RobotTaskStatusApi {
|
||||
} else if (CommandTypeEnum.WORK_DROP_OFF_GOODS.getType().equals(robotCompleteTaskDTO.getCommandStatus().getCommandType())) {
|
||||
taskDone(robotCompleteTaskDTO);
|
||||
}
|
||||
} else if (PathTaskTypeEnum.MOVE_TO_WAIT.getType().equals(robotCompleteTaskDTO.getOrderType())) {
|
||||
moveToWaitService.updateWaitStatus(robotCompleteTaskDTO.getOrderId(), WaitStatusEnum.REACH_WAIT.getType());
|
||||
} else if (PathTaskTypeEnum.AUTO_CHARGE.getType().equals(robotCompleteTaskDTO.getOrderType())) {
|
||||
RobotChargeLogDO build = RobotChargeLogDO
|
||||
.builder()
|
||||
.id(robotCompleteTaskDTO.getOrderId())
|
||||
.taskStatus(ChargeTaskStatusEnum.CHARGEING.getType())
|
||||
.build();
|
||||
chargeLogMapper.updateById(build);
|
||||
}
|
||||
|
||||
if (PathTaskTypeEnum.AUTO_CHARGE.getType().equals(robotCompleteTaskDTO.getOrderType())
|
||||
|| PathTaskTypeEnum.CHARGE.getType().equals(robotCompleteTaskDTO.getOrderType())) {
|
||||
chargeLogMapper.updateChargStatusByTaskId(robotCompleteTaskDTO.getOrderId(),ChargeTaskStatusEnum.DONE.getType());
|
||||
}
|
||||
taskDetailActionLogMapper.updateActionStatus(robotCompleteTaskDTO.getOrderId(), ActionStatusEnum.DONE.getType(), LocalDateTime.now());
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 释放放货库位
|
||||
*
|
||||
* @param robotCompleteTaskDTO
|
||||
*/
|
||||
private void releaseToLocation(RobotCompleteTaskDTO robotCompleteTaskDTO) {
|
||||
RobotTaskDetailDO robotTaskDetailDO = robotTaskDetailMapper.selectById(robotCompleteTaskDTO.getOrderId());
|
||||
if (ObjectUtil.isEmpty(robotTaskDetailDO) || ObjectUtil.isEmpty(robotTaskDetailDO.getToLocationId())) {
|
||||
return;
|
||||
}
|
||||
WareHouseLocationDO toWareHouseLocation = locationMapper.selectById(robotTaskDetailDO.getToLocationId());
|
||||
if (ObjectUtil.isEmpty(toWareHouseLocation)) {
|
||||
return;
|
||||
}
|
||||
//查询最近一起取货任务
|
||||
WareHouseLocationDO fromWareHouseLocation = getFromLocation(robotTaskDetailDO);
|
||||
if (ObjectUtil.isNotEmpty(fromWareHouseLocation)) {
|
||||
toWareHouseLocation.setSkuNumber(fromWareHouseLocation.getSkuNumber());
|
||||
toWareHouseLocation.setSkuInfo(fromWareHouseLocation.getSkuInfo());
|
||||
}
|
||||
toWareHouseLocation.setLocationLock(LocationLockEnum.YES.getType());
|
||||
toWareHouseLocation.setLocationUseStatus(LocationUseStatusEnum.YES.getType());
|
||||
locationMapper.updateById(toWareHouseLocation);
|
||||
pushWareLocation(toWareHouseLocation,robotCompleteTaskDTO.getMac(),ZeroOneEnum.ONE.getType());
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询最近一次取货任务
|
||||
*
|
||||
* @param robotTaskDetailDO
|
||||
* @return
|
||||
*/
|
||||
private WareHouseLocationDO getFromLocation(RobotTaskDetailDO robotTaskDetailDO) {
|
||||
if (RobotTaskTypeEnum.TAKE_RELEASE.getType().equals(robotTaskDetailDO.getTaskType())
|
||||
&& ObjectUtil.isNotEmpty(robotTaskDetailDO.getFromLocationId())) {
|
||||
return locationMapper.selectById(robotTaskDetailDO.getFromLocationId());
|
||||
}
|
||||
List<RobotTaskDetailActionLogDO> actionLogs = taskDetailActionLogMapper.getLastTwoTask(robotTaskDetailDO.getRobotNo());
|
||||
if (ObjectUtil.isEmpty(actionLogs)) {
|
||||
return null;
|
||||
}
|
||||
for (RobotTaskDetailActionLogDO actionLog : actionLogs) {
|
||||
if (!robotTaskDetailDO.getId().equals(actionLog.getTaskDetailId())) {
|
||||
RobotTaskDetailDO taskDetail = robotTaskDetailMapper.selectById(actionLog.getTaskDetailId());
|
||||
if (ObjectUtil.isEmpty(taskDetail) || !RobotTaskTypeEnum.TAKE.getType().equals(taskDetail.getTaskType())
|
||||
|| ObjectUtil.isEmpty(taskDetail.getFromLocationId())) {
|
||||
continue;
|
||||
}
|
||||
locationMapper.selectById(taskDetail.getFromLocationId());
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置车辆上的物料信息,释放取货库位
|
||||
*
|
||||
* @param robotCompleteTaskDTO
|
||||
*/
|
||||
private void releaseFromLocationAndSetRobotSkuInfo(RobotCompleteTaskDTO robotCompleteTaskDTO) {
|
||||
RobotTaskDetailDO robotTaskDetailDO = robotTaskDetailMapper.selectById(robotCompleteTaskDTO.getOrderId());
|
||||
if (ObjectUtil.isEmpty(robotTaskDetailDO) || ObjectUtil.isEmpty(robotTaskDetailDO.getFromLocationId())) {
|
||||
return;
|
||||
}
|
||||
WareHouseLocationDO wareHouseLocationDO = locationMapper.selectById(robotTaskDetailDO.getFromLocationId());
|
||||
if (ObjectUtil.isEmpty(wareHouseLocationDO)) {
|
||||
return;
|
||||
}
|
||||
RobotSkuInfoDTO robotSkuInfo = new RobotSkuInfoDTO();
|
||||
robotSkuInfo.setHaveSku(ZeroOneEnum.ONE.getType());
|
||||
robotSkuInfo.setSkuNumber(wareHouseLocationDO.getSkuNumber());
|
||||
robotSkuInfo.setSkuInfo(wareHouseLocationDO.getSkuInfo());
|
||||
robotSkuInfo.setLocationStorey(wareHouseLocationDO.getLocationStorey());
|
||||
redisUtil.set(RobotTaskChcheConstant.ROBOT_TASK_SKU_INFO + robotCompleteTaskDTO.getMac(), JSON.toJSONString(robotSkuInfo));
|
||||
wareHouseLocationDO.setSkuInfo(null);
|
||||
wareHouseLocationDO.setSkuNumber(0L);
|
||||
wareHouseLocationDO.setLocationLock(LocationLockEnum.YES.getType());
|
||||
wareHouseLocationDO.setLocationUseStatus(LocationUseStatusEnum.NO.getType());
|
||||
locationMapper.updateById(wareHouseLocationDO);
|
||||
pushWareLocation(wareHouseLocationDO,robotCompleteTaskDTO.getMac(),ZeroOneEnum.ZERO.getType());
|
||||
}
|
||||
|
||||
public void pushWareLocation(WareHouseLocationDO wareHouseLocationDO, String mac, Integer type) {
|
||||
String floorAreaKey = RobotTaskChcheConstant.ROBOT_FLOOR_AREA + mac;
|
||||
Object floorAreaObject = redisUtil.get(floorAreaKey);
|
||||
if (ObjectUtil.isEmpty(floorAreaObject)) {
|
||||
return;
|
||||
}
|
||||
FloorZoneDTO floorZoneDTO = JSONUtil.toBean((String) floorAreaObject, FloorZoneDTO.class);
|
||||
String floorAreaStr = floorZoneDTO.getFloor() + CommonConstant.SYMBOL + floorZoneDTO.getArea();
|
||||
WsWareHouseLocationDTO wsWareHouseLocation = new WsWareHouseLocationDTO();
|
||||
wsWareHouseLocation.setActualLocationX(wareHouseLocationDO.getActualLocationX());
|
||||
wsWareHouseLocation.setActualLocationY(wareHouseLocationDO.getActualLocationY());
|
||||
wsWareHouseLocation.setType(type);
|
||||
wsWareHouseLocation.setFloor(floorZoneDTO.getFloor());
|
||||
wsWareHouseLocation.setArea(floorZoneDTO.getArea());
|
||||
log.info("让3D推送修改库存 :{}", JSON.toJSONString(wsWareHouseLocation));
|
||||
webSocketSenderApi.sendObject(floorAreaStr, WebSocketConstant.THREE_D_CHANGE_STOCK, JSON.toJSONString(wsWareHouseLocation));
|
||||
}
|
||||
|
||||
|
||||
@ -324,8 +439,7 @@ public class RobotTaskStatusApiImpl implements RobotTaskStatusApi {
|
||||
|
||||
String solve = "";
|
||||
String taskNo = "";
|
||||
if (!PathTaskTypeEnum.MOVE_TO_WAIT.getType().equals(robotCompleteTaskDTO.getOrderType())
|
||||
&& !PathTaskTypeEnum.AUTO_CHARGE.getType().equals(robotCompleteTaskDTO.getOrderType())
|
||||
if (!PathTaskTypeEnum.AUTO_CHARGE.getType().equals(robotCompleteTaskDTO.getOrderType())
|
||||
&& ObjectUtil.isEmpty(msg)) {
|
||||
taskNo = taskDetailService.getTaskNoByDetailId(robotCompleteTaskDTO.getOrderId());
|
||||
solve = " 并且到任务列表关闭任务 " + taskNo;
|
||||
@ -348,63 +462,26 @@ public class RobotTaskStatusApiImpl implements RobotTaskStatusApi {
|
||||
warnMsgService.sendWarnMsgToWebsocket(warnMsg.getWarnMsg());
|
||||
}
|
||||
|
||||
/**
|
||||
* 关闭订单
|
||||
*
|
||||
* @param taskDetailId
|
||||
*/
|
||||
public RobotTaskDetailDO closeTaskDetail(Long taskDetailId) {
|
||||
return taskDetailService.closeTaskDetail(taskDetailId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理充电中
|
||||
*
|
||||
* @param robotCompleteTaskDTO
|
||||
*/
|
||||
private void chargeDoing(RobotCompleteTaskDTO robotCompleteTaskDTO, String robotDoingActionKey, RobotTaskDetailActionLogDO lastLog) {
|
||||
RobotTaskDetailActionLogDO logOne = new RobotTaskDetailActionLogDO();
|
||||
RobotCommandStateDTO commandStatus = robotCompleteTaskDTO.getCommandStatus();
|
||||
Integer taskStatus = ChargeTaskStatusEnum.CHARGEING.getType();
|
||||
if (ObjectUtil.isNotEmpty(commandStatus) && CommandTypeEnum.MOVE_POSES.getType().equals(commandStatus.getCommandType())) {
|
||||
RobotChargeLogDO robotChargeLogDO = chargeLogMapper.selectById(robotCompleteTaskDTO.getOrderId());
|
||||
logOne.setActionMsg("车辆正在前往充电点" + robotChargeLogDO.getDeviceNo());
|
||||
logOne.setTaskStage(RobotTaskStageEnum.MOVE.getType());
|
||||
taskStatus = ChargeTaskStatusEnum.DOING.getType();
|
||||
} else if (ObjectUtil.isNotEmpty(commandStatus)) {
|
||||
logOne.setActionMsg("车辆正在充电");
|
||||
logOne.setTaskStage(RobotTaskStageEnum.CHARGEING.getType());
|
||||
}
|
||||
private void chargeDoing(RobotCompleteTaskDTO robotCompleteTaskDTO) {
|
||||
|
||||
//编辑地图会判断这表的状态,所以自动充电任务,移动到充电点就改为完成
|
||||
RobotCommandStateDTO commandStatus = robotCompleteTaskDTO.getCommandStatus();
|
||||
|
||||
//自动充电任务,移动到充电点就改为完成
|
||||
if (ObjectUtil.isNotEmpty(commandStatus) && CommandTypeEnum.MOVE_POSES.getType().equals(commandStatus.getCommandType())
|
||||
&& RobotExecutionStateConstant.DONE.equals(commandStatus.getExecutionState())) {
|
||||
taskDetailActionLogMapper.updateActionStatus(robotCompleteTaskDTO.getOrderId(), ActionStatusEnum.DONE.getType(), LocalDateTime.now());
|
||||
setTaskDone(robotCompleteTaskDTO);
|
||||
}
|
||||
|
||||
String robotNo = robotInformationService.getRobotNoByMac(robotCompleteTaskDTO.getMac());
|
||||
logOne.setRobotNo(robotNo);
|
||||
logOne.setTaskDetailId(robotCompleteTaskDTO.getOrderId());
|
||||
|
||||
logOne.setCommandType(lastLog.getCommandType());
|
||||
logOne.setTaskNo(lastLog.getTaskNo());
|
||||
logOne.setStartTime(LocalDateTime.now());
|
||||
taskDetailActionLogMapper.insert(logOne);
|
||||
redisUtil.set(robotDoingActionKey, logOne.getActionMsg(), doingActionCacheTime);
|
||||
RobotChargeLogDO build = RobotChargeLogDO
|
||||
.builder()
|
||||
.id(robotCompleteTaskDTO.getOrderId())
|
||||
.taskStatus(taskStatus)
|
||||
.build();
|
||||
chargeLogMapper.updateById(build);
|
||||
chargeLogMapper.updateChargStatusByTaskId(robotCompleteTaskDTO.getOrderId(),ChargeTaskStatusEnum.CHARGEING.getType());
|
||||
}
|
||||
|
||||
/**
|
||||
* 任务完成
|
||||
*
|
||||
* @param robotCompleteTaskDTO
|
||||
*/
|
||||
private void taskDone(RobotCompleteTaskDTO robotCompleteTaskDTO) {
|
||||
public RobotTaskDetailDO setTaskDone(RobotCompleteTaskDTO robotCompleteTaskDTO) {
|
||||
//更新任务状态
|
||||
RobotTaskDetailDO detailDO = new RobotTaskDetailDO();
|
||||
detailDO.setId(robotCompleteTaskDTO.getOrderId());
|
||||
@ -416,7 +493,8 @@ public class RobotTaskStatusApiImpl implements RobotTaskStatusApi {
|
||||
RobotTaskDetailDO robotTaskDetailDO = robotTaskDetailMapper.selectById(robotCompleteTaskDTO.getOrderId());
|
||||
List<RobotTaskDetailDO> taskDetails = robotTaskDetailMapper.queryByTaskId(robotTaskDetailDO.getRobotTaskId());
|
||||
boolean done =
|
||||
taskDetails.stream().noneMatch(v -> (v.getTaskStatus().equals(RobotTaskDetailStatusEnum.NEW.getType())));
|
||||
taskDetails.stream().noneMatch(v -> (v.getTaskStatus().equals(RobotTaskDetailStatusEnum.NEW.getType()) ||
|
||||
v.getTaskStatus().equals(RobotTaskDetailStatusEnum.DOING.getType())));
|
||||
if (done) {
|
||||
RobotTaskDO robotTaskDO = new RobotTaskDO();
|
||||
robotTaskDO.setId(taskDetails.get(0).getRobotTaskId());
|
||||
@ -425,6 +503,17 @@ public class RobotTaskStatusApiImpl implements RobotTaskStatusApi {
|
||||
robotTaskMapper.updateRobot(robotTaskDO);
|
||||
taskCycleMapper.deletByRobotTaskId(taskDetails.get(0).getRobotTaskId());
|
||||
}
|
||||
return robotTaskDetailDO;
|
||||
}
|
||||
|
||||
/**
|
||||
* 任务完成
|
||||
*
|
||||
* @param robotCompleteTaskDTO
|
||||
*/
|
||||
private void taskDone(RobotCompleteTaskDTO robotCompleteTaskDTO) {
|
||||
|
||||
RobotTaskDetailDO robotTaskDetailDO = setTaskDone(robotCompleteTaskDTO);
|
||||
|
||||
RobotInformationDO robotInformationDO = robotInformationMapper.selectOne(new LambdaQueryWrapperX<RobotInformationDO>()
|
||||
.eq(RobotInformationDO::getRobotNo, robotTaskDetailDO.getRobotNo()));
|
||||
@ -438,6 +527,11 @@ public class RobotTaskStatusApiImpl implements RobotTaskStatusApi {
|
||||
//同步任务完成给PP
|
||||
pathPlanningService.updateBehavior(String.valueOf(robotCompleteTaskDTO.getOrderId()), robotTaskDetailDO.getRobotNo()
|
||||
, "", PathIsReachEnum.END_WORK.getType());
|
||||
|
||||
if (!isSimulation) {
|
||||
String plantingKey = PathPlanningChcheConstant.PATH_PLANNING_TASK + robotCompleteTaskDTO.getOrderId();
|
||||
redisUtil.del(plantingKey);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -457,7 +551,7 @@ public class RobotTaskStatusApiImpl implements RobotTaskStatusApi {
|
||||
RobotCommandStateDTO commandStatus = robotCompleteTaskDTO.getCommandStatus();
|
||||
String commandType = commandStatus.getCommandType();
|
||||
|
||||
RobotTaskDetailActionLogDO logOne = new RobotTaskDetailActionLogDO();
|
||||
RobotTaskDetailActionLogSaveReqVO logOne = new RobotTaskDetailActionLogSaveReqVO();
|
||||
if (PathTaskTypeEnum.TAKE_RELEASE.getType().equals(robotCompleteTaskDTO.getOrderType())) {
|
||||
if (CommandTypeEnum.MOVE_POSES.getType().equals(commandType) && RobotTaskStageEnum.UN_START.getType().equals(taskStage)) {
|
||||
logOne.setActionMsg("车辆正在前往" + robotTaskDetailDO.getFromLocationNo() + "取货");
|
||||
@ -473,7 +567,8 @@ public class RobotTaskStatusApiImpl implements RobotTaskStatusApi {
|
||||
robotTaskDetailDO.setTaskStage(RobotTaskStageEnum.GO_RELEASE.getType());
|
||||
}
|
||||
|
||||
} else if (PathTaskTypeEnum.CHARGE.getType().equals(robotCompleteTaskDTO.getOrderType())) {
|
||||
} else if (PathTaskTypeEnum.CHARGE.getType().equals(robotCompleteTaskDTO.getOrderType())
|
||||
|| PathTaskTypeEnum.AUTO_CHARGE.getType().equals(robotCompleteTaskDTO.getOrderType())) {
|
||||
RobotChargeLogDO robotChargeLogDO = chargeLogMapper.selectById(robotCompleteTaskDTO.getOrderId());
|
||||
if (CommandTypeEnum.MOVE_POSES.getType().equals(commandType)) {
|
||||
logOne.setActionMsg("车辆正在前往" + robotChargeLogDO.getDeviceNo() + "充电");
|
||||
@ -483,7 +578,9 @@ public class RobotTaskStatusApiImpl implements RobotTaskStatusApi {
|
||||
robotTaskDetailDO.setTaskStage(RobotTaskStageEnum.CHARGEING.getType());
|
||||
}
|
||||
|
||||
} else if (PathTaskTypeEnum.MOVE.getType().equals(robotCompleteTaskDTO.getOrderType())) {
|
||||
} else if (PathTaskTypeEnum.MOVE.getType().equals(robotCompleteTaskDTO.getOrderType())
|
||||
|| PathTaskTypeEnum.MOVE_TO_WAIT.getType().equals(robotCompleteTaskDTO.getOrderType())
|
||||
|| PathTaskTypeEnum.MOVE_TO_POINT.getType().equals(robotCompleteTaskDTO.getOrderType())) {
|
||||
if (CommandTypeEnum.MOVE_POSES.getType().equals(commandType)) {
|
||||
logOne.setActionMsg("车辆正在前往" + robotTaskDetailDO.getToLocationNo());
|
||||
robotTaskDetailDO.setTaskStage(RobotTaskStageEnum.MOVE.getType());
|
||||
@ -515,19 +612,25 @@ public class RobotTaskStatusApiImpl implements RobotTaskStatusApi {
|
||||
//编辑地图会判断这表的状态,所以自动充电任务,移动到充电点就改为完成
|
||||
if (ObjectUtil.isNotEmpty(commandStatus) && CommandTypeEnum.MOVE_POSES.getType().equals(commandStatus.getCommandType())
|
||||
&& RobotExecutionStateConstant.DONE.equals(commandStatus.getExecutionState())
|
||||
&& PathTaskTypeEnum.CHARGE.getType().equals(robotCompleteTaskDTO.getOrderType())) {
|
||||
&& (PathTaskTypeEnum.CHARGE.getType().equals(robotCompleteTaskDTO.getOrderType())
|
||||
|| PathTaskTypeEnum.AUTO_CHARGE.getType().equals(robotCompleteTaskDTO.getOrderType()))) {
|
||||
taskDetailActionLogMapper.updateActionStatus(robotCompleteTaskDTO.getOrderId(), ActionStatusEnum.DONE.getType(), LocalDateTime.now());
|
||||
}
|
||||
|
||||
String robotNo = robotInformationService.getRobotNoByMac(robotCompleteTaskDTO.getMac());
|
||||
logOne.setRobotNo(robotNo);
|
||||
logOne.setOriginalRobotNo(robotNo);
|
||||
logOne.setTaskDetailId(robotCompleteTaskDTO.getOrderId());
|
||||
logOne.setTaskStage(robotTaskDetailDO.getTaskStage());
|
||||
logOne.setCommandType(PathTaskTypeEnum.getTaskType(robotTaskDetailDO.getTaskType()));
|
||||
logOne.setTaskNo(robotTask.getTaskNo());
|
||||
logOne.setActionStatus(ActionStatusEnum.DOING.getType());
|
||||
logOne.setStartTime(LocalDateTime.now());
|
||||
taskDetailActionLogMapper.insert(logOne);
|
||||
Long mapId = robotInformationService.getRobotMapIdByRobotNo(robotNo);
|
||||
if (ObjectUtil.isNotEmpty(mapId)) {
|
||||
logOne.setPositionMapId(mapId);
|
||||
}
|
||||
taskDetailActionLogService.createTaskDetailActionLog(logOne);
|
||||
redisUtil.set(robotDoingActionKey, logOne.getActionMsg(), doingActionCacheTime);
|
||||
robotTaskDetailMapper.updateById(robotTaskDetailDO);
|
||||
}
|
||||
@ -570,7 +673,6 @@ public class RobotTaskStatusApiImpl implements RobotTaskStatusApi {
|
||||
public void robotDoneTask(RobotCompleteTaskDTO robotCompleteTaskDTO) {
|
||||
taskExecutor.execute(() -> {
|
||||
String requestId = UUID.randomUUID().toString().replace("-", "");
|
||||
;
|
||||
MDC.put(CommonConstant.REQUEST_ID, requestId);
|
||||
try {
|
||||
doRobotDoneTask(robotCompleteTaskDTO);
|
||||
|
@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.system.api.robot;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder;
|
||||
import cn.iocoder.yudao.module.system.api.robot.vo.RobotUpdatePalletHeightDTO;
|
||||
import cn.iocoder.yudao.module.system.constant.CommonConstant;
|
||||
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.robot.RobotTaskDetailDO;
|
||||
@ -101,7 +102,7 @@ public class RobotUpdatePalletHeightApiImpl implements RobotUpdatePalletHeightAp
|
||||
.warnCode(WARN_CODE)
|
||||
.robotNo(robotNo)
|
||||
.warnType(RobotWarnType.ROBOT_WARN.getType())
|
||||
.warnMsg(data.getOrderId() + "_" + "不需要更新库位高度")
|
||||
.warnMsg(data.getOrderId() + CommonConstant.SYMBOL + "不需要更新库位高度")
|
||||
.build();
|
||||
warnMsgMapper.insert(warnMsg);
|
||||
}
|
||||
|
@ -1,7 +1,8 @@
|
||||
package cn.iocoder.yudao.module.system.api.robot;
|
||||
package cn.iocoder.yudao.module.system.api.robot.processor;
|
||||
|
||||
import cn.hutool.core.map.MapUtil;
|
||||
import cn.iocoder.yudao.module.infra.api.websocket.WebSocketSenderApi;
|
||||
import cn.iocoder.yudao.module.system.constant.webSocket.WebSocketConstant;
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Component;
|
||||
@ -46,8 +47,8 @@ public class RequestProcessor {
|
||||
private void sendData(String map, Map<String, String> data) {
|
||||
// -- 发送给对应的websocket
|
||||
// System.out.println("key:" + map + "发送数据:" + data);
|
||||
log.info("key:" + map + "发送数据:" + data);
|
||||
webSocketSenderApi.sendObject(map, "map_push", data);
|
||||
// log.info("key:" + map + "发送数据:" + data);
|
||||
webSocketSenderApi.sendObject(map, WebSocketConstant.MAP_PUSH, data);
|
||||
}
|
||||
|
||||
public void shutdown() {
|
@ -6,4 +6,9 @@ public class CommonConstant {
|
||||
* MDC请求常亮
|
||||
*/
|
||||
public static final String REQUEST_ID = "requestId";
|
||||
|
||||
/**
|
||||
* 拼接的符号 (不能改)
|
||||
*/
|
||||
public static final String SYMBOL = "_";
|
||||
}
|
||||
|
@ -0,0 +1,13 @@
|
||||
package cn.iocoder.yudao.module.system.constant.area;
|
||||
|
||||
public class FloorAreaConstant {
|
||||
|
||||
//楼层区域的KEY,通过这个KEY,可以查这个楼层下所有的机器人
|
||||
//仅限给WEBSOCKET推送给前端使用,缓存15秒
|
||||
public static String FLOOR_AREA_ROBOT = "floor:area:robot";
|
||||
|
||||
//所有的楼层区域
|
||||
public static String FLOOR_AREA_ALL = "floor:area:all";
|
||||
|
||||
|
||||
}
|
@ -9,7 +9,10 @@ public class RobotTaskChcheConstant {
|
||||
public static String ROBOT_CARGO_DETECTED = "robot:information:cargo:detected";
|
||||
|
||||
//机器人点位和电量 (拼接的是mac地址)
|
||||
public static String ROBOT_INFORMATION_POSE_BAT_SOC = "robot:information:pose:bat:soc";
|
||||
public static String ROBOT_INFORMATION_POSE_BAT = "robot:information:pose:bat";
|
||||
|
||||
//机器人电量
|
||||
public static String ROBOT_INFORMATION_SOC = "robot:information:soc";
|
||||
|
||||
//机器人楼层和区域 (拼接的是mac地址)
|
||||
public static String ROBOT_FLOOR_AREA = "robot:floor:area";
|
||||
@ -35,15 +38,15 @@ public class RobotTaskChcheConstant {
|
||||
//机器人mac地址和机器人id以及机器人类型映射(通过mac地址。获取机器人基本信息)
|
||||
public static String ROBOT_GET_ROBOT_INFO = "robot:information:getRobotInfo";
|
||||
|
||||
//机器人正在做的任务整体信息(拼接common_id)
|
||||
// public static String ROBOT_ACTION_LOG_ENTITY = "robot:action:log:entity";
|
||||
|
||||
//机器人取货完成(拼接robot_task_detail的id)
|
||||
// public static String ROBOT_ACTION_TAKE_GOODS = "robot:take:";
|
||||
|
||||
//机器人放货完成(拼接robot_task_detail的id)
|
||||
// public static String ROBOT_ACTION_RELEASE_GOODS = "robot:release:";
|
||||
|
||||
//机器人点位
|
||||
public static String ROBOT_ADDRESS = "robot:information:address";
|
||||
|
||||
//机器人速度和货叉高度 (拼接的是车辆编号robotNo)
|
||||
public static String ROBOT_SPEED_FORK_HEIGHT = "robot:speed:fork:height";
|
||||
|
||||
//机器人开始空闲的时间 (拼接的是车辆编号robotNo)
|
||||
public static String ROBOT_LAST_FREE_TIME = "robot:last:free:time";
|
||||
|
||||
//机器人物料数量(拼接的是mac地址)
|
||||
public static String ROBOT_TASK_SKU_INFO = "robot:task:sku:info";
|
||||
}
|
||||
|
@ -7,4 +7,19 @@ public class WebSocketConstant {
|
||||
* webSocket推送车机要走的点位id
|
||||
*/
|
||||
public static String PLANNING_MOVE_POSE = "planning_move_pose";
|
||||
|
||||
/**
|
||||
* 3D地图的信息
|
||||
*/
|
||||
public static String THREE_D_MAP_PUSH = "3d_map_push";
|
||||
|
||||
/**
|
||||
* 3D地图修改库存
|
||||
*/
|
||||
public static String THREE_D_CHANGE_STOCK = "3d_change_stock";
|
||||
|
||||
/**
|
||||
* 推送地图点位信息
|
||||
*/
|
||||
public static String MAP_PUSH = "map_push";
|
||||
}
|
||||
|
@ -51,6 +51,9 @@ public class AuthLoginReqVO {
|
||||
@Schema(description = "state", requiredMode = Schema.RequiredMode.REQUIRED, example = "9b2ffbc1-7425-4155-9894-9d5c08541d62")
|
||||
private String socialState;
|
||||
|
||||
@Schema(description = "登录来源地址, 远遥传: remote")
|
||||
private String clientid;
|
||||
|
||||
/**
|
||||
* 开启验证码的 Group
|
||||
*/
|
||||
|
@ -6,10 +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.controller.admin.houselocation.vo.WareHouseLocationPageReqVO;
|
||||
import cn.iocoder.yudao.module.system.controller.admin.houselocation.vo.WareHouseLocationRespVO;
|
||||
import cn.iocoder.yudao.module.system.controller.admin.houselocation.vo.WareHouseLocationSaveReqVO;
|
||||
import cn.iocoder.yudao.module.system.controller.admin.houselocation.vo.WareHouseLocationVO;
|
||||
import cn.iocoder.yudao.module.system.controller.admin.houselocation.vo.*;
|
||||
import cn.iocoder.yudao.module.system.dal.dataobject.houselocation.WareHouseLocationDO;
|
||||
import cn.iocoder.yudao.module.system.service.houselocation.HouseLocationService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
@ -123,4 +120,12 @@ public class WareHouseLocationController {
|
||||
houseLocationService.updateHouseLocationList(list);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@GetMapping("/getLocationsXYByMapId")
|
||||
@Operation(summary = "根据地图id查询,此地图对应的所有库位,包括库位坐标")
|
||||
@Parameter(name = "mapId", description = "地图id", required = true, example = "1024")
|
||||
public CommonResult<List<WareHouseLocationItemRespVO>> getLocationsXYByMapId(@RequestParam("mapId") Long mapId) {
|
||||
List<WareHouseLocationItemRespVO> list = houseLocationService.getLocationsXYByMapId(mapId);
|
||||
return success(list);
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,63 @@
|
||||
package cn.iocoder.yudao.module.system.controller.admin.houselocation.vo;
|
||||
|
||||
import com.alibaba.excel.annotation.ExcelProperty;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
@Schema(description = "管理后台 - 库位和坐标 Response VO")
|
||||
@Data
|
||||
public class WareHouseLocationItemRespVO {
|
||||
|
||||
@Schema(description = "主键ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "31866")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "库位编号")
|
||||
private String locationNo;
|
||||
|
||||
@Schema(description = "物料信息")
|
||||
private String skuInfo;
|
||||
|
||||
@Schema(description = "物料数量")
|
||||
private Long skuNumber;
|
||||
|
||||
@Schema(description = "启用/禁用(0:禁用、1:启用)")
|
||||
private Integer locationEnable;
|
||||
|
||||
@Schema(description = "锁定/正常(0:锁定、1:正常)")
|
||||
private Integer locationLock;
|
||||
|
||||
@Schema(description = "状态(0:空闲、1:占用)", example = "2")
|
||||
private Integer locationUseStatus;
|
||||
|
||||
@Schema(description = "宽度")
|
||||
private BigDecimal locationWide;
|
||||
|
||||
@Schema(description = "长度")
|
||||
private BigDecimal locationDeep;
|
||||
|
||||
@Schema(description = "层数")
|
||||
private Integer locationStorey;
|
||||
|
||||
@Schema(description = "实际坐标x轴")
|
||||
private String actualLocationX;
|
||||
|
||||
@Schema(description = "实际坐标y轴")
|
||||
private String actualLocationY;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
@ -35,7 +35,7 @@ public class DeviceInformationPageReqVO extends PageParam {
|
||||
@Schema(description = "深度")
|
||||
private BigDecimal locationDeep;
|
||||
|
||||
//1:充电桩,2:输送线,3:码垛机,4:自动门,5:提升机,6:信号灯,7:按钮盒,8:拆垛机
|
||||
//1:充电桩,2:输送线,3:码垛机,4:自动门,5:提升机,6:信号灯,7:按钮盒,8:拆垛机, 9:摄像头
|
||||
@Schema(description = "设备类型 字典device_type", example = "2")
|
||||
private Integer deviceType;
|
||||
|
||||
@ -74,8 +74,8 @@ public class DeviceInformationPageReqVO extends PageParam {
|
||||
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
|
||||
private LocalDateTime[] createTime;
|
||||
|
||||
@Schema(description = "设备使用状态(IDLE:空闲、USEING:使用中)")
|
||||
private String deviceUseStatus;
|
||||
@Schema(description = "设备使用状态(0:空闲、1:使用中)")
|
||||
private Integer deviceUseStatus;
|
||||
|
||||
@Schema(description = "设备专有属性(1:自动充电类型充电桩、2:手动充电类型充电桩)")
|
||||
private Integer deviceAttribute;
|
||||
@ -89,4 +89,10 @@ public class DeviceInformationPageReqVO extends PageParam {
|
||||
@Schema(description = "最后使用者")
|
||||
private String lastUser;
|
||||
|
||||
@Schema(description = "摄像头类型(1 枪机 2半球 3球机 4云台枪机)")
|
||||
private String cameraType;
|
||||
|
||||
@Schema(description = "摄像头编号")
|
||||
private String cameraCode;
|
||||
|
||||
}
|
||||
|
@ -42,7 +42,7 @@ public class DeviceInformationRespVO {
|
||||
@ExcelProperty("深度")
|
||||
private BigDecimal locationDeep;
|
||||
|
||||
//1:充电桩,2:输送线,3:码垛机,4:自动门,5:提升机,6:信号灯,7:按钮盒,8:拆垛机
|
||||
//1:充电桩,2:输送线,3:码垛机,4:自动门,5:提升机,6:信号灯,7:按钮盒,8:拆垛机, 9:摄像头
|
||||
@Schema(description = "设备类型 字典device_type", requiredMode = Schema.RequiredMode.REQUIRED, example = "2")
|
||||
@ExcelProperty("设备类型 字典device_type")
|
||||
private Integer deviceType;
|
||||
@ -91,9 +91,9 @@ public class DeviceInformationRespVO {
|
||||
@ExcelProperty("创建时间")
|
||||
private LocalDateTime createTime;
|
||||
|
||||
@Schema(description = "设备使用状态(IDLE:空闲、USEING:使用中)")
|
||||
@ExcelProperty("设备使用状态(IDLE:空闲、USEING:使用中)")
|
||||
private String deviceUseStatus;
|
||||
@Schema(description = "设备使用状态(0:空闲、1:使用中)")
|
||||
@ExcelProperty("设备使用状态(0:空闲、1:使用中)")
|
||||
private Integer deviceUseStatus;
|
||||
|
||||
@Schema(description = "设备专有属性(1:自动充电类型充电桩、2:手动充电类型充电桩)")
|
||||
@ExcelProperty("设备专有属性(1:自动充电类型充电桩、2:手动充电类型充电桩)")
|
||||
@ -120,4 +120,11 @@ public class DeviceInformationRespVO {
|
||||
@ExcelProperty("最后使用者")
|
||||
private String lastUser;
|
||||
|
||||
@Schema(description = "摄像头类型(1 枪机 2半球 3球机 4云台枪机)")
|
||||
@ExcelProperty("摄像头类型(1 枪机 2半球 3球机 4云台枪机)")
|
||||
private String cameraType;
|
||||
|
||||
@Schema(description = "摄像头编号")
|
||||
@ExcelProperty("摄像头编号")
|
||||
private String cameraCode;
|
||||
}
|
||||
|
@ -35,7 +35,7 @@ public class DeviceInformationSaveReqVO {
|
||||
@Schema(description = "深度")
|
||||
private BigDecimal locationDeep;
|
||||
|
||||
//1:充电桩,2:输送线,3:码垛机,4:自动门,5:提升机,6:信号灯,7:按钮盒,8:拆垛机
|
||||
//1:充电桩,2:输送线,3:码垛机,4:自动门,5:提升机,6:信号灯,7:按钮盒,8:拆垛机 9:摄像头
|
||||
@Schema(description = "设备类型 字典device_type", requiredMode = Schema.RequiredMode.REQUIRED, example = "2")
|
||||
@NotNull(message = "设备类型不能为空")
|
||||
private Integer deviceType;
|
||||
@ -72,8 +72,8 @@ public class DeviceInformationSaveReqVO {
|
||||
@Schema(description = "设备最后通讯时间")
|
||||
private LocalDateTime deviceLastTime;
|
||||
|
||||
@Schema(description = "设备使用状态(IDLE:空闲、USEING:使用中)")
|
||||
private String deviceUseStatus;
|
||||
@Schema(description = "设备使用状态(0:空闲、1:使用中)")
|
||||
private Integer deviceUseStatus;
|
||||
|
||||
@Schema(description = "设备专有属性(1:自动充电类型充电桩、2:手动充电类型充电桩)")
|
||||
private Integer deviceAttribute;
|
||||
@ -89,4 +89,9 @@ public class DeviceInformationSaveReqVO {
|
||||
@Schema(description = "最后使用者")
|
||||
private String lastUser;
|
||||
|
||||
@Schema(description = "摄像头类型(1 枪机 2半球 3球机 4云台枪机)")
|
||||
private String cameraType;
|
||||
|
||||
@Schema(description = "摄像头编号")
|
||||
private String cameraCode;
|
||||
}
|
||||
|
@ -14,7 +14,7 @@ import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_
|
||||
@ToString(callSuper = true)
|
||||
public class RobotTaskDetailActionLogPageReqVO extends PageParam {
|
||||
|
||||
@Schema(description = "下发给车机的任务id", example = "18544")
|
||||
@Schema(description = "-1代表是任务,其他的是操作的明细", example = "18544")
|
||||
private Long commandId;
|
||||
|
||||
@Schema(description = "下发给车机的任务类型", example = "2")
|
||||
@ -51,4 +51,12 @@ public class RobotTaskDetailActionLogPageReqVO extends PageParam {
|
||||
@Schema(description = "结束时间")
|
||||
private LocalDateTime endTime;
|
||||
|
||||
@Schema(description = "车辆做任务时,所在的仓库点位地图表id")
|
||||
private Long positionMapId;
|
||||
|
||||
@Schema(description = "是否已经统计(0:未统计、1:已经统计)")
|
||||
private Integer alreadyCounted;
|
||||
|
||||
@Schema(description = "这条任务第一次执行的AGV编号")
|
||||
private String originalRobotNo;
|
||||
}
|
@ -15,8 +15,8 @@ public class RobotTaskDetailActionLogRespVO {
|
||||
@ExcelProperty("主键ID")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "下发给车机的任务id", example = "18544")
|
||||
@ExcelProperty("下发给车机的任务id")
|
||||
@Schema(description = "-1代表是任务,其他的是操作的明细", example = "18544")
|
||||
@ExcelProperty("-1代表是任务,其他的是操作的明细")
|
||||
private Long commandId;
|
||||
|
||||
@Schema(description = "下发给车机的任务类型", example = "2")
|
||||
@ -61,4 +61,15 @@ public class RobotTaskDetailActionLogRespVO {
|
||||
@ExcelProperty("结束时间")
|
||||
private LocalDateTime endTime;
|
||||
|
||||
@Schema(description = "车辆做任务时,所在的仓库点位地图表id")
|
||||
@ExcelProperty("车辆做任务时,所在的仓库点位地图表id")
|
||||
private Long positionMapId;
|
||||
|
||||
@Schema(description = "是否已经统计(0:未统计、1:已经统计)")
|
||||
@ExcelProperty("是否已经统计(0:未统计、1:已经统计)")
|
||||
private Integer alreadyCounted;
|
||||
|
||||
@Schema(description = "这条任务第一次执行的AGV编号")
|
||||
@ExcelProperty("这条任务第一次执行的AGV编号")
|
||||
private String originalRobotNo;
|
||||
}
|
@ -13,7 +13,7 @@ public class RobotTaskDetailActionLogSaveReqVO {
|
||||
@Schema(description = "主键ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "25503")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "下发给车机的任务id", example = "18544")
|
||||
@Schema(description = "-1代表是任务,其他的是操作的明细", example = "18544")
|
||||
private Long commandId;
|
||||
|
||||
@Schema(description = "下发给车机的任务类型", example = "2")
|
||||
@ -26,7 +26,7 @@ public class RobotTaskDetailActionLogSaveReqVO {
|
||||
private String actionMsg;
|
||||
|
||||
@Schema(description = "动作状态(0:未开始、1:执行中、2:已完成、3:已取消、4:异常)", requiredMode = Schema.RequiredMode.REQUIRED, example = "2")
|
||||
@NotNull(message = "动作状态(0:未开始、1:执行中、2:已完成、3:已取消、4:异常)不能为空")
|
||||
// @NotNull(message = "动作状态(0:未开始、1:执行中、2:已完成、3:已取消、4:异常)不能为空") 不要了
|
||||
private Integer actionStatus;
|
||||
|
||||
@Schema(description = "AGV编号")
|
||||
@ -35,6 +35,9 @@ public class RobotTaskDetailActionLogSaveReqVO {
|
||||
@Schema(description = "robot_task_detail的id")
|
||||
private Long taskDetailId;
|
||||
|
||||
@Schema(description = "任务阶段(0:待执行、1:前往取货、2:取货中、3:前往放货、4:放货中、5:结束、6:移动中、7:正在充电、8:取消、9:人工完成、10:异常)")
|
||||
private Long taskStage;
|
||||
|
||||
@Schema(description = "任务号")
|
||||
private String taskNo;
|
||||
|
||||
@ -44,4 +47,12 @@ public class RobotTaskDetailActionLogSaveReqVO {
|
||||
@Schema(description = "结束时间")
|
||||
private LocalDateTime endTime;
|
||||
|
||||
@Schema(description = "车辆做任务时,所在的仓库点位地图表id")
|
||||
private Long positionMapId;
|
||||
|
||||
@Schema(description = "是否已经统计(0:未统计、1:已经统计)")
|
||||
private Integer alreadyCounted;
|
||||
|
||||
@Schema(description = "这条任务第一次执行的AGV编号")
|
||||
private String originalRobotNo;
|
||||
}
|
@ -22,6 +22,7 @@ import cn.iocoder.yudao.module.system.service.log.UserOperationLogService;
|
||||
import cn.iocoder.yudao.module.system.service.positionmap.PositionMapItemService;
|
||||
import cn.iocoder.yudao.module.system.service.positionmap.PositionMapLineService;
|
||||
import cn.iocoder.yudao.module.system.service.robot.RobotTaskService;
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
@ -35,6 +36,7 @@ import javax.annotation.Resource;
|
||||
import javax.validation.Valid;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
@ -136,7 +138,7 @@ public class PositionMapItemController {
|
||||
@PostMapping("/lineAddItem")
|
||||
@Operation(summary = "线上加点保存点位")
|
||||
@PreAuthorize("@ss.hasPermission('system:position-map-item:lineAddItem')")
|
||||
public CommonResult<Boolean> lineAddItem(@Valid @RequestBody List<PositionMapItemNodeDTO> list) {
|
||||
public CommonResult<Map<String,Object>> lineAddItem(@Valid @RequestBody List<PositionMapItemNodeDTO> list) {
|
||||
|
||||
PositionMapItemSaveReqVO positionMapItem = BeanUtils.toBean(list.get(0), PositionMapItemSaveReqVO.class);
|
||||
positionMapItemService.createPositionMapItem(positionMapItem);
|
||||
@ -144,10 +146,23 @@ public class PositionMapItemController {
|
||||
positionMapLineService.deletePositionMapLine(list.get(0).getOldLineId());
|
||||
List<PositionMapLineSaveReqVO> positionMapLines = list.get(0).getPositionMapLines();
|
||||
List<PositionMapLineDO> lineList = BeanUtils.toBean(positionMapLines, PositionMapLineDO.class);
|
||||
List<Long> itemIds = new ArrayList<>();
|
||||
for (PositionMapLineDO positionMapLineDO : lineList) {
|
||||
itemIds.add(positionMapLineDO.getStartingPointId());
|
||||
itemIds.add(positionMapLineDO.getEndPointId());
|
||||
}
|
||||
|
||||
Map<Long,Long> sortNumMap = positionMapItemService.getSortNumMapByIds(itemIds);
|
||||
|
||||
for (PositionMapLineDO positionMapLineDO : lineList) {
|
||||
positionMapLineDO.setPositionMapId(positionMapItem.getPositionMapId());
|
||||
positionMapLineDO.setStartingSortNum(sortNumMap.get(positionMapLineDO.getStartingPointId()).intValue());
|
||||
positionMapLineDO.setEndPointSortNum(sortNumMap.get(positionMapLineDO.getEndPointId()).intValue());
|
||||
}
|
||||
positionMapLineService.batchSaveLines(lineList);
|
||||
return success(true);
|
||||
Map<String,Object> map = new HashMap<>();
|
||||
map.put("ITEM",positionMapItemService.getPositionMapItem(positionMapItem.getId()));
|
||||
map.put("LINE",lineList);
|
||||
return success(map);
|
||||
}
|
||||
}
|
||||
|
@ -8,6 +8,7 @@ import lombok.EqualsAndHashCode;
|
||||
import lombok.ToString;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
|
||||
import javax.validation.constraints.NotEmpty;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
|
||||
@ -52,7 +53,9 @@ public class PositionMapItemPageReqVO extends PageParam {
|
||||
@Schema(description = "排序的位置,越大越优先堆放")
|
||||
private Long locationNumber;
|
||||
|
||||
@Schema(description = "等待点使用状态(0.空闲 1.使用中)")
|
||||
@Schema(description = "等待点使用状态, 0:空闲 ,1:前往停车点(预占用停车点) ,2.使用中(已经在停车位上)")
|
||||
private Integer useStatus;
|
||||
|
||||
@Schema(description = "AGV编号")
|
||||
private String robotNo;
|
||||
}
|
||||
|
@ -70,8 +70,12 @@ public class PositionMapItemRespVO {
|
||||
@ExcelProperty("排序的位置,越大越优先堆放")
|
||||
private Long locationNumber;
|
||||
|
||||
@Schema(description = "等待点使用状态(0.空闲 1.使用中)")
|
||||
@ExcelProperty("等待点使用状态(0.空闲 1.使用中)")
|
||||
@Schema(description = "等待点使用状态, 0:空闲 ,1:前往停车点(预占用停车点) ,2.使用中(已经在停车位上)")
|
||||
@ExcelProperty("等待点使用状态, 0:空闲 ,1:前往停车点(预占用停车点) ,2.使用中(已经在停车位上)")
|
||||
private Integer useStatus;
|
||||
|
||||
@Schema(description = "AGV编号")
|
||||
@ExcelProperty("等待点使用状态(0.空闲 1.使用中)")
|
||||
private String robotNo;
|
||||
|
||||
}
|
||||
|
@ -43,6 +43,9 @@ public class PositionMapItemSaveReqVO {
|
||||
@Schema(description = "排序的位置,越大越优先堆放")
|
||||
private Long locationNumber;
|
||||
|
||||
@Schema(description = "等待点使用状态(0.空闲 1.使用中)")
|
||||
@Schema(description = "等待点使用状态, 0:空闲 ,1:前往停车点(预占用停车点) ,2.使用中(已经在停车位上)")
|
||||
private Integer useStatus;
|
||||
|
||||
@Schema(description = "AGV编号")
|
||||
private String robotNo;
|
||||
}
|
||||
|
@ -121,4 +121,13 @@ public class RobotTaskController {
|
||||
return success(pageResult);
|
||||
}
|
||||
|
||||
@PostMapping("/checkHaveTask")
|
||||
@Operation(summary = "判断是否存在任务")
|
||||
@PreAuthorize("@ss.hasPermission('robot:task:checkHaveTask')")
|
||||
public CommonResult<Boolean> checkHaveTask() {
|
||||
//校验是否存在未完成的任务
|
||||
taskService.checkHaveDoingTask();
|
||||
return success(true);
|
||||
}
|
||||
|
||||
}
|
@ -4,6 +4,7 @@ import cn.iocoder.yudao.module.system.controller.admin.robot.vo.RobotTaskDetailP
|
||||
import cn.iocoder.yudao.module.system.controller.admin.robot.vo.RobotTaskDetailRespVO;
|
||||
import cn.iocoder.yudao.module.system.controller.admin.robot.vo.RobotTaskDetailSaveReqVO;
|
||||
import cn.iocoder.yudao.module.system.dal.dataobject.robot.RobotTaskDetailDO;
|
||||
import cn.iocoder.yudao.module.system.enums.robot.task.RobotTaskManualInterventionEnum;
|
||||
import cn.iocoder.yudao.module.system.service.robot.RobotTaskDetailService;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import javax.annotation.Resource;
|
||||
@ -96,7 +97,7 @@ public class RobotTaskDetailController {
|
||||
@Operation(summary = "人工完成")
|
||||
@PreAuthorize("@ss.hasPermission('robot:task-detail:manuallyCompleted')")
|
||||
public CommonResult manuallyCompleted(@RequestParam("id") Long id) {
|
||||
taskDetailService.manuallyCompleted(id,"人工完成");
|
||||
taskDetailService.manuallyCompleted(id,"人工完成", RobotTaskManualInterventionEnum.RCS_DONE.getType());
|
||||
return success(true);
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,7 @@
|
||||
package cn.iocoder.yudao.module.system.controller.admin.robot.camera;
|
||||
|
||||
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
|
||||
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.*;
|
||||
import java.util.*;
|
||||
@ -13,6 +15,7 @@ import com.alibaba.excel.annotation.*;
|
||||
public class RobotCameraRespVO {
|
||||
|
||||
@Schema(description = "主键ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "30856")
|
||||
@JsonSerialize(using = ToStringSerializer.class)
|
||||
@ExcelProperty("主键ID")
|
||||
private Long id;
|
||||
|
||||
|
@ -1,5 +1,7 @@
|
||||
package cn.iocoder.yudao.module.system.controller.admin.robot.chargelog;
|
||||
|
||||
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
|
||||
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.*;
|
||||
import java.util.*;
|
||||
@ -14,6 +16,7 @@ public class RobotChargeLogRespVO {
|
||||
|
||||
@Schema(description = "主键ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "6554")
|
||||
@ExcelProperty("主键ID")
|
||||
@JsonSerialize(using = ToStringSerializer.class)
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "AGV编号")
|
||||
|
@ -1,6 +1,8 @@
|
||||
package cn.iocoder.yudao.module.system.controller.admin.robot.detail;
|
||||
|
||||
import com.alibaba.excel.annotation.ExcelProperty;
|
||||
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
|
||||
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
@ -9,6 +11,7 @@ import java.time.LocalDateTime;
|
||||
@Data
|
||||
public class RobotTaskDetailLogResoVO {
|
||||
@Schema(description = "主键ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "26224")
|
||||
@JsonSerialize(using = ToStringSerializer.class)
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "任务号")
|
||||
|
@ -1,5 +1,7 @@
|
||||
package cn.iocoder.yudao.module.system.controller.admin.robot.mapstop;
|
||||
|
||||
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
|
||||
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.*;
|
||||
import java.util.*;
|
||||
@ -14,6 +16,7 @@ public class RobotMapStopRespVO {
|
||||
|
||||
@Schema(description = "主键ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1220")
|
||||
@ExcelProperty("主键ID")
|
||||
@JsonSerialize(using = ToStringSerializer.class)
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "急停仓库点位地图表id", example = "20550")
|
||||
|
@ -2,10 +2,11 @@ package cn.iocoder.yudao.module.system.controller.admin.robot.vo;
|
||||
|
||||
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
|
||||
import com.alibaba.excel.annotation.ExcelProperty;
|
||||
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
|
||||
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.util.Set;
|
||||
|
||||
|
||||
@ -14,6 +15,7 @@ import java.util.Set;
|
||||
@ExcelIgnoreUnannotated
|
||||
public class RobotInformationPageRespVO {
|
||||
@Schema(description = "主键ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "21881")
|
||||
@JsonSerialize(using = ToStringSerializer.class)
|
||||
@ExcelProperty("主键ID")
|
||||
private Long id;
|
||||
|
||||
|
@ -3,6 +3,8 @@ package cn.iocoder.yudao.module.system.controller.admin.robot.vo;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.type.LongListTypeHandler;
|
||||
import cn.iocoder.yudao.module.system.controller.admin.robot.camera.RobotCameraAddVO;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
|
||||
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.*;
|
||||
import java.time.LocalDateTime;
|
||||
@ -17,6 +19,7 @@ public class RobotInformationRespVO {
|
||||
|
||||
@Schema(description = "主键ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "21881")
|
||||
@ExcelProperty("主键ID")
|
||||
@JsonSerialize(using = ToStringSerializer.class)
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "车辆类型表id", example = "28234")
|
||||
|
@ -1,6 +1,8 @@
|
||||
package cn.iocoder.yudao.module.system.controller.admin.robot.vo;
|
||||
|
||||
import cn.iocoder.yudao.module.system.controller.admin.robot.camera.RobotCameraAddVO;
|
||||
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
|
||||
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import org.hibernate.validator.constraints.Range;
|
||||
@ -16,6 +18,7 @@ import java.util.Set;
|
||||
public class RobotInformationSaveReqVO {
|
||||
|
||||
@Schema(description = "主键ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "21881")
|
||||
@JsonSerialize(using = ToStringSerializer.class)
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "车辆类型表id", example = "28234")
|
||||
|
@ -2,6 +2,8 @@ package cn.iocoder.yudao.module.system.controller.admin.robot.vo;
|
||||
|
||||
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
|
||||
import com.alibaba.excel.annotation.ExcelProperty;
|
||||
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
|
||||
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
@ -14,6 +16,7 @@ public class RobotModelRespVO {
|
||||
|
||||
@Schema(description = "主键ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "15571")
|
||||
@ExcelProperty("主键ID")
|
||||
@JsonSerialize(using = ToStringSerializer.class)
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "车辆类型", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
|
@ -1,5 +1,7 @@
|
||||
package cn.iocoder.yudao.module.system.controller.admin.robot.vo;
|
||||
|
||||
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
|
||||
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.*;
|
||||
import java.util.*;
|
||||
@ -14,6 +16,7 @@ public class RobotTaskAutoMoveRespVO {
|
||||
|
||||
@Schema(description = "主键ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "30110")
|
||||
@ExcelProperty("主键ID")
|
||||
@JsonSerialize(using = ToStringSerializer.class)
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "机器人任务主表id", example = "24553")
|
||||
|
@ -9,6 +9,7 @@ import javax.validation.constraints.NotNull;
|
||||
@Data
|
||||
@Schema(description = "子列表")
|
||||
public class RobotTaskDetailAddVO {
|
||||
private Long id;
|
||||
@Schema(description = "任务类型(1:取放货、2:停车、 3:充电、4:移动、5:仅取货、6:仅放货、7:扫描码、8:检测托盘类型、9:移动到点位)", requiredMode = Schema.RequiredMode.REQUIRED, example = "2")
|
||||
@NotNull(message = "任务类型(1:取放货、2:停车、 3:充电、4:移动、5:仅取货、6:仅放货、7:扫描码、8:检测托盘类型、9:移动到点位)不能为空")
|
||||
private Integer taskType;
|
||||
|
@ -96,4 +96,10 @@ public class RobotTaskDetailPageReqVO extends PageParam {
|
||||
|
||||
@Schema(description = "是否发生异常(0:正常、1:异常)")
|
||||
private Integer occurError;
|
||||
|
||||
@Schema(description = "是否人工干预(0:未干预、1:RCS关闭、2:RCS人工完成、3:远遥取货完成、4:远遥任务完成、5:远遥取货完成和远遥任务完成)")
|
||||
private Integer manualIntervention;
|
||||
|
||||
@Schema(description = "人工干预时间")
|
||||
private LocalDateTime manualInterventionTime;
|
||||
}
|
@ -1,5 +1,7 @@
|
||||
package cn.iocoder.yudao.module.system.controller.admin.robot.vo;
|
||||
|
||||
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
|
||||
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.*;
|
||||
|
||||
@ -13,6 +15,7 @@ public class RobotTaskDetailRespVO {
|
||||
|
||||
@Schema(description = "主键ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "26224")
|
||||
@ExcelProperty("主键ID")
|
||||
@JsonSerialize(using = ToStringSerializer.class)
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "机器人任务主表id", requiredMode = Schema.RequiredMode.REQUIRED, example = "9241")
|
||||
@ -118,4 +121,10 @@ public class RobotTaskDetailRespVO {
|
||||
|
||||
@Schema(description = "是否发生异常(0:正常、1:异常)")
|
||||
private Integer occurError;
|
||||
|
||||
@Schema(description = "是否人工干预(0:未干预、1:RCS关闭、2:RCS人工完成、3:远遥取货完成、4:远遥任务完成、5:远遥取货完成和远遥任务完成)")
|
||||
private Integer manualIntervention;
|
||||
|
||||
@Schema(description = "人工干预时间")
|
||||
private LocalDateTime manualInterventionTime;
|
||||
}
|
@ -97,4 +97,10 @@ public class RobotTaskDetailSaveReqVO {
|
||||
@Schema(description = "是否发生异常(0:正常、1:异常)")
|
||||
private Integer occurError;
|
||||
|
||||
@Schema(description = "是否人工干预(0:未干预、1:RCS关闭、2:RCS人工完成、3:远遥取货完成、4:远遥任务完成、5:远遥取货完成和远遥任务完成)")
|
||||
private Integer manualIntervention;
|
||||
|
||||
@Schema(description = "人工干预时间")
|
||||
private LocalDateTime manualInterventionTime;
|
||||
|
||||
}
|
@ -1,6 +1,8 @@
|
||||
package cn.iocoder.yudao.module.system.controller.admin.robot.vo;
|
||||
|
||||
import cn.iocoder.yudao.module.system.dal.dataobject.robot.RobotTaskDetailDO;
|
||||
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
|
||||
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.*;
|
||||
import java.util.*;
|
||||
@ -17,6 +19,7 @@ public class RobotTaskRespVO {
|
||||
|
||||
@Schema(description = "主键ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "15306")
|
||||
@ExcelProperty("主键ID")
|
||||
@JsonSerialize(using = ToStringSerializer.class)
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "是否拼接任务(0:不拼接、1:拼接)", requiredMode = Schema.RequiredMode.REQUIRED)
|
||||
|
@ -1,5 +1,7 @@
|
||||
package cn.iocoder.yudao.module.system.controller.admin.robot.vo;
|
||||
|
||||
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
|
||||
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.*;
|
||||
import java.util.*;
|
||||
@ -14,6 +16,7 @@ public class RobotWarnCodeMappingRespVO {
|
||||
|
||||
@Schema(description = "主键ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "15754")
|
||||
@ExcelProperty("主键ID")
|
||||
@JsonSerialize(using = ToStringSerializer.class)
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "告警等级 (1,2,3,4)")
|
||||
|
@ -1,5 +1,7 @@
|
||||
package cn.iocoder.yudao.module.system.controller.admin.robot.vo;
|
||||
|
||||
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
|
||||
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.*;
|
||||
import java.util.*;
|
||||
@ -14,6 +16,7 @@ public class RobotWarnMsgRespVO {
|
||||
|
||||
@Schema(description = "主键ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "26180")
|
||||
@ExcelProperty("主键ID")
|
||||
@JsonSerialize(using = ToStringSerializer.class)
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "AGV编号")
|
||||
|
@ -0,0 +1,95 @@
|
||||
package cn.iocoder.yudao.module.system.controller.admin.statistics;
|
||||
|
||||
import cn.iocoder.yudao.module.system.controller.admin.statistics.vo.*;
|
||||
import cn.iocoder.yudao.module.system.dal.dataobject.statistics.RobotWorkingHoursStatisticsDO;
|
||||
import cn.iocoder.yudao.module.system.service.statistics.RobotWorkingHoursStatisticsService;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import javax.annotation.Resource;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
|
||||
import javax.validation.constraints.*;
|
||||
import javax.validation.*;
|
||||
import javax.servlet.http.*;
|
||||
import java.util.*;
|
||||
import java.io.IOException;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
|
||||
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
|
||||
|
||||
import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
|
||||
|
||||
import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog;
|
||||
import static cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum.*;
|
||||
|
||||
|
||||
@Tag(name = "管理后台 - 车辆工作时长统计")
|
||||
@RestController
|
||||
@RequestMapping("/system/statistics/robot-working-hours-statistics")
|
||||
@Validated
|
||||
public class RobotWorkingHoursStatisticsController {
|
||||
|
||||
@Resource
|
||||
private RobotWorkingHoursStatisticsService robotWorkingHoursStatisticsService;
|
||||
|
||||
@PostMapping("/create")
|
||||
@Operation(summary = "创建车辆工作时长统计")
|
||||
@PreAuthorize("@ss.hasPermission('statistics:robot-working-hours-statistics:create')")
|
||||
public CommonResult<Long> createRobotWorkingHoursStatistics(@Valid @RequestBody RobotWorkingHoursStatisticsSaveReqVO createReqVO) {
|
||||
return success(robotWorkingHoursStatisticsService.createRobotWorkingHoursStatistics(createReqVO));
|
||||
}
|
||||
|
||||
@PutMapping("/update")
|
||||
@Operation(summary = "更新车辆工作时长统计")
|
||||
@PreAuthorize("@ss.hasPermission('statistics:robot-working-hours-statistics:update')")
|
||||
public CommonResult<Boolean> updateRobotWorkingHoursStatistics(@Valid @RequestBody RobotWorkingHoursStatisticsSaveReqVO updateReqVO) {
|
||||
robotWorkingHoursStatisticsService.updateRobotWorkingHoursStatistics(updateReqVO);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@DeleteMapping("/delete")
|
||||
@Operation(summary = "删除车辆工作时长统计")
|
||||
@Parameter(name = "id", description = "编号", required = true)
|
||||
@PreAuthorize("@ss.hasPermission('statistics:robot-working-hours-statistics:delete')")
|
||||
public CommonResult<Boolean> deleteRobotWorkingHoursStatistics(@RequestParam("id") Long id) {
|
||||
robotWorkingHoursStatisticsService.deleteRobotWorkingHoursStatistics(id);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@GetMapping("/get")
|
||||
@Operation(summary = "获得车辆工作时长统计")
|
||||
@Parameter(name = "id", description = "编号", required = true, example = "1024")
|
||||
@PreAuthorize("@ss.hasPermission('statistics:robot-working-hours-statistics:query')")
|
||||
public CommonResult<RobotWorkingHoursStatisticsRespVO> getRobotWorkingHoursStatistics(@RequestParam("id") Long id) {
|
||||
RobotWorkingHoursStatisticsDO robotWorkingHoursStatistics = robotWorkingHoursStatisticsService.getRobotWorkingHoursStatistics(id);
|
||||
return success(BeanUtils.toBean(robotWorkingHoursStatistics, RobotWorkingHoursStatisticsRespVO.class));
|
||||
}
|
||||
|
||||
@GetMapping("/page")
|
||||
@Operation(summary = "获得车辆工作时长统计分页")
|
||||
@PreAuthorize("@ss.hasPermission('statistics:robot-working-hours-statistics:query')")
|
||||
public CommonResult<PageResult<RobotWorkingHoursStatisticsRespVO>> getRobotWorkingHoursStatisticsPage(@Valid RobotWorkingHoursStatisticsPageReqVO pageReqVO) {
|
||||
PageResult<RobotWorkingHoursStatisticsDO> pageResult = robotWorkingHoursStatisticsService.getRobotWorkingHoursStatisticsPage(pageReqVO);
|
||||
return success(BeanUtils.toBean(pageResult, RobotWorkingHoursStatisticsRespVO.class));
|
||||
}
|
||||
|
||||
@GetMapping("/export-excel")
|
||||
@Operation(summary = "导出车辆工作时长统计 Excel")
|
||||
@PreAuthorize("@ss.hasPermission('statistics:robot-working-hours-statistics:export')")
|
||||
@ApiAccessLog(operateType = EXPORT)
|
||||
public void exportRobotWorkingHoursStatisticsExcel(@Valid RobotWorkingHoursStatisticsPageReqVO pageReqVO,
|
||||
HttpServletResponse response) throws IOException {
|
||||
pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
|
||||
List<RobotWorkingHoursStatisticsDO> list = robotWorkingHoursStatisticsService.getRobotWorkingHoursStatisticsPage(pageReqVO).getList();
|
||||
// 导出 Excel
|
||||
ExcelUtils.write(response, "车辆工作时长统计.xls", "数据", RobotWorkingHoursStatisticsRespVO.class,
|
||||
BeanUtils.toBean(list, RobotWorkingHoursStatisticsRespVO.class));
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,72 @@
|
||||
package cn.iocoder.yudao.module.system.controller.admin.statistics;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||
import cn.iocoder.yudao.module.system.controller.admin.statistics.dto.RobotStatusClassificationDTO;
|
||||
import cn.iocoder.yudao.module.system.controller.admin.statistics.dto.RobotTaskManualInterventionDTO;
|
||||
import cn.iocoder.yudao.module.system.controller.admin.statistics.dto.RobotWarnMsgClassificationDTO;
|
||||
import cn.iocoder.yudao.module.system.controller.admin.statistics.dto.RobotWorkHourStatisticsDTO;
|
||||
import cn.iocoder.yudao.module.system.service.robot.RobotInformationService;
|
||||
import cn.iocoder.yudao.module.system.service.robot.RobotTaskDetailService;
|
||||
import cn.iocoder.yudao.module.system.service.robot.RobotWarnMsgService;
|
||||
import cn.iocoder.yudao.module.system.service.statistics.RobotWorkingHoursStatisticsService;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
|
||||
|
||||
@Tag(name = "管理后台 - 统计")
|
||||
@RestController
|
||||
@RequestMapping("/system/statistics")
|
||||
@Validated
|
||||
public class StatisticsController {
|
||||
|
||||
@Resource
|
||||
private RobotInformationService informationService;
|
||||
|
||||
@Resource
|
||||
private RobotTaskDetailService taskDetailService;
|
||||
|
||||
@Resource
|
||||
private RobotWarnMsgService warnMsgService;
|
||||
|
||||
@Resource
|
||||
private RobotWorkingHoursStatisticsService robotWorkingHoursStatisticsService;
|
||||
|
||||
@GetMapping("/robotStatusClassification")
|
||||
@Operation(summary = "统计车辆状态分类")
|
||||
@PreAuthorize("@ss.hasPermission('robot:information:robotStatusClassification')")
|
||||
public CommonResult<RobotStatusClassificationDTO> robotStatusClassification() {
|
||||
return success(informationService.robotStatusClassification());
|
||||
}
|
||||
|
||||
@GetMapping("/robotTaskAutomaticArtificial")
|
||||
@Operation(summary = "统计任务人工完成/自动完成" ,description = "type 1:周, 2:月, 3:季度")
|
||||
@PreAuthorize("@ss.hasPermission('robot:information:robotTaskAutomaticArtificial')")
|
||||
public CommonResult<RobotTaskManualInterventionDTO> robotTaskAutomaticArtificial(@RequestParam("type") String type) {
|
||||
return success(taskDetailService.robotTaskAutomaticArtificial(type));
|
||||
}
|
||||
|
||||
@GetMapping("/robotWarnMsgClassification")
|
||||
@Operation(summary = "统计故障根因分析" ,description = "type 1:周, 2:月, 3:季度")
|
||||
@PreAuthorize("@ss.hasPermission('robot:information:robotWarnMsgClassification')")
|
||||
public CommonResult<Map<String,List<RobotWarnMsgClassificationDTO>>> robotWarnMsgClassification(@RequestParam("type") String type) {
|
||||
return success(warnMsgService.robotWarnMsgClassification(type));
|
||||
}
|
||||
|
||||
@GetMapping("/robotWorkHourStatistics")
|
||||
@Operation(summary = "车辆工作时长统计" ,description = "type 1:周, 2:月, 3:季度 ; positionMapId 地图Id")
|
||||
@PreAuthorize("@ss.hasPermission('robot:information:robotWorkHourStatistics')")
|
||||
public CommonResult<List<RobotWorkHourStatisticsDTO>> robotWorkHourStatistics(@RequestParam("type") String type,
|
||||
@RequestParam("positionMapId") String positionMapId) {
|
||||
return success(robotWorkingHoursStatisticsService.robotWorkHourStatistics(type,positionMapId));
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,35 @@
|
||||
package cn.iocoder.yudao.module.system.controller.admin.statistics.dto;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
@Builder
|
||||
public class RobotStatusClassificationDTO {
|
||||
|
||||
@Schema(description = "空闲车辆百分比")
|
||||
private Integer idle ;
|
||||
|
||||
@Schema(description = "空闲车辆数量")
|
||||
private Integer idleNum = 0;
|
||||
|
||||
@Schema(description = "执行任务车辆百分比")
|
||||
private Integer doingTask;
|
||||
|
||||
@Schema(description = "执行任务车辆数量")
|
||||
private Integer doingTaskNum = 0;
|
||||
|
||||
@Schema(description = "充电车辆百分比")
|
||||
private Integer charge ;
|
||||
|
||||
@Schema(description = "充电车辆数量")
|
||||
private Integer chargeNum = 0;
|
||||
|
||||
@Schema(description = "故障车辆百分比")
|
||||
private Integer fault;
|
||||
|
||||
@Schema(description = "故障车辆数量")
|
||||
private Integer faultNum = 0;
|
||||
|
||||
}
|
@ -0,0 +1,21 @@
|
||||
package cn.iocoder.yudao.module.system.controller.admin.statistics.dto;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class RobotTaskManualInterventionDTO {
|
||||
|
||||
@Schema(description = "人工完成任务的百分比")
|
||||
private Integer artificialDone = 0;
|
||||
|
||||
@Schema(description = "人工完成任务的数量")
|
||||
private Integer artificialDoneNum = 0;
|
||||
|
||||
@Schema(description = "自动完成任务的百分比")
|
||||
private Integer automaticDone = 0;
|
||||
|
||||
@Schema(description = "自动完成任务的数量")
|
||||
private Integer automaticDoneNum = 0;
|
||||
|
||||
}
|
@ -0,0 +1,17 @@
|
||||
package cn.iocoder.yudao.module.system.controller.admin.statistics.dto;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class RobotWarnMsgClassificationDTO {
|
||||
|
||||
@Schema(description = "时间")
|
||||
private String warnTime;
|
||||
|
||||
@Schema(description = "告警等级, 1,2,3,4")
|
||||
private String warnLevel;
|
||||
|
||||
@Schema(description = "数量")
|
||||
private Integer num;
|
||||
}
|
@ -0,0 +1,20 @@
|
||||
package cn.iocoder.yudao.module.system.controller.admin.statistics.dto;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class RobotWorkHourStatisticsDTO {
|
||||
|
||||
@Schema(description = "车辆编号", example = "28478")
|
||||
private String robotNo;
|
||||
|
||||
@Schema(description = "空闲时长 单位小时", example = "28478")
|
||||
private String freeTimeNum;
|
||||
|
||||
@Schema(description = "工作时长 单位小时", example = "28478")
|
||||
private String taskTimeNum;
|
||||
|
||||
@Schema(description = "充电时长 单位小时", example = "28478")
|
||||
private String chargeTimeNum;
|
||||
}
|
@ -0,0 +1,34 @@
|
||||
package cn.iocoder.yudao.module.system.controller.admin.statistics.vo;
|
||||
|
||||
import lombok.*;
|
||||
import java.util.*;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
|
||||
|
||||
@Schema(description = "管理后台 - 车辆工作时长统计分页 Request VO")
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
public class RobotWorkingHoursStatisticsPageReqVO extends PageParam {
|
||||
|
||||
@Schema(description = "仓库点位地图表id", example = "28478")
|
||||
private Long positionMapId;
|
||||
|
||||
@Schema(description = "AGV编号")
|
||||
private String robotNo;
|
||||
|
||||
@Schema(description = "时长,单位分钟")
|
||||
private Long duration;
|
||||
|
||||
@Schema(description = "类型(0:空闲时长, 1:任务时长, 2:充电时长)", example = "1")
|
||||
private Integer durationType;
|
||||
|
||||
@Schema(description = "创建时间")
|
||||
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
|
||||
private LocalDateTime[] createTime;
|
||||
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user