Commit b09d5a05 authored by wanghao's avatar wanghao

1 指令指令完成,但是 没有检测到机械臂完成。

parent d22727dd
......@@ -148,13 +148,16 @@ public class ModbusResultHandler implements Consumer<DeviceStatusReaderDto> {
} catch (ModbusInitException e) {
log.error("Modbus初始化异常:ip={}, port={}", ip, port, e);
palletDeviceBinding.setStatus("5");
recordAlarm(palletDeviceBinding, "Modbus初始化失败:" + e.getMessage());
} catch (ModbusTransportException e) {
log.error("Modbus传输异常:ip={}, port={}, deviceId={}", ip, port, deviceId, e);
palletDeviceBinding.setStatus("5");
recordAlarm(palletDeviceBinding, "Modbus写时间失败:" + e.getMessage());
} catch (Exception e) {
// 捕获其他异常(如NPE、数据溢出)
log.error("处理Modbus数据异常:ip={}, port={}, deviceId={}", ip, port, deviceId, e);
palletDeviceBinding.setStatus("5");
recordAlarm(palletDeviceBinding, "数据处理异常:" + e.getMessage());
} finally {
// 关键:关闭Modbus连接,避免资源泄漏
......@@ -300,7 +303,6 @@ public class ModbusResultHandler implements Consumer<DeviceStatusReaderDto> {
return str == null || str.trim().isEmpty();
}
}
// 创建通用的停止条件(可选)
public static Predicate<int[]> createDefaultStopCondition() {
return values -> values.length >= 2 && values[1] == DeviceStatusReaderAndTimeSetter.TARGET_VALUE;
......
package com.zehong.system.task;
import org.quartz.Job;
import org.springframework.stereotype.Component;
import com.serotonin.modbus4j.ModbusFactory;
import com.serotonin.modbus4j.ModbusMaster;
import com.serotonin.modbus4j.exception.ModbusInitException;
import com.serotonin.modbus4j.exception.ModbusTransportException;
import com.serotonin.modbus4j.ip.IpParameters;
import com.serotonin.modbus4j.ip.tcp.TcpMaster;
import com.serotonin.modbus4j.msg.ModbusResponse;
import com.serotonin.modbus4j.msg.ReadHoldingRegistersRequest;
import com.serotonin.modbus4j.msg.ReadHoldingRegistersResponse;
import com.zehong.system.domain.PalletDeviceBinding;
import com.zehong.system.domain.TEquipmentAlarmData;
import com.zehong.system.domain.TStoreyInfo;
import com.zehong.system.mapper.PalletDeviceBindingMapper;
import com.zehong.system.mapper.TStoreyInfoMapper;
import com.zehong.system.modbus.handler.ModbusResultHandler;
import com.zehong.system.modbus.handler.dto.DeviceStatusReaderDto;
......@@ -32,8 +31,10 @@ import java.lang.reflect.Field;
import java.net.Socket;
import java.util.Date;
import java.util.List;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.function.Predicate;
/**
* @author lenovo
......@@ -44,15 +45,18 @@ import java.util.function.Predicate;
public abstract class BaseDeviceCommJob implements Job {
private static final Logger log = LoggerFactory.getLogger(BaseDeviceCommJob.class);
// -------------------------- 公共常量配置 --------------------------
private static final int TOTAL_TASK_TIMEOUT_SEC = 240; // 任务总超时:4分钟
private static final int SINGLE_DEVICE_TIMEOUT_SEC = 10; // 单个设备超时:10秒
private static final int MODBUS_CONN_TIMEOUT_MS = 3000; // 连接超时:3秒
private static final int CUSTOM_RETRY_TIMES = 1; // 自定义重试次数:1次
private static final int RETRY_DELAY_MS = 200; // 重试间隔:200ms
// -------------------------- 核心常量(仅保留必要配置,删除冗余) --------------------------
// 超时配置:适配单设备场景,无需预留多设备缓冲
private static final int SINGLE_DEVICE_TIMEOUT_SEC = 10; // 单个设备总超时
private static final int MODBUS_CONN_TIMEOUT_MS = 3000; // Modbus连接超时
// 重试配置:单设备重试1次足够,避免过度占用连接
private static final int CUSTOM_RETRY_TIMES = 3;
private static final int RETRY_DELAY_MS = 200;
// Modbus寄存器固定配置(单设备无需动态调整)
private static final int REG_START_ADDR = 0;
private static final int REG_READ_COUNT = 10;
private static final ModbusFactory modbusFactory = new ModbusFactory(); // 单例工厂
// 单例Modbus工厂:避免重复创建开销
private static final ModbusFactory modbusFactory = new ModbusFactory();
// -------------------------- 公共依赖注入 --------------------------
@Resource
......@@ -62,6 +66,9 @@ public abstract class BaseDeviceCommJob implements Job {
@Autowired
protected ModbusResultHandler resultHandler;
@Resource
private PalletDeviceBindingMapper palletDeviceBindingMapper;
// -------------------------- 抽象方法:子类实现差异化 --------------------------
/**
* 获取当前Job的固定端口号(501/502/503)
......@@ -71,248 +78,247 @@ public abstract class BaseDeviceCommJob implements Job {
/**
* 获取当前端口对应的设备ID列表
*/
protected abstract List<Integer> getDeviceIds();
protected abstract int getDeviceId();
// -------------------------- 核心执行逻辑(公共) --------------------------
// -------------------------- 核心执行逻辑(单设备直连,无冗余步骤) --------------------------
@Override
public void execute(JobExecutionContext context) throws JobExecutionException {
public void execute(JobExecutionContext context) {
long taskStartTime = System.currentTimeMillis();
String storeyIdStr = getStoreyIdFromContext(context);
ExecutorService deviceExecutor = null;
// 单设备场景:直接获取唯一deviceId(子类返回的List仅1个元素)
Integer deviceId = getSingleDeviceId();
TStoreyInfo storeyInfo = null;
try {
// 1. 初始化线程池(单个端口设备数较少,核心线程数设为5)
deviceExecutor = new ThreadPoolExecutor(
5, 5,
0, TimeUnit.SECONDS,
new LinkedBlockingQueue<>(30),
r -> new Thread(r, "modbus-port-" + getFixedPort() + "-" + storeyIdStr),
new ThreadPoolExecutor.AbortPolicy()
);
log.info("单设备任务开始:port={}, deviceId={}, storeyId={}",
getFixedPort(), deviceId, storeyIdStr);
// 2. 执行当前端口的设备通信(带总超时
executePortDevices(context, deviceExecutor, taskStartTime, storeyIdStr);
// 1. 校验基础参数(设备信息、IP、端口
storeyInfo = validateBaseParams(storeyIdStr);
log.info("端口[{}]通信任务执行成功:fStoreyId={},总耗时={}ms",
getFixedPort(), storeyIdStr, System.currentTimeMillis() - taskStartTime);
if(storeyInfo == null) {
log.info("设备不存在:fStoreyId={}", storeyIdStr);
return;
}
String deviceIp = storeyInfo.getfIp();
int port = getFixedPort();
} catch (Throwable e) {
String errMsg = "端口[" + getFixedPort() + "]通信任务异常:fStoreyId=" + storeyIdStr;
log.error(errMsg, e);
recordAlarm(null, storeyIdStr, errMsg + ":" + e.getMessage());
throw new JobExecutionException(errMsg, e); // 抛出让Quartz感知,不隐藏异常
} finally {
// 3. 强制关闭线程池,避免资源泄漏
if (deviceExecutor != null && !deviceExecutor.isShutdown()) {
deviceExecutor.shutdownNow();
try {
if (!deviceExecutor.awaitTermination(5, TimeUnit.SECONDS)) {
log.warn("端口[{}]线程池关闭超时:fStoreyId={}", getFixedPort(), storeyIdStr);
}
} catch (InterruptedException e) {
log.warn("端口[{}]线程池关闭被中断:fStoreyId={}", getFixedPort(), storeyIdStr);
}
// 2. 执行单设备Modbus通信(带超时+重试)
int[] modbusResult = executeModbusWithTimeout(deviceIp, port, deviceId);
// 3. 处理Modbus结果(非必须,为空则跳过)
if (resultHandler != null && modbusResult != null) {
resultHandler.accept(new DeviceStatusReaderDto(deviceIp, port, deviceId, modbusResult));
} else {
updateDeviceError(storeyInfo.getfIp());
}
log.info("单设备任务成功:port={}, deviceId={}, storeyId={},耗时={}ms",
port, deviceId, storeyIdStr, System.currentTimeMillis() - taskStartTime);
} catch (Throwable e) {
// 单设备异常直接捕获,记录告警并抛出让Quartz感知
String errMsg = String.format("单设备任务失败:port=%d, deviceId=%d, storeyId=%s",
getFixedPort(), deviceId, storeyIdStr);
log.info(errMsg, e);
if(storeyInfo != null) {
updateDeviceError(storeyInfo.getfIp());
}
recordAlarm(storeyInfo, storeyIdStr, errMsg + ":" + e.getMessage());
}
}
// -------------------------- 精简后的核心工具方法 --------------------------
/**
* 执行当前端口的所有设备通信(带总超时
* 提取单个deviceId(子类返回的List仅1个元素,避免集合遍历
*/
private void executePortDevices(JobExecutionContext context, ExecutorService deviceExecutor,
long taskStartTime, String storeyIdStr) throws Exception {
// 校验设备信息
TStoreyInfo storeyInfo = validateAndGetStoreyInfo(storeyIdStr);
String ip = storeyInfo.getfIp();
int port = getFixedPort();
List<Integer> deviceIds = getDeviceIds();
// 设备通信计数器
CountDownLatch deviceLatch = new CountDownLatch(deviceIds.size());
AtomicInteger deviceErrorCount = new AtomicInteger(0);
// 逐个设备提交任务
for (int deviceId : deviceIds) {
deviceExecutor.submit(() -> {
try {
executeSingleDeviceWithTimeout(ip, port, deviceId, storeyIdStr);
} catch (Exception e) {
deviceErrorCount.incrementAndGet();
log.error("端口[{}]设备[{}]通信异常:fStoreyId={}",
port, deviceId, storeyIdStr, e);
recordAlarm(storeyInfo, "设备" + deviceId + "通信异常:" + e.getMessage());
} finally {
deviceLatch.countDown();
}
});
}
// 等待所有设备完成(带总超时)
boolean allCompleted = deviceLatch.await(TOTAL_TASK_TIMEOUT_SEC, TimeUnit.SECONDS);
long totalCost = System.currentTimeMillis() - taskStartTime;
// 超时校验
if (totalCost > TOTAL_TASK_TIMEOUT_SEC * 1000) {
String errMsg = "端口[" + port + "]任务总超时:fStoreyId=" + storeyIdStr + ",耗时=" + totalCost + "ms";
log.warn(errMsg);
recordAlarm(storeyInfo, errMsg);
}
// 错误统计
if (deviceErrorCount.get() > 0) {
String errMsg = "端口[" + port + "]" + deviceErrorCount.get() + "个设备通信失败:fStoreyId=" + storeyIdStr;
log.error(errMsg);
recordAlarm(storeyInfo, errMsg);
}
private Integer getSingleDeviceId() {
return getDeviceId();
}
// -------------------------- 以下为原DeviceCommunicationJob的公共工具方法 --------------------------
protected TStoreyInfo validateAndGetStoreyInfo(String storeyIdStr) {
if (StringUtils.isBlank(storeyIdStr)) {
String errMsg = "fStoreyId为空:端口[" + getFixedPort() + "]";
log.error(errMsg);
recordAlarm(null, "unknown", errMsg);
throw new RuntimeException(errMsg);
/**
* 校验基础参数(storeyId、设备信息、IP),失败直接抛异常
*/
private TStoreyInfo validateBaseParams(String storeyIdStr) {
// 1. 校验storeyId格式
if (StringUtils.isBlank(storeyIdStr)) {
log.info("storeyId为空:port=" + getFixedPort());
}
Long storeyId;
try {
storeyId = Long.parseLong(storeyIdStr);
} catch (NumberFormatException e) {
String errMsg = "fStoreyId格式错误:" + storeyIdStr + ",端口[" + getFixedPort() + "]";
log.error(errMsg);
recordAlarm(null, storeyIdStr, errMsg);
throw new RuntimeException(errMsg);
Long storeyId = parseStoreyId(storeyIdStr);
if(storeyId == null) {
log.info("storeyId格式错误:port=" + getFixedPort());
return null;
}
// 2. 校验设备信息和IP
TStoreyInfo storeyInfo = tStoreyInfoMapper.selectTStoreyInfoById(storeyId);
if (storeyInfo == null || StringUtils.isBlank(storeyInfo.getfIp())) {
String errMsg = "设备信息无效:fStoreyId=" + storeyId + ",端口[" + getFixedPort() + "]";
log.error(errMsg);
recordAlarm(null, storeyIdStr, errMsg);
throw new RuntimeException(errMsg);
log.info("设备信息无效:storeyId="+storeyId);
}
return storeyInfo;
}
protected void executeSingleDeviceWithTimeout(String ip, int port, int deviceId, String storeyIdStr) {
Future<?> deviceFuture = Executors.newSingleThreadExecutor().submit(() -> {
try {
int[] result = readDeviceWithRetry(ip, port, deviceId, storeyIdStr);
if (resultHandler != null) {
resultHandler.accept(new DeviceStatusReaderDto(ip, port, deviceId, result));
}
} catch (Exception e) {
throw new RuntimeException("设备[" + deviceId + "]读取失败", e);
}
});
/**
* 解析storeyId(单独抽离,减少代码冗余)
*/
private Long parseStoreyId(String storeyIdStr) {
try {
return Long.parseLong(storeyIdStr);
} catch (NumberFormatException e) {
log.info("设备信息无效:storeyId="+storeyIdStr);
}
return null;
}
/**
* 单设备Modbus通信(带超时+重试,无线程池,用Future做超时控制)
*/
private int[] executeModbusWithTimeout(String ip, int port, int deviceId) throws Exception {
// 用单线程池做超时控制(比自定义线程更轻量,执行完自动销毁)
ExecutorService singleExecutor = Executors.newSingleThreadExecutor();
try {
deviceFuture.get(SINGLE_DEVICE_TIMEOUT_SEC, TimeUnit.SECONDS);
} catch (TimeoutException e) {
deviceFuture.cancel(true);
throw new RuntimeException("设备[" + deviceId + "]通信超时(>" + SINGLE_DEVICE_TIMEOUT_SEC + "秒)");
} catch (Exception e) {
throw new RuntimeException("设备[" + deviceId + "]通信异常", e.getCause());
Future<int[]> future = singleExecutor.submit(() ->
readModbusWithRetry(ip, port, deviceId)
);
// 超时控制:超过SINGLE_DEVICE_TIMEOUT_SEC秒直接中断
return future.get(SINGLE_DEVICE_TIMEOUT_SEC, TimeUnit.SECONDS);
} finally {
// 强制关闭线程池,避免资源泄漏(单线程池关闭开销极小)
singleExecutor.shutdownNow();
}
}
protected int[] readDeviceWithRetry(String ip, int port, int deviceId, String storeyIdStr) throws Exception {
/**
* Modbus读取(带重试,连接用完即时销毁)
*/
private int[] readModbusWithRetry(String ip, int port, int deviceId) throws Exception {
ModbusMaster master = null;
int[] result = null;
for (int retry = 0; retry <= CUSTOM_RETRY_TIMES; retry++) {
try {
// 1. 创建Modbus连接(禁用内置重试,避免冲突)
master = createModbusMaster(ip, port);
result = readDeviceRegisters(master, deviceId);
Predicate<int[]> stopCondition = ModbusResultHandler.createDefaultStopCondition();
if (stopCondition.test(result)) {
log.debug("端口[{}]设备[{}]读取成功:重试={},fStoreyId={}",
port, deviceId, retry, storeyIdStr);
break;
} else if (retry < CUSTOM_RETRY_TIMES) {
Thread.sleep(RETRY_DELAY_MS);
// 2. 读取寄存器
int[] result = readRegisters(master, deviceId);
// 3. 校验结果(满足停止条件则返回,否则重试)
if (isValidResult(result)) {
log.info("Modbus读取成功:retry={}, port={}, deviceId={}", retry, port, deviceId);
return result;
}
log.info("Modbus结果不满足条件,重试:retry={}, port={}, deviceId={}", retry, port, deviceId);
} catch (Exception e) {
// 重试耗尽才抛异常
if (retry >= CUSTOM_RETRY_TIMES) {
log.error("端口[{}]设备[{}]重试耗尽({}次):fStoreyId={}",
port, deviceId, CUSTOM_RETRY_TIMES, storeyIdStr, e);
throw e;
throw new RuntimeException(String.format("Modbus重试耗尽(%d次):ip=%s, port=%d, deviceId=%d",
CUSTOM_RETRY_TIMES, ip, port, deviceId), e);
}
Thread.sleep(RETRY_DELAY_MS);
log.info("Modbus读取异常,重试:retry={}, port={}, deviceId={}", retry, port, deviceId, e);
} finally {
// 每次重试后销毁连接(关键:避免单设备场景下的连接泄漏)
destroyModbusMaster(master, deviceId);
// 重试间隔(最后一次重试无需等)
if (retry < CUSTOM_RETRY_TIMES) {
Thread.sleep(RETRY_DELAY_MS);
}
}
}
return result;
log.info("Modbus读取无有效结果:ip=" + ip + ", port=" + port + ", deviceId=" + deviceId);
return null;
}
protected ModbusMaster createModbusMaster(String ip, int port) throws ModbusInitException {
// -------------------------- Modbus基础操作(保留核心,精简冗余) --------------------------
/**
* 创建Modbus Master(无冗余配置,仅核心参数)
*/
private ModbusMaster createModbusMaster(String ip, int port) throws ModbusInitException {
IpParameters params = new IpParameters();
params.setHost(ip);
params.setPort(port);
TcpMaster master = (TcpMaster) modbusFactory.createTcpMaster(params, true);
master.setTimeout(MODBUS_CONN_TIMEOUT_MS);
master.setRetries(0); // 禁用内置重试,用自定义重试
master.setRetries(0); // 禁用内置重试,用自定义重试逻辑
master.init();
return master;
}
protected int[] readDeviceRegisters(ModbusMaster master, int deviceId) throws ModbusTransportException {
/**
* 读取寄存器(无冗余判断,直接强转)
*/
private int[] readRegisters(ModbusMaster master, int deviceId) throws ModbusTransportException {
ReadHoldingRegistersRequest request = Modbus4jUtils.getReadHoldingRegistersRequest(
deviceId, REG_START_ADDR, REG_READ_COUNT);
ModbusResponse response = master.send(request);
if (!(response instanceof ReadHoldingRegistersResponse)) {
throw new RuntimeException("无效Modbus响应:设备[" + deviceId + "]");
}
short[] signedVals = ((ReadHoldingRegistersResponse) response).getShortData();
ReadHoldingRegistersResponse response = (ReadHoldingRegistersResponse) master.send(request);
// 转换为无符号整数(单设备场景无需循环优化,直接遍历)
short[] signedVals = response.getShortData();
int[] unsignedVals = new int[signedVals.length];
for (int i = 0; i < signedVals.length; i++) {
unsignedVals[i] = signedVals[i] & 0xFFFF; // 转无符号整数
unsignedVals[i] = signedVals[i] & 0xFFFF;
}
return unsignedVals;
}
protected void destroyModbusMaster(ModbusMaster master, int deviceId) {
/**
* 销毁Modbus连接(精简反射逻辑,失败仅日志告警,不中断主流程)
*/
private void destroyModbusMaster(ModbusMaster master, int deviceId) {
if (master == null) return;
// 1. 关闭底层Socket(反射失败不抛异常,避免影响主流程)
if (master instanceof TcpMaster) {
closeSocket((TcpMaster) master, deviceId);
}
// 2. 销毁Master
try {
if (master instanceof TcpMaster) {
Socket socket = getUnderlyingSocket((TcpMaster) master);
if (socket != null && !socket.isClosed()) {
socket.close();
}
}
master.destroy();
} catch (Exception e) {
log.error("设备[{}]Socket销毁异常", deviceId, e);
} finally {
try {
master.destroy();
} catch (Exception e) {
log.error("设备[{}]ModbusMaster销毁异常", deviceId, e);
}
log.info("ModbusMaster销毁异常:deviceId={}", deviceId, e);
}
}
private Socket getUnderlyingSocket(TcpMaster tcpMaster) {
/**
* 关闭底层Socket(精简反射代码,减少异常处理层级)
*/
private void closeSocket(TcpMaster tcpMaster, int deviceId) {
try {
Field socketField = TcpMaster.class.getDeclaredField("socket");
socketField.setAccessible(true);
return (Socket) socketField.get(tcpMaster);
Socket socket = (Socket) socketField.get(tcpMaster);
if (socket != null && !socket.isClosed()) {
socket.close();
}
} catch (Exception e) {
log.warn("反射获取Socket失败:TcpMaster版本不匹配", e);
return null;
log.info("Modbus Socket关闭异常:deviceId={}", deviceId, e);
}
}
// -------------------------- 保留的基础工具方法(仅核心) --------------------------
/**
* 校验Modbus结果有效性(调用ResultHandler的停止条件,避免重复逻辑)
*/
private boolean isValidResult(int[] result) {
if (result == null || result.length == 0) {
return false;
}
Predicate<int[]> stopCondition = ModbusResultHandler.createDefaultStopCondition();
return stopCondition.test(result);
}
protected String getStoreyIdFromContext(JobExecutionContext context) {
/**
* 从JobContext获取storeyId(精简异常处理,失败返回unknown)
*/
private String getStoreyIdFromContext(JobExecutionContext context) {
try {
return context.getJobDetail().getJobDataMap().getString("fStoreyId");
} catch (Exception e) {
log.error("获取fStoreyId失败", e);
log.info("获取storeyId失败", e);
return "unknown";
}
}
/**
* 记录告警(保留原逻辑,精简参数判断)
*/
protected void recordAlarm(TStoreyInfo storeyInfo, String equipmentCode, String alarmData) {
try {
TEquipmentAlarmData alarm = new TEquipmentAlarmData();
......@@ -322,11 +328,21 @@ public abstract class BaseDeviceCommJob implements Job {
alarm.setfCreateTime(new Date());
alarmDataService.insertTEquipmentAlarmData(alarm);
} catch (Exception e) {
log.error("告警记录失败:{}", alarmData, e);
log.info("告警记录失败:{}", alarmData, e);
}
}
protected void recordAlarm(TStoreyInfo storeyInfo, String alarmData) {
recordAlarm(storeyInfo, storeyInfo != null ? storeyInfo.getfStoreyCode() : "unknown", alarmData);
protected void updateDeviceError(String ip) {
int deviceId = getDeviceId();
// 2. 查询数据库并校验(避免NPE)
PalletDeviceBinding palletDeviceBinding;
try {
palletDeviceBinding = palletDeviceBindingMapper.selectByTrayIdAndIndex(ip, deviceId);
if(palletDeviceBinding != null) {
palletDeviceBinding.setStatus("4");
}
} catch (Exception e) {
log.info("查询PalletDeviceBinding异常:ip={}, deviceId={}", ip, deviceId, e);
}
}
}
......@@ -21,8 +21,7 @@ public class DeviceComm501Device1Job extends BaseDeviceCommJob {
}
@Override
protected List<Integer> getDeviceIds() {
// 端口501对应的设备ID列表
return Collections.singletonList(1);
protected int getDeviceId() {
return 1;
}
}
......@@ -20,8 +20,7 @@ public class DeviceComm501Device2Job extends BaseDeviceCommJob {
}
@Override
protected List<Integer> getDeviceIds() {
// 端口501对应的设备ID列表
return Collections.singletonList(2);
protected int getDeviceId() {
return 2;
}
}
......@@ -20,8 +20,7 @@ public class DeviceComm501Device3Job extends BaseDeviceCommJob {
}
@Override
protected List<Integer> getDeviceIds() {
// 端口501对应的设备ID列表
return Collections.singletonList(3);
protected int getDeviceId() {
return 3;
}
}
package com.zehong.system.task.DeviceCommJob;
import com.zehong.system.task.BaseDeviceCommJob;
import org.springframework.stereotype.Component;
import java.util.Arrays;
import java.util.List;
/**
* @author lenovo
* @date 2025/9/25
* @description TODO
*/
@Component
public class DeviceComm501Job extends BaseDeviceCommJob {
@Override
protected int getFixedPort() {
return 501; // 固定端口501
}
@Override
protected List<Integer> getDeviceIds() {
// 端口501对应的设备ID列表
return Arrays.asList(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27);
}
}
package com.zehong.system.task.DeviceCommJob;
import com.zehong.system.task.BaseDeviceCommJob;
import org.springframework.stereotype.Component;
import java.util.Arrays;
import java.util.List;
/**
* @author lenovo
* @date 2025/9/25
* @description TODO
*/
@Component
public class DeviceComm502Job extends BaseDeviceCommJob {
@Override
protected int getFixedPort() {
return 502; // 固定端口502
}
@Override
protected List<Integer> getDeviceIds() {
// 端口502对应的设备ID列表
return Arrays.asList(28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54);
}
}
package com.zehong.system.task.DeviceCommJob;
import com.zehong.system.task.BaseDeviceCommJob;
import org.springframework.stereotype.Component;
import java.util.Arrays;
import java.util.List;
/**
* @author lenovo
* @date 2025/9/25
* @description TODO
*/
@Component
public class DeviceComm503Job extends BaseDeviceCommJob {
@Override
protected int getFixedPort() {
return 503; // 固定端口503
}
@Override
protected List<Integer> getDeviceIds() {
// 端口503对应的设备ID列表
return Arrays.asList(55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72);
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment