远遥socket连接
This commit is contained in:
parent
a5f790ca04
commit
fb593e35f8
@ -0,0 +1,239 @@
|
||||
package cn.iocoder.yudao.module.remote.api.robot;
|
||||
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
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 com.alibaba.fastjson.JSON;
|
||||
import lombok.SneakyThrows;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.annotation.PreDestroy;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.Socket;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
|
||||
import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.REMOTE_ROBOT_CONNECT_FAIL;
|
||||
|
||||
@Component
|
||||
@Slf4j
|
||||
public class RemoteControllerProcessor {
|
||||
private final ConcurrentHashMap<String, RemoteControllerSocketDTO> cache = new ConcurrentHashMap<>();
|
||||
|
||||
private 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;
|
||||
|
||||
@Value("${remote.industrial-control-time-out}")
|
||||
private int industrialControlTimeOut;
|
||||
|
||||
@Value("${remote.robot-communication-time-out}")
|
||||
private int robotCommunicationTimeOut;
|
||||
|
||||
private final String ONE = "01";
|
||||
private final String TWO = "02";
|
||||
|
||||
public void addCache() {
|
||||
RemoteControllerSocketDTO remoteControllerSocketDTO = cache.get(remoteControllerIp);
|
||||
log.info("缓存的数据 :{}", JSON.toJSONString(remoteControllerSocketDTO));
|
||||
if (ObjectUtil.isNotEmpty(remoteControllerSocketDTO)) {
|
||||
try {
|
||||
Socket socket = remoteControllerSocketDTO.getSocket();
|
||||
if (socket != null && !socket.isClosed()) {
|
||||
socket.close();
|
||||
}
|
||||
log.info("关闭socket :{}", remoteControllerIp);
|
||||
} catch (IOException e) {
|
||||
log.error("关闭socket出现异常 :{}", remoteControllerIp);
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
} else {
|
||||
remoteControllerSocketDTO = new RemoteControllerSocketDTO();
|
||||
}
|
||||
remoteControllerSocketDTO.setHost(remoteControllerIp);
|
||||
remoteControllerSocketDTO.setPort(remoteControllerPort);
|
||||
try {
|
||||
Socket socket = new Socket();
|
||||
socket.connect(new InetSocketAddress(remoteControllerIp, remoteControllerPort), 1000);
|
||||
remoteControllerSocketDTO.setSocket(socket);
|
||||
} catch (IOException e) {
|
||||
log.error("添加socket失败 :{}", e);
|
||||
throw exception(REMOTE_ROBOT_CONNECT_FAIL);
|
||||
}
|
||||
setMsg(remoteControllerSocketDTO, RemoteIpTypeEnum.ONE.getType());
|
||||
cache.put(remoteControllerIp, remoteControllerSocketDTO);
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置
|
||||
*
|
||||
* @param remoteControllerSocket
|
||||
* @param type
|
||||
*/
|
||||
public void setMsg(RemoteControllerSocketDTO remoteControllerSocket, Integer type) {
|
||||
String msg = defaultMsg;
|
||||
if (RemoteIpTypeEnum.ONE.getType().equals(type)) {
|
||||
msg = msg + " " + ONE;
|
||||
} else {
|
||||
msg = msg + " " + TWO;
|
||||
}
|
||||
|
||||
String[] split = remoteControllerSocket.getHost().split("\\.");
|
||||
for (String ipItem : split) {
|
||||
String hex = Integer.toHexString(Integer.valueOf(ipItem));
|
||||
msg = msg + " " + hex;
|
||||
log.info("组装 :{}", hex);
|
||||
}
|
||||
|
||||
String portHex = Integer.toHexString(remoteControllerSocket.getPort());
|
||||
String portHexOne = portHex.substring(0, 2);
|
||||
String portHexTwo = portHex.substring(2);
|
||||
msg = msg + " " + portHexOne + " " + portHexTwo;
|
||||
if (cockpitTimeOut > 0) {
|
||||
msg = msg + " " + ONE + " " + Integer.toHexString(cockpitTimeOut);
|
||||
} else {
|
||||
msg = msg + " " + TWO + " " + Integer.toHexString(cockpitTimeOut);
|
||||
}
|
||||
|
||||
if (industrialControlTimeOut > 0) {
|
||||
msg = msg + " " + ONE + " " + Integer.toHexString(industrialControlTimeOut);
|
||||
} else {
|
||||
msg = msg + " " + TWO + " " + Integer.toHexString(industrialControlTimeOut);
|
||||
}
|
||||
|
||||
if (robotCommunicationTimeOut > 0) {
|
||||
msg = msg + " " + ONE + " " + Integer.toHexString(robotCommunicationTimeOut);
|
||||
} else {
|
||||
msg = msg + " " + TWO + " " + Integer.toHexString(robotCommunicationTimeOut);
|
||||
}
|
||||
|
||||
String crc = CRCUtil.getCRC(msg);
|
||||
String crcOne = crc.substring(0, 2);
|
||||
String crcTwo = crc.substring(2);
|
||||
|
||||
msg = msg + " " + crcOne + " " + crcTwo;
|
||||
|
||||
remoteControllerSocket.setMsg(msg);
|
||||
}
|
||||
|
||||
public void remoteCache() {
|
||||
RemoteControllerSocketDTO remoteControllerSocketDTO = cache.get(remoteControllerIp);
|
||||
if (ObjectUtil.isEmpty(remoteControllerSocketDTO)) {
|
||||
return;
|
||||
}
|
||||
setMsg(remoteControllerSocketDTO, RemoteIpTypeEnum.THREE.getType());
|
||||
cache.remove(remoteControllerIp);
|
||||
|
||||
Socket socket = remoteControllerSocketDTO.getSocket();
|
||||
|
||||
OutputStream os = null;
|
||||
try {
|
||||
if (socket != null && !socket.isClosed()) {
|
||||
os = socket.getOutputStream();
|
||||
log.info("断开连接 :{},对应的IP :{}", remoteControllerSocketDTO.getMsg(), remoteControllerSocketDTO.getHost());
|
||||
os.write(remoteControllerSocketDTO.getMsg().getBytes());
|
||||
socket.close();
|
||||
}
|
||||
log.info("关闭socket :{}", remoteControllerIp);
|
||||
} catch (IOException e) {
|
||||
log.error("关闭socket出现异常 :{}", remoteControllerIp);
|
||||
} finally {
|
||||
if (ObjectUtil.isNotEmpty(os)) {
|
||||
try {
|
||||
os.close();
|
||||
} catch (IOException e) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
remoteCache();
|
||||
}
|
||||
|
||||
|
||||
public RemoteControllerProcessor() {
|
||||
// 每秒执行一次 - 处理并发送数据 - 避免数据丢失
|
||||
scheduler.scheduleAtFixedRate(this::processAndSend, 150, 150, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
|
||||
private void processAndSend() {
|
||||
if (ObjectUtil.isEmpty(cache)) {
|
||||
return;
|
||||
}
|
||||
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()) {
|
||||
try {
|
||||
socket = new Socket();
|
||||
socket.connect(new InetSocketAddress(v.getKey(), remoteControllerPort), 1000);
|
||||
remoteControllerSocketDTO.setSocket(socket);
|
||||
} catch (IOException e) {
|
||||
log.error("socket重连异常 :{}", e);
|
||||
}
|
||||
}
|
||||
|
||||
OutputStream os = null;
|
||||
try {
|
||||
os = socket.getOutputStream();
|
||||
String str = remoteControllerSocketDTO.getMsg();
|
||||
System.out.println(str);
|
||||
os.write(remoteControllerSocketDTO.getMsg().getBytes());
|
||||
} catch (IOException e) {
|
||||
log.error("socket发送异常 :{}", e);
|
||||
} finally {
|
||||
if (ObjectUtil.isNotEmpty(os)) {
|
||||
try {
|
||||
os.close();
|
||||
} catch (IOException e) {
|
||||
}
|
||||
}
|
||||
}
|
||||
log.info("socket发送数据成功");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void shutdown() {
|
||||
scheduler.shutdown();
|
||||
}
|
||||
|
||||
@PreDestroy
|
||||
public void destroy() {
|
||||
// 在Bean销毁前关闭去啊
|
||||
shutdown();
|
||||
}
|
||||
}
|
@ -0,0 +1,13 @@
|
||||
package cn.iocoder.yudao.module.remote.controller.admin.robot.dto;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.net.Socket;
|
||||
|
||||
@Data
|
||||
public class RemoteControllerSocketDTO {
|
||||
private String host;
|
||||
private int port;
|
||||
private Socket socket;
|
||||
private String msg;
|
||||
}
|
@ -0,0 +1,23 @@
|
||||
package cn.iocoder.yudao.module.remote.enums.robot;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
public enum RemoteIpTypeEnum {
|
||||
|
||||
ONE(1, "有效,设置车辆IP信息"),
|
||||
TWO(2, "有效,设置工控主机IP信息"),
|
||||
THREE(3, "有效:断开当前车辆IP"),
|
||||
FOUR(4, "无效,IP信息直接舍弃");
|
||||
|
||||
/**
|
||||
* 类型
|
||||
*/
|
||||
private final Integer type;
|
||||
/**
|
||||
* 说明
|
||||
*/
|
||||
private final String msg;
|
||||
}
|
@ -5,6 +5,7 @@ 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.robot.RemoteControllerProcessor;
|
||||
import cn.iocoder.yudao.module.remote.api.webSocket.RequestProcessor;
|
||||
import cn.iocoder.yudao.module.remote.constant.robot.RobotTaskChcheConstant;
|
||||
import cn.iocoder.yudao.module.remote.controller.admin.robot.dto.PositionMapRespDTO;
|
||||
@ -20,6 +21,7 @@ import cn.iocoder.yudao.module.system.api.remote.dto.RemoteRobotStatusDTO;
|
||||
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.Value;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
@ -42,6 +44,15 @@ public class RemoteRobotServiceImpl implements RemoteRobotService {
|
||||
@Resource
|
||||
private RequestProcessor processor;
|
||||
|
||||
@Resource
|
||||
private RemoteControllerProcessor remoteControllerProcessor;
|
||||
|
||||
@Value("${remote.controller-port}")
|
||||
private int remoteControllerPort;
|
||||
|
||||
@Value("${remote.controller-ip}")
|
||||
private String remoteControllerIp;
|
||||
|
||||
/**
|
||||
* 获取地图区域对应的机器人信息
|
||||
*
|
||||
@ -115,10 +126,16 @@ public class RemoteRobotServiceImpl implements RemoteRobotService {
|
||||
@Override
|
||||
public void robotChangeMode(RemoteRobotChangeModeDTO data, HttpServletRequest request) {
|
||||
String ip = IpUtils.getIp(request);
|
||||
CommonResult<Boolean> result = remoteRobotApi.robotChangeMode(data.getRemoteMode(), ip, data.getRobotNo());
|
||||
CommonResult<Boolean> result = remoteRobotApi.robotChangeMode(data.getRemoteMode(), ip, data.getRobotNo(),remoteControllerPort,remoteControllerIp);
|
||||
if (!result.isSuccess()) {
|
||||
throw exception0(TASK_COMMONG_FAIL.getCode(), result.getMsg());
|
||||
}
|
||||
//非自动模式
|
||||
if (0!= data.getRemoteMode()) {
|
||||
remoteControllerProcessor.addCache();
|
||||
}else {
|
||||
remoteControllerProcessor.remoteCache();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -138,6 +155,7 @@ public class RemoteRobotServiceImpl implements RemoteRobotService {
|
||||
if (!result.isSuccess()) {
|
||||
throw exception0(TASK_COMMONG_FAIL.getCode(), result.getMsg());
|
||||
}
|
||||
remoteControllerProcessor.remoteCache();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -0,0 +1,91 @@
|
||||
package cn.iocoder.yudao.module.remote.util.crc;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @author lwt
|
||||
* @date 2018-06-26
|
||||
*
|
||||
* CRC16校验码计算
|
||||
* <p>
|
||||
* (1).预置1个16位的寄存器为十六进制FFFF(即全为1),称此寄存器为CRC寄存器;
|
||||
* (2).把第一个8位二进制数据(既通讯信息帧的第一个字节)与16位的CRC寄存器的低
|
||||
* 8位相异或,把结果放于CRC寄存器;
|
||||
* (3).把CRC寄存器的内容右移一位(朝低位)用0填补最高位,并检查右移后的移出位;
|
||||
* (4).如果移出位为0:重复第3步(再次右移一位);如果移出位为1:CRC寄存器与多项式A001(1010 0000 0000 0001)进行异或;
|
||||
* (5).重复步骤3和4,直到右移8次,这样整个8位数据全部进行了处理;
|
||||
* (6).重复步骤2到步骤5,进行通讯信息帧下一个字节的处理;
|
||||
* (7).将该通讯信息帧所有字节按上述步骤计算完成后,得到的16位CRC寄存器的高、低
|
||||
* 字节进行交换;
|
||||
* (8).最后得到的CRC寄存器内容即为CRC16码。(注意得到的CRC码即为低前高后顺序)
|
||||
*/
|
||||
public class CRCUtil {
|
||||
/**
|
||||
* 计算CRC16校验码
|
||||
*
|
||||
* @param data 需要校验的字符串
|
||||
* @return 校验码
|
||||
*/
|
||||
public static String getCRC(String data) {
|
||||
data = data.replace(" ", "");
|
||||
int len = data.length();
|
||||
if (!(len % 2 == 0)) {
|
||||
return "0000";
|
||||
}
|
||||
int num = len / 2;
|
||||
byte[] para = new byte[num];
|
||||
for (int i = 0; i < num; i++) {
|
||||
int value = Integer.valueOf(data.substring(i * 2, 2 * (i + 1)), 16);
|
||||
para[i] = (byte) value;
|
||||
}
|
||||
return getCRC(para);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 计算CRC16校验码
|
||||
*
|
||||
* @param bytes 字节数组
|
||||
* @return {@link String} 校验码
|
||||
* @since 1.0
|
||||
*/
|
||||
public static String getCRC(byte[] bytes) {
|
||||
//CRC寄存器全为1
|
||||
int CRC = 0x0000ffff;
|
||||
//多项式校验值
|
||||
int POLYNOMIAL = 0x0000a001;
|
||||
int i, j;
|
||||
for (i = 0; i < bytes.length; i++) {
|
||||
CRC ^= ((int) bytes[i] & 0x000000ff);
|
||||
for (j = 0; j < 8; j++) {
|
||||
if ((CRC & 0x00000001) != 0) {
|
||||
CRC >>= 1;
|
||||
CRC ^= POLYNOMIAL;
|
||||
} else {
|
||||
CRC >>= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
//结果转换为16进制
|
||||
String result = Integer.toHexString(CRC).toUpperCase();
|
||||
if (result.length() != 4) {
|
||||
StringBuffer sb = new StringBuffer("0000");
|
||||
result = sb.replace(4 - result.length(), 4, result).toString();
|
||||
}
|
||||
//交换高低位
|
||||
return result.substring(2, 4) + result.substring(0, 2);
|
||||
}
|
||||
|
||||
|
||||
public static void main(String[] args) {
|
||||
//01 03 20 7F FF 7F FF 7F FF 7F FF 7F FF 7F FF 7F FF 7F FF 7F FF 7F FF 7F FF 7F FF 7F FF 7F FF 7F FF 7F FF 8C 45
|
||||
//01 03 00 00 00 08 44 0C
|
||||
//01 03 10 00 8F 02 4E 00 91 02 44 00 92 02 5A 00 8B 02 47 40 D8
|
||||
|
||||
System.out.println(getCRC("01 03 20 7F FF 7F FF 7F FF 7F FF 7F FF 7F FF 7F FF 7F FF 7F FF 7F FF 7F FF 7F FF 7F FF 7F FF 7F FF 7F FF"));
|
||||
System.out.println(getCRC("01 03 00 00 00 08"));
|
||||
System.out.println(getCRC("01 03 10 00 8F 02 4E 00 91 02 44 00 92 02 5A 00 8B 02 47"));
|
||||
|
||||
|
||||
}
|
||||
}
|
@ -52,3 +52,10 @@ logging:
|
||||
file:
|
||||
name: ${user.home}/logs/${spring.application.name}.log # 日志文件名,全路径
|
||||
|
||||
remote:
|
||||
controller-port: 9000
|
||||
controller-ip: 10.10.110.17
|
||||
msg: AA 55 13 04 01 88 88 # 驾舱socket头信息
|
||||
cockpit-time-out: 120 # 驾舱超时报警时间
|
||||
industrial-control-time-out: 120 # 工控通信超时报警时间
|
||||
robot-communication-time-out: 120 # 车辆通信超时报警时间
|
@ -52,3 +52,11 @@ logging:
|
||||
file:
|
||||
name: C:\system\install\log/${spring.application.name}.log
|
||||
|
||||
remote:
|
||||
controller-port: 9000
|
||||
controller-ip: 10.10.110.17
|
||||
msg: AA 55 13 04 01 88 88 # 驾舱socket头信息
|
||||
cockpit-time-out: 120 # 驾舱超时报警时间
|
||||
industrial-control-time-out: 120 # 工控通信超时报警时间
|
||||
robot-communication-time-out: 120 # 车辆通信超时报警时间
|
||||
|
||||
|
@ -32,3 +32,11 @@ management:
|
||||
logging:
|
||||
file:
|
||||
name: D:/project/rcs/logs/${spring.application.name}.log
|
||||
|
||||
remote:
|
||||
controller-port: 9000
|
||||
controller-ip: 10.10.110.17
|
||||
msg: AA 55 13 04 01 88 88 # 驾舱socket头信息
|
||||
cockpit-time-out: 120 # 驾舱超时报警时间
|
||||
industrial-control-time-out: 120 # 工控通信超时报警时间
|
||||
robot-communication-time-out: 120 # 车辆通信超时报警时间
|
@ -42,7 +42,9 @@ public interface RemoteRobotApi {
|
||||
@Operation(summary = "切换模式")
|
||||
CommonResult<Boolean> robotChangeMode(@RequestParam(value = "remoteMode") Integer remoteMode,
|
||||
@RequestParam(value = "ip") String ip,
|
||||
@RequestParam(value = "robotNo") String robotNo);
|
||||
@RequestParam(value = "robotNo") String robotNo,
|
||||
@RequestParam(value = "remoteControllerPort") int remoteControllerPort,
|
||||
@RequestParam(value = "remoteControllerIp") String remoteControllerIp);
|
||||
|
||||
@PostMapping(PREFIX + "/getRemotePositionMapList")
|
||||
@Operation(summary = "远遥查询地图")
|
||||
|
@ -199,6 +199,8 @@ public interface ErrorCodeConstants {
|
||||
ErrorCode ROBOT_NOT_STAND_BY = new ErrorCode(1-002-034-013, "车辆非空闲");
|
||||
ErrorCode ROBOT_ELECTRICITY_INSUFFICIENT = new ErrorCode(1-002-034-014, "车辆电量不足");
|
||||
ErrorCode ROBOT_HAVE_TASK = new ErrorCode(1-002-034-015, "车辆当前有处理中的任务,请断开连接后,选取其他空闲车辆");
|
||||
ErrorCode ROBOT_PORT_NOT_COMPLIANCE = new ErrorCode(1-002-034-016, "车辆端口范围在4096至65535之间");
|
||||
ErrorCode ROBOT_IP_NOT_COMPLIANCE = new ErrorCode(1-002-034-017, "请检测车辆IP是否符合规范");
|
||||
|
||||
// ========== 机器人任务主表 1-002-035-000 ==========
|
||||
ErrorCode TASK_NOT_EXISTS = new ErrorCode(1-002-035-001, "车辆任务主表不存在");
|
||||
@ -296,6 +298,7 @@ public interface ErrorCodeConstants {
|
||||
ErrorCode REMOTE_ALREADY_CHOOSE_ROBOT = new ErrorCode(1_002_053_014, "此车辆已经被其他远遥设备控制中");
|
||||
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, "与远遥工控机连接失败");
|
||||
|
||||
// ========== 车辆摄像头信息 1_002_054_001 ==========
|
||||
ErrorCode CAMERA_NOT_EXISTS = new ErrorCode(1_002_054_001, "车辆摄像头信息不存在");
|
||||
|
@ -19,8 +19,6 @@ import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
import static cn.iocoder.yudao.module.system.config.SystemJobConfiguration.NOTIFY_THREAD_POOL_TASK_EXECUTOR;
|
||||
|
||||
@Slf4j
|
||||
@RestController // 提供 RESTful API 接口,给 Feign 调用
|
||||
@Validated
|
||||
@ -56,14 +54,15 @@ public class PathApiImpl implements PathApi {
|
||||
//同步点位信息
|
||||
PositionMapSaveReqVO positionMapSaveReqVO = new PositionMapSaveReqVO();
|
||||
pathPlanningService.synchronousAllItem(positionMapSaveReqVO);
|
||||
//同步区域变更点的绑定信息
|
||||
pathPlanningService.sendPositionChangePointBinding();
|
||||
//同步线的信息
|
||||
pathPlanningService.synchronousPoint(positionMapSaveReqVO);
|
||||
//车辆尺寸
|
||||
pathPlanningService.robotDimensions();
|
||||
//距离、优先级、时间权重
|
||||
toolsService.sendPPsortConfig();
|
||||
//同步区域变更点的绑定信息
|
||||
pathPlanningService.sendPositionChangePointBinding();
|
||||
|
||||
log.info("初始化数据发送个PP---完成");
|
||||
});
|
||||
}
|
||||
|
@ -100,8 +100,8 @@ public class RemoteRobotApiImpl implements RemoteRobotApi {
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public CommonResult<Boolean> robotChangeMode(Integer remoteMode, String remoteIp, String robotNo) {
|
||||
controllerInformationService.robotChangeMode(remoteMode, remoteIp, robotNo);
|
||||
public CommonResult<Boolean> robotChangeMode(Integer remoteMode, String remoteIp, String robotNo,int remoteControllerPort,String remoteControllerIp) {
|
||||
controllerInformationService.robotChangeMode(remoteMode, remoteIp, robotNo,remoteControllerPort,remoteControllerIp);
|
||||
return CommonResult.success(true);
|
||||
}
|
||||
|
||||
|
@ -1,3 +1,4 @@
|
||||
/*
|
||||
package cn.iocoder.yudao.module.system.config;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
@ -24,3 +25,4 @@ public class SystemJobConfiguration {
|
||||
return executor;
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
@ -107,7 +107,7 @@ public class PathPlanningTopicConstant {
|
||||
/**
|
||||
* 区域等待点绑定信息
|
||||
*/
|
||||
public static String SYNCHRONOUS_ALL_CHANGE_POINT_BINDING = "SYNCHRONOUS_ALL_CHANGE_POINT_BINDING";
|
||||
public static String SYNCHRONOUS_ALL_SWITCH_POINT_BINDING = "SYNCHRONOUS_ALL_SWITCH_POINT_BINDING";
|
||||
|
||||
|
||||
}
|
||||
|
@ -80,6 +80,14 @@ public class WareHouseLocationController {
|
||||
return success(BeanUtils.toBean(list, WareHouseLocationRespVO.class));
|
||||
}
|
||||
|
||||
@GetMapping("/getByMapId")
|
||||
@Operation(summary = "根据地图id查询,此地图对应的所有库位")
|
||||
@Parameter(name = "mapId", description = "地图id", required = true, example = "1024")
|
||||
public CommonResult<List<WareHouseLocationRespVO>> getByMapId(@RequestParam("mapId") Long mapId) {
|
||||
List<WareHouseLocationDO> list = houseLocationService.getByMapId(mapId);
|
||||
return success(BeanUtils.toBean(list, WareHouseLocationRespVO.class));
|
||||
}
|
||||
|
||||
@PostMapping("/page")
|
||||
@Operation(summary = "获得库位分页")
|
||||
@PreAuthorize("@ss.hasPermission('ware:house-location:query')")
|
||||
|
@ -50,6 +50,7 @@ public interface WareHouseLocationMapper extends BaseMapperX<WareHouseLocationDO
|
||||
.eqIfPresent(WareHouseLocationDO::getLocationType, reqVO.getLocationType())
|
||||
.eqIfPresent(WareHouseLocationDO::getLocationNumber, reqVO.getLocationNumber())
|
||||
.eqIfPresent(WareHouseLocationDO::getTaskId, reqVO.getTaskId())
|
||||
.eqIfPresent(WareHouseLocationDO::getMapId, reqVO.getMapId())
|
||||
.betweenIfPresent(WareHouseLocationDO::getCreateTime, reqVO.getCreateTime())
|
||||
.orderByDesc(WareHouseLocationDO::getId));
|
||||
}
|
||||
|
@ -8,12 +8,8 @@ import cn.iocoder.yudao.module.mqtt.api.common.CommonApi;
|
||||
import cn.iocoder.yudao.module.mqtt.api.path.PathPlanningApi;
|
||||
import cn.iocoder.yudao.module.mqtt.api.path.dto.*;
|
||||
import cn.iocoder.yudao.module.mqtt.api.path.task.TaskPathPlanningDTO;
|
||||
import cn.iocoder.yudao.module.system.api.robot.RequestProcessor;
|
||||
import cn.iocoder.yudao.module.system.api.robot.dto.FloorZoneDTO;
|
||||
import cn.iocoder.yudao.module.system.api.robot.dto.RobotPoseStatusDTO;
|
||||
import cn.iocoder.yudao.module.system.api.robot.dto.RobotStatusDataPoseDTO;
|
||||
import cn.iocoder.yudao.module.system.api.robot.vo.PathPlanningMovePoseVO;
|
||||
import cn.iocoder.yudao.module.system.api.robot.vo.RobotInformationVO;
|
||||
import cn.iocoder.yudao.module.system.constant.path.PathPlanningChcheConstant;
|
||||
import cn.iocoder.yudao.module.system.constant.path.PathPlanningTopicConstant;
|
||||
import cn.iocoder.yudao.module.system.constant.robot.RobotTaskChcheConstant;
|
||||
@ -24,7 +20,6 @@ import cn.iocoder.yudao.module.system.controller.admin.path.dto.SimulationRobotP
|
||||
import cn.iocoder.yudao.module.system.controller.admin.positionmap.vo.PositionMapItemSaveReqVO;
|
||||
import cn.iocoder.yudao.module.system.controller.admin.positionmap.vo.PositionMapLineSaveReqVO;
|
||||
import cn.iocoder.yudao.module.system.controller.admin.positionmap.vo.PositionMapSaveReqVO;
|
||||
import cn.iocoder.yudao.module.system.controller.admin.robot.task.TaskAssignDTO;
|
||||
import cn.iocoder.yudao.module.system.dal.dataobject.config.CommonConfigDO;
|
||||
import cn.iocoder.yudao.module.system.dal.dataobject.positionmap.PositionMapDO;
|
||||
import cn.iocoder.yudao.module.system.dal.dataobject.positionmap.PositionMapItemDO;
|
||||
@ -576,7 +571,7 @@ public class PathPlanningServiceImpl implements PathPlanningService {
|
||||
public void sendPositionChangePointBinding() {
|
||||
List<PositionAllChangePointBindingDTO> bindingDTOS = positionChangePointBindingService.getAllPositionChangePointBinding();
|
||||
if (ObjectUtil.isNotEmpty(bindingDTOS)) {
|
||||
commonApi.commonMethod(bindingDTOS, PathPlanningTopicConstant.SYNCHRONOUS_ALL_CHANGE_POINT_BINDING);
|
||||
commonApi.commonMethod(bindingDTOS, PathPlanningTopicConstant.SYNCHRONOUS_ALL_SWITCH_POINT_BINDING);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -103,7 +103,7 @@ public interface RemoteControllerInformationService extends IService<RemoteContr
|
||||
* @param remoteMode
|
||||
* @param remoteIp
|
||||
*/
|
||||
void robotChangeMode(Integer remoteMode, String remoteIp, String robotNo);
|
||||
void robotChangeMode(Integer remoteMode, String remoteIp, String robotNo,int remoteControllerPort,String remoteControllerIp);
|
||||
|
||||
/**
|
||||
* 任务转移给空闲车辆
|
||||
|
@ -58,6 +58,9 @@ import javax.annotation.Resource;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.Socket;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@ -302,7 +305,7 @@ public class RemoteControllerInformationServiceImpl extends ServiceImpl<RemoteCo
|
||||
*/
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void robotChangeMode(Integer remoteMode, String remoteIp, String robotNo) {
|
||||
public void robotChangeMode(Integer remoteMode, String remoteIp, String robotNo,int remoteControllerPort,String remoteControllerIp) {
|
||||
RLock lock = redissonUtils.getLock(RobotCacheLockEnum.ROBOT_TASK_DISTRIBUTE_LOCK.getKey());
|
||||
if (lock.tryLock()) {
|
||||
try {
|
||||
@ -313,7 +316,7 @@ public class RemoteControllerInformationServiceImpl extends ServiceImpl<RemoteCo
|
||||
} catch (InterruptedException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
doRobotChangeMode(remoteMode, remoteIp, robotNo);
|
||||
doRobotChangeMode(remoteMode, remoteIp, robotNo,remoteControllerPort,remoteControllerIp);
|
||||
} finally {
|
||||
lock.unlock();
|
||||
}
|
||||
@ -551,7 +554,7 @@ public class RemoteControllerInformationServiceImpl extends ServiceImpl<RemoteCo
|
||||
* @param robotNo
|
||||
*/
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void doRobotChangeMode(Integer remoteMode, String remoteIp, String robotNo) {
|
||||
public void doRobotChangeMode(Integer remoteMode, String remoteIp, String robotNo,int remoteControllerPort,String remoteControllerIp) {
|
||||
log.info("切换模式的车辆 :{}", robotNo);
|
||||
|
||||
//后续判断下,如果协控中,能不能切换模式
|
||||
@ -568,6 +571,15 @@ public class RemoteControllerInformationServiceImpl extends ServiceImpl<RemoteCo
|
||||
throw exception(REMOTE_DEVICE_NEED_AUTOMATIC);
|
||||
}
|
||||
|
||||
if (!RemoteModeEnum.AUTOMATIC.getType().equals(remoteMode)) {
|
||||
try {
|
||||
Socket socket = new Socket();
|
||||
socket.connect(new InetSocketAddress(remoteControllerIp, remoteControllerPort), 1000);
|
||||
} catch (IOException e) {
|
||||
throw exception(REMOTE_ROBOT_CONNECT_FAIL);
|
||||
}
|
||||
}
|
||||
|
||||
RobotInformationDO robotInformation = informationService.getInformationByRobotNo(robotNo);
|
||||
|
||||
|
||||
|
@ -174,6 +174,9 @@ public class RobotMaxSpeedServiceImpl extends ServiceImpl<RobotMaxSpeedMapper, R
|
||||
.eq(PositionMapDO::getFloor, floorZoneDTO.getFloor())
|
||||
.eq(PositionMapDO::getArea, floorZoneDTO.getArea()));
|
||||
RobotMaxSpeedDO robotMaxSpeed = getRobotMaxSpeed(positionMap.getId());
|
||||
if (ObjectUtil.isEmpty(robotMaxSpeed)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return robotMaxSpeed.getMaxSpeed();
|
||||
}
|
||||
|
@ -189,6 +189,9 @@ public class RobotInformationServiceImpl extends ServiceImpl<RobotInformationMap
|
||||
if (ObjectUtil.isNotEmpty(existRobotMac)) {
|
||||
throw exception(ROBOT_MAC_ADDRESS_EXISTS);
|
||||
}
|
||||
|
||||
checkIpAndPort(createReqVO);
|
||||
|
||||
//判断机器人编号
|
||||
RobotInformationDO existRobotNo = informationMapper.selectOne(new LambdaQueryWrapper<RobotInformationDO>()
|
||||
.eq(RobotInformationDO::getRobotNo, createReqVO.getRobotNo())
|
||||
@ -243,6 +246,31 @@ public class RobotInformationServiceImpl extends ServiceImpl<RobotInformationMap
|
||||
return information.getId();
|
||||
}
|
||||
|
||||
private void checkIpAndPort(RobotInformationSaveReqVO createReqVO) {
|
||||
if (ObjectUtil.isNotEmpty(createReqVO.getRobotPort())) {
|
||||
String hexString = Integer.toHexString(createReqVO.getRobotPort().intValue());
|
||||
if (hexString.length() != 4) {
|
||||
throw exception(ROBOT_PORT_NOT_COMPLIANCE);
|
||||
}
|
||||
}
|
||||
if (ObjectUtil.isNotEmpty(createReqVO.getRobotIp())) {
|
||||
boolean validSubnet = isValidIpAddress(createReqVO.getRobotIp());
|
||||
if (!validSubnet) {
|
||||
throw exception(ROBOT_IP_NOT_COMPLIANCE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 校验IP地址是否合法
|
||||
* @param ipAddress IP地址字符串
|
||||
* @return 是否合法
|
||||
*/
|
||||
public static boolean isValidIpAddress(String ipAddress) {
|
||||
String ipPattern = "^((25[0-5]|2[0-4]\\d|[01]?\\d\\d?)\\.){3}(25[0-5]|2[0-4]\\d|[01]?\\d\\d?)$";
|
||||
return ipAddress.matches(ipPattern);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void updateInformation(RobotInformationSaveReqVO updateReqVO) {
|
||||
@ -266,6 +294,8 @@ public class RobotInformationServiceImpl extends ServiceImpl<RobotInformationMap
|
||||
}
|
||||
}
|
||||
|
||||
checkIpAndPort(updateReqVO);
|
||||
|
||||
//校验MAC地址
|
||||
RobotInformationDO query = new RobotInformationDO();
|
||||
query.setMacAddress(updateReqVO.getMacAddress());
|
||||
|
@ -274,7 +274,7 @@ public class RobotTaskDetailServiceImpl implements RobotTaskDetailService {
|
||||
List<RobotWarnMsgDO> warnMsgs = warnMsgService.getWarnMsgByDetailIds(detailIds);
|
||||
Map<Long, String> warnMsgMap = null;
|
||||
if (ObjectUtil.isNotEmpty(warnMsgs)) {
|
||||
warnMsgMap = warnMsgs.stream().collect(Collectors.toMap(RobotWarnMsgDO::getTaskDetailId, RobotWarnMsgDO::getWarnMsg));
|
||||
warnMsgMap = warnMsgs.stream().collect(Collectors.toMap(RobotWarnMsgDO::getTaskDetailId, RobotWarnMsgDO::getWarnMsg,(existingValue, newValue) -> existingValue));
|
||||
}
|
||||
|
||||
for (RemoteExceptionTaskDetailDTO record : page.getRecords()) {
|
||||
|
@ -0,0 +1,46 @@
|
||||
package cn.iocoder.yudao.module.system.util.socket;
|
||||
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.net.Socket;
|
||||
|
||||
//客服端
|
||||
public class TCPClient {
|
||||
public static void main(String[] args) throws IOException {
|
||||
//发送100个客户端请求
|
||||
for (int i = 0; i < 100; i++) {
|
||||
new Thread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
//和服务器创建连接
|
||||
Socket socket =new Socket("127.0.0.1",8800);
|
||||
|
||||
OutputStream os = socket.getOutputStream();
|
||||
String str="你好服务器====:___:";
|
||||
os.write(str.getBytes());
|
||||
//服务器返回的信息
|
||||
InputStream is=socket.getInputStream();
|
||||
byte[] bytes=new byte[1024];
|
||||
int len=is.read(bytes);
|
||||
System.out.println(new String(bytes,0,len));
|
||||
|
||||
socket.close();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}).start();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,48 @@
|
||||
package cn.iocoder.yudao.module.system.util.socket;
|
||||
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.net.ServerSocket;
|
||||
import java.net.Socket;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
public class TCPServer {
|
||||
|
||||
|
||||
|
||||
public static void main(String[] args) throws IOException {
|
||||
|
||||
ServerSocket server=new ServerSocket(9000);
|
||||
while (true){
|
||||
// 监听客户端的请求,没有的话就会进行阻塞
|
||||
Socket socket=server.accept();
|
||||
//开启一个线程进行处理客户端的请求
|
||||
new Thread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
|
||||
InputStream is=socket.getInputStream();
|
||||
byte[] bytes=new byte[1024];
|
||||
int len=is.read(bytes);
|
||||
System.out.println(new String(bytes,0,len));
|
||||
OutputStream os= socket.getOutputStream();
|
||||
//响应给客户端
|
||||
os.write("收到谢谢".getBytes());
|
||||
socket.close();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}).start();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user