远遥socket连接

This commit is contained in:
cbs 2025-05-07 18:04:14 +08:00
parent a5f790ca04
commit fb593e35f8
24 changed files with 576 additions and 20 deletions

View File

@ -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();
}
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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();
}
/**

View File

@ -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步再次右移一位如果移出位为1CRC寄存器与多项式A0011010 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"));
}
}

View File

@ -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 # 车辆通信超时报警时间

View File

@ -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 # 车辆通信超时报警时间

View File

@ -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 # 车辆通信超时报警时间

View File

@ -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 = "远遥查询地图")

View File

@ -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, "车辆摄像头信息不存在");

View File

@ -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---完成");
});
}

View File

@ -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);
}

View File

@ -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;
}
}
*/

View File

@ -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";
}

View File

@ -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')")

View File

@ -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));
}

View File

@ -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);
}
}

View File

@ -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);
/**
* 任务转移给空闲车辆

View File

@ -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);

View File

@ -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();
}

View File

@ -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());

View File

@ -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()) {

View File

@ -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();
}
}
}

View File

@ -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();
}
}
}