Commit b09d5a05 authored by wanghao's avatar wanghao

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

parent d22727dd
...@@ -148,13 +148,16 @@ public class ModbusResultHandler implements Consumer<DeviceStatusReaderDto> { ...@@ -148,13 +148,16 @@ public class ModbusResultHandler implements Consumer<DeviceStatusReaderDto> {
} catch (ModbusInitException e) { } catch (ModbusInitException e) {
log.error("Modbus初始化异常:ip={}, port={}", ip, port, e); log.error("Modbus初始化异常:ip={}, port={}", ip, port, e);
palletDeviceBinding.setStatus("5");
recordAlarm(palletDeviceBinding, "Modbus初始化失败:" + e.getMessage()); recordAlarm(palletDeviceBinding, "Modbus初始化失败:" + e.getMessage());
} catch (ModbusTransportException e) { } catch (ModbusTransportException e) {
log.error("Modbus传输异常:ip={}, port={}, deviceId={}", ip, port, deviceId, e); log.error("Modbus传输异常:ip={}, port={}, deviceId={}", ip, port, deviceId, e);
palletDeviceBinding.setStatus("5");
recordAlarm(palletDeviceBinding, "Modbus写时间失败:" + e.getMessage()); recordAlarm(palletDeviceBinding, "Modbus写时间失败:" + e.getMessage());
} catch (Exception e) { } catch (Exception e) {
// 捕获其他异常(如NPE、数据溢出) // 捕获其他异常(如NPE、数据溢出)
log.error("处理Modbus数据异常:ip={}, port={}, deviceId={}", ip, port, deviceId, e); log.error("处理Modbus数据异常:ip={}, port={}, deviceId={}", ip, port, deviceId, e);
palletDeviceBinding.setStatus("5");
recordAlarm(palletDeviceBinding, "数据处理异常:" + e.getMessage()); recordAlarm(palletDeviceBinding, "数据处理异常:" + e.getMessage());
} finally { } finally {
// 关键:关闭Modbus连接,避免资源泄漏 // 关键:关闭Modbus连接,避免资源泄漏
...@@ -300,7 +303,6 @@ public class ModbusResultHandler implements Consumer<DeviceStatusReaderDto> { ...@@ -300,7 +303,6 @@ public class ModbusResultHandler implements Consumer<DeviceStatusReaderDto> {
return str == null || str.trim().isEmpty(); return str == null || str.trim().isEmpty();
} }
} }
// 创建通用的停止条件(可选) // 创建通用的停止条件(可选)
public static Predicate<int[]> createDefaultStopCondition() { public static Predicate<int[]> createDefaultStopCondition() {
return values -> values.length >= 2 && values[1] == DeviceStatusReaderAndTimeSetter.TARGET_VALUE; return values -> values.length >= 2 && values[1] == DeviceStatusReaderAndTimeSetter.TARGET_VALUE;
......
package com.zehong.system.task; package com.zehong.system.task;
import org.quartz.Job;
import org.springframework.stereotype.Component;
import com.serotonin.modbus4j.ModbusFactory; import com.serotonin.modbus4j.ModbusFactory;
import com.serotonin.modbus4j.ModbusMaster; import com.serotonin.modbus4j.ModbusMaster;
import com.serotonin.modbus4j.exception.ModbusInitException; import com.serotonin.modbus4j.exception.ModbusInitException;
import com.serotonin.modbus4j.exception.ModbusTransportException; import com.serotonin.modbus4j.exception.ModbusTransportException;
import com.serotonin.modbus4j.ip.IpParameters; import com.serotonin.modbus4j.ip.IpParameters;
import com.serotonin.modbus4j.ip.tcp.TcpMaster; import com.serotonin.modbus4j.ip.tcp.TcpMaster;
import com.serotonin.modbus4j.msg.ModbusResponse;
import com.serotonin.modbus4j.msg.ReadHoldingRegistersRequest; import com.serotonin.modbus4j.msg.ReadHoldingRegistersRequest;
import com.serotonin.modbus4j.msg.ReadHoldingRegistersResponse; import com.serotonin.modbus4j.msg.ReadHoldingRegistersResponse;
import com.zehong.system.domain.PalletDeviceBinding;
import com.zehong.system.domain.TEquipmentAlarmData; import com.zehong.system.domain.TEquipmentAlarmData;
import com.zehong.system.domain.TStoreyInfo; import com.zehong.system.domain.TStoreyInfo;
import com.zehong.system.mapper.PalletDeviceBindingMapper;
import com.zehong.system.mapper.TStoreyInfoMapper; import com.zehong.system.mapper.TStoreyInfoMapper;
import com.zehong.system.modbus.handler.ModbusResultHandler; import com.zehong.system.modbus.handler.ModbusResultHandler;
import com.zehong.system.modbus.handler.dto.DeviceStatusReaderDto; import com.zehong.system.modbus.handler.dto.DeviceStatusReaderDto;
...@@ -32,8 +31,10 @@ import java.lang.reflect.Field; ...@@ -32,8 +31,10 @@ import java.lang.reflect.Field;
import java.net.Socket; import java.net.Socket;
import java.util.Date; import java.util.Date;
import java.util.List; import java.util.List;
import java.util.concurrent.*; import java.util.concurrent.ExecutorService;
import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.function.Predicate; import java.util.function.Predicate;
/** /**
* @author lenovo * @author lenovo
...@@ -44,15 +45,18 @@ import java.util.function.Predicate; ...@@ -44,15 +45,18 @@ import java.util.function.Predicate;
public abstract class BaseDeviceCommJob implements Job { public abstract class BaseDeviceCommJob implements Job {
private static final Logger log = LoggerFactory.getLogger(BaseDeviceCommJob.class); 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 SINGLE_DEVICE_TIMEOUT_SEC = 10; // 单个设备总超时
private static final int MODBUS_CONN_TIMEOUT_MS = 3000; // 连接超时:3秒 private static final int MODBUS_CONN_TIMEOUT_MS = 3000; // Modbus连接超时
private static final int CUSTOM_RETRY_TIMES = 1; // 自定义重试次数:1次 // 重试配置:单设备重试1次足够,避免过度占用连接
private static final int RETRY_DELAY_MS = 200; // 重试间隔:200ms 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_START_ADDR = 0;
private static final int REG_READ_COUNT = 10; private static final int REG_READ_COUNT = 10;
private static final ModbusFactory modbusFactory = new ModbusFactory(); // 单例工厂 // 单例Modbus工厂:避免重复创建开销
private static final ModbusFactory modbusFactory = new ModbusFactory();
// -------------------------- 公共依赖注入 -------------------------- // -------------------------- 公共依赖注入 --------------------------
@Resource @Resource
...@@ -62,6 +66,9 @@ public abstract class BaseDeviceCommJob implements Job { ...@@ -62,6 +66,9 @@ public abstract class BaseDeviceCommJob implements Job {
@Autowired @Autowired
protected ModbusResultHandler resultHandler; protected ModbusResultHandler resultHandler;
@Resource
private PalletDeviceBindingMapper palletDeviceBindingMapper;
// -------------------------- 抽象方法:子类实现差异化 -------------------------- // -------------------------- 抽象方法:子类实现差异化 --------------------------
/** /**
* 获取当前Job的固定端口号(501/502/503) * 获取当前Job的固定端口号(501/502/503)
...@@ -71,248 +78,247 @@ public abstract class BaseDeviceCommJob implements Job { ...@@ -71,248 +78,247 @@ public abstract class BaseDeviceCommJob implements Job {
/** /**
* 获取当前端口对应的设备ID列表 * 获取当前端口对应的设备ID列表
*/ */
protected abstract List<Integer> getDeviceIds(); protected abstract int getDeviceId();
// -------------------------- 核心执行逻辑(公共) -------------------------- // -------------------------- 核心执行逻辑(单设备直连,无冗余步骤) --------------------------
@Override @Override
public void execute(JobExecutionContext context) throws JobExecutionException { public void execute(JobExecutionContext context) {
long taskStartTime = System.currentTimeMillis(); long taskStartTime = System.currentTimeMillis();
String storeyIdStr = getStoreyIdFromContext(context); String storeyIdStr = getStoreyIdFromContext(context);
ExecutorService deviceExecutor = null; // 单设备场景:直接获取唯一deviceId(子类返回的List仅1个元素)
Integer deviceId = getSingleDeviceId();
TStoreyInfo storeyInfo = null;
try { try {
// 1. 初始化线程池(单个端口设备数较少,核心线程数设为5) log.info("单设备任务开始:port={}, deviceId={}, storeyId={}",
deviceExecutor = new ThreadPoolExecutor( getFixedPort(), deviceId, storeyIdStr);
5, 5,
0, TimeUnit.SECONDS,
new LinkedBlockingQueue<>(30),
r -> new Thread(r, "modbus-port-" + getFixedPort() + "-" + storeyIdStr),
new ThreadPoolExecutor.AbortPolicy()
);
// 2. 执行当前端口的设备通信(带总超时 // 1. 校验基础参数(设备信息、IP、端口
executePortDevices(context, deviceExecutor, taskStartTime, storeyIdStr); storeyInfo = validateBaseParams(storeyIdStr);
log.info("端口[{}]通信任务执行成功:fStoreyId={},总耗时={}ms", if(storeyInfo == null) {
getFixedPort(), storeyIdStr, System.currentTimeMillis() - taskStartTime); log.info("设备不存在:fStoreyId={}", storeyIdStr);
return;
}
String deviceIp = storeyInfo.getfIp();
int port = getFixedPort();
} catch (Throwable e) { // 2. 执行单设备Modbus通信(带超时+重试)
String errMsg = "端口[" + getFixedPort() + "]通信任务异常:fStoreyId=" + storeyIdStr; int[] modbusResult = executeModbusWithTimeout(deviceIp, port, deviceId);
log.error(errMsg, e);
recordAlarm(null, storeyIdStr, errMsg + ":" + e.getMessage()); // 3. 处理Modbus结果(非必须,为空则跳过)
throw new JobExecutionException(errMsg, e); // 抛出让Quartz感知,不隐藏异常 if (resultHandler != null && modbusResult != null) {
} finally { resultHandler.accept(new DeviceStatusReaderDto(deviceIp, port, deviceId, modbusResult));
// 3. 强制关闭线程池,避免资源泄漏 } else {
if (deviceExecutor != null && !deviceExecutor.isShutdown()) { updateDeviceError(storeyInfo.getfIp());
deviceExecutor.shutdownNow();
try {
if (!deviceExecutor.awaitTermination(5, TimeUnit.SECONDS)) {
log.warn("端口[{}]线程池关闭超时:fStoreyId={}", getFixedPort(), storeyIdStr);
}
} catch (InterruptedException e) {
log.warn("端口[{}]线程池关闭被中断:fStoreyId={}", getFixedPort(), storeyIdStr);
}
} }
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, private Integer getSingleDeviceId() {
long taskStartTime, String storeyIdStr) throws Exception { return getDeviceId();
// 校验设备信息
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);
}
} }
// -------------------------- 以下为原DeviceCommunicationJob的公共工具方法 -------------------------- /**
protected TStoreyInfo validateAndGetStoreyInfo(String storeyIdStr) { * 校验基础参数(storeyId、设备信息、IP),失败直接抛异常
if (StringUtils.isBlank(storeyIdStr)) { */
String errMsg = "fStoreyId为空:端口[" + getFixedPort() + "]"; private TStoreyInfo validateBaseParams(String storeyIdStr) {
log.error(errMsg); // 1. 校验storeyId格式
recordAlarm(null, "unknown", errMsg); if (StringUtils.isBlank(storeyIdStr)) {
throw new RuntimeException(errMsg); log.info("storeyId为空:port=" + getFixedPort());
} }
Long storeyId = parseStoreyId(storeyIdStr);
Long storeyId; if(storeyId == null) {
try { log.info("storeyId格式错误:port=" + getFixedPort());
storeyId = Long.parseLong(storeyIdStr); return null;
} catch (NumberFormatException e) {
String errMsg = "fStoreyId格式错误:" + storeyIdStr + ",端口[" + getFixedPort() + "]";
log.error(errMsg);
recordAlarm(null, storeyIdStr, errMsg);
throw new RuntimeException(errMsg);
} }
// 2. 校验设备信息和IP
TStoreyInfo storeyInfo = tStoreyInfoMapper.selectTStoreyInfoById(storeyId); TStoreyInfo storeyInfo = tStoreyInfoMapper.selectTStoreyInfoById(storeyId);
if (storeyInfo == null || StringUtils.isBlank(storeyInfo.getfIp())) { if (storeyInfo == null || StringUtils.isBlank(storeyInfo.getfIp())) {
String errMsg = "设备信息无效:fStoreyId=" + storeyId + ",端口[" + getFixedPort() + "]"; log.info("设备信息无效:storeyId="+storeyId);
log.error(errMsg);
recordAlarm(null, storeyIdStr, errMsg);
throw new RuntimeException(errMsg);
} }
return storeyInfo; return storeyInfo;
} }
protected void executeSingleDeviceWithTimeout(String ip, int port, int deviceId, String storeyIdStr) { /**
Future<?> deviceFuture = Executors.newSingleThreadExecutor().submit(() -> { * 解析storeyId(单独抽离,减少代码冗余)
try { */
int[] result = readDeviceWithRetry(ip, port, deviceId, storeyIdStr); private Long parseStoreyId(String storeyIdStr) {
if (resultHandler != null) { try {
resultHandler.accept(new DeviceStatusReaderDto(ip, port, deviceId, result)); return Long.parseLong(storeyIdStr);
} } catch (NumberFormatException e) {
} catch (Exception e) { log.info("设备信息无效:storeyId="+storeyIdStr);
throw new RuntimeException("设备[" + deviceId + "]读取失败", e); }
} return null;
}); }
/**
* 单设备Modbus通信(带超时+重试,无线程池,用Future做超时控制)
*/
private int[] executeModbusWithTimeout(String ip, int port, int deviceId) throws Exception {
// 用单线程池做超时控制(比自定义线程更轻量,执行完自动销毁)
ExecutorService singleExecutor = Executors.newSingleThreadExecutor();
try { try {
deviceFuture.get(SINGLE_DEVICE_TIMEOUT_SEC, TimeUnit.SECONDS); Future<int[]> future = singleExecutor.submit(() ->
} catch (TimeoutException e) { readModbusWithRetry(ip, port, deviceId)
deviceFuture.cancel(true); );
throw new RuntimeException("设备[" + deviceId + "]通信超时(>" + SINGLE_DEVICE_TIMEOUT_SEC + "秒)"); // 超时控制:超过SINGLE_DEVICE_TIMEOUT_SEC秒直接中断
} catch (Exception e) { return future.get(SINGLE_DEVICE_TIMEOUT_SEC, TimeUnit.SECONDS);
throw new RuntimeException("设备[" + deviceId + "]通信异常", e.getCause()); } 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; ModbusMaster master = null;
int[] result = null;
for (int retry = 0; retry <= CUSTOM_RETRY_TIMES; retry++) { for (int retry = 0; retry <= CUSTOM_RETRY_TIMES; retry++) {
try { try {
// 1. 创建Modbus连接(禁用内置重试,避免冲突)
master = createModbusMaster(ip, port); master = createModbusMaster(ip, port);
result = readDeviceRegisters(master, deviceId); // 2. 读取寄存器
Predicate<int[]> stopCondition = ModbusResultHandler.createDefaultStopCondition(); int[] result = readRegisters(master, deviceId);
if (stopCondition.test(result)) { // 3. 校验结果(满足停止条件则返回,否则重试)
log.debug("端口[{}]设备[{}]读取成功:重试={},fStoreyId={}", if (isValidResult(result)) {
port, deviceId, retry, storeyIdStr); log.info("Modbus读取成功:retry={}, port={}, deviceId={}", retry, port, deviceId);
break; return result;
} else if (retry < CUSTOM_RETRY_TIMES) {
Thread.sleep(RETRY_DELAY_MS);
} }
log.info("Modbus结果不满足条件,重试:retry={}, port={}, deviceId={}", retry, port, deviceId);
} catch (Exception e) { } catch (Exception e) {
// 重试耗尽才抛异常
if (retry >= CUSTOM_RETRY_TIMES) { if (retry >= CUSTOM_RETRY_TIMES) {
log.error("端口[{}]设备[{}]重试耗尽({}次):fStoreyId={}", throw new RuntimeException(String.format("Modbus重试耗尽(%d次):ip=%s, port=%d, deviceId=%d",
port, deviceId, CUSTOM_RETRY_TIMES, storeyIdStr, e); CUSTOM_RETRY_TIMES, ip, port, deviceId), e);
throw e;
} }
Thread.sleep(RETRY_DELAY_MS); log.info("Modbus读取异常,重试:retry={}, port={}, deviceId={}", retry, port, deviceId, e);
} finally { } finally {
// 每次重试后销毁连接(关键:避免单设备场景下的连接泄漏)
destroyModbusMaster(master, deviceId); 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(); IpParameters params = new IpParameters();
params.setHost(ip); params.setHost(ip);
params.setPort(port); params.setPort(port);
TcpMaster master = (TcpMaster) modbusFactory.createTcpMaster(params, true); TcpMaster master = (TcpMaster) modbusFactory.createTcpMaster(params, true);
master.setTimeout(MODBUS_CONN_TIMEOUT_MS); master.setTimeout(MODBUS_CONN_TIMEOUT_MS);
master.setRetries(0); // 禁用内置重试,用自定义重试 master.setRetries(0); // 禁用内置重试,用自定义重试逻辑
master.init(); master.init();
return master; return master;
} }
protected int[] readDeviceRegisters(ModbusMaster master, int deviceId) throws ModbusTransportException { /**
* 读取寄存器(无冗余判断,直接强转)
*/
private int[] readRegisters(ModbusMaster master, int deviceId) throws ModbusTransportException {
ReadHoldingRegistersRequest request = Modbus4jUtils.getReadHoldingRegistersRequest( ReadHoldingRegistersRequest request = Modbus4jUtils.getReadHoldingRegistersRequest(
deviceId, REG_START_ADDR, REG_READ_COUNT); deviceId, REG_START_ADDR, REG_READ_COUNT);
ModbusResponse response = master.send(request); ReadHoldingRegistersResponse response = (ReadHoldingRegistersResponse) master.send(request);
if (!(response instanceof ReadHoldingRegistersResponse)) {
throw new RuntimeException("无效Modbus响应:设备[" + deviceId + "]"); // 转换为无符号整数(单设备场景无需循环优化,直接遍历)
} short[] signedVals = response.getShortData();
short[] signedVals = ((ReadHoldingRegistersResponse) response).getShortData();
int[] unsignedVals = new int[signedVals.length]; int[] unsignedVals = new int[signedVals.length];
for (int i = 0; i < signedVals.length; i++) { for (int i = 0; i < signedVals.length; i++) {
unsignedVals[i] = signedVals[i] & 0xFFFF; // 转无符号整数 unsignedVals[i] = signedVals[i] & 0xFFFF;
} }
return unsignedVals; return unsignedVals;
} }
protected void destroyModbusMaster(ModbusMaster master, int deviceId) { /**
* 销毁Modbus连接(精简反射逻辑,失败仅日志告警,不中断主流程)
*/
private void destroyModbusMaster(ModbusMaster master, int deviceId) {
if (master == null) return; if (master == null) return;
// 1. 关闭底层Socket(反射失败不抛异常,避免影响主流程)
if (master instanceof TcpMaster) {
closeSocket((TcpMaster) master, deviceId);
}
// 2. 销毁Master
try { try {
if (master instanceof TcpMaster) { master.destroy();
Socket socket = getUnderlyingSocket((TcpMaster) master);
if (socket != null && !socket.isClosed()) {
socket.close();
}
}
} catch (Exception e) { } catch (Exception e) {
log.error("设备[{}]Socket销毁异常", deviceId, e); log.info("ModbusMaster销毁异常:deviceId={}", deviceId, e);
} finally {
try {
master.destroy();
} catch (Exception e) {
log.error("设备[{}]ModbusMaster销毁异常", deviceId, e);
}
} }
} }
private Socket getUnderlyingSocket(TcpMaster tcpMaster) { /**
* 关闭底层Socket(精简反射代码,减少异常处理层级)
*/
private void closeSocket(TcpMaster tcpMaster, int deviceId) {
try { try {
Field socketField = TcpMaster.class.getDeclaredField("socket"); Field socketField = TcpMaster.class.getDeclaredField("socket");
socketField.setAccessible(true); socketField.setAccessible(true);
return (Socket) socketField.get(tcpMaster); Socket socket = (Socket) socketField.get(tcpMaster);
if (socket != null && !socket.isClosed()) {
socket.close();
}
} catch (Exception e) { } catch (Exception e) {
log.warn("反射获取Socket失败:TcpMaster版本不匹配", e); log.info("Modbus Socket关闭异常:deviceId={}", deviceId, e);
return null; }
}
// -------------------------- 保留的基础工具方法(仅核心) --------------------------
/**
* 校验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 { try {
return context.getJobDetail().getJobDataMap().getString("fStoreyId"); return context.getJobDetail().getJobDataMap().getString("fStoreyId");
} catch (Exception e) { } catch (Exception e) {
log.error("获取fStoreyId失败", e); log.info("获取storeyId失败", e);
return "unknown"; return "unknown";
} }
} }
/**
* 记录告警(保留原逻辑,精简参数判断)
*/
protected void recordAlarm(TStoreyInfo storeyInfo, String equipmentCode, String alarmData) { protected void recordAlarm(TStoreyInfo storeyInfo, String equipmentCode, String alarmData) {
try { try {
TEquipmentAlarmData alarm = new TEquipmentAlarmData(); TEquipmentAlarmData alarm = new TEquipmentAlarmData();
...@@ -322,11 +328,21 @@ public abstract class BaseDeviceCommJob implements Job { ...@@ -322,11 +328,21 @@ public abstract class BaseDeviceCommJob implements Job {
alarm.setfCreateTime(new Date()); alarm.setfCreateTime(new Date());
alarmDataService.insertTEquipmentAlarmData(alarm); alarmDataService.insertTEquipmentAlarmData(alarm);
} catch (Exception e) { } catch (Exception e) {
log.error("告警记录失败:{}", alarmData, e); log.info("告警记录失败:{}", alarmData, e);
} }
} }
protected void recordAlarm(TStoreyInfo storeyInfo, String alarmData) { protected void updateDeviceError(String ip) {
recordAlarm(storeyInfo, storeyInfo != null ? storeyInfo.getfStoreyCode() : "unknown", alarmData); 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 { ...@@ -21,8 +21,7 @@ public class DeviceComm501Device1Job extends BaseDeviceCommJob {
} }
@Override @Override
protected List<Integer> getDeviceIds() { protected int getDeviceId() {
// 端口501对应的设备ID列表 return 1;
return Collections.singletonList(1);
} }
} }
...@@ -20,8 +20,7 @@ public class DeviceComm501Device2Job extends BaseDeviceCommJob { ...@@ -20,8 +20,7 @@ public class DeviceComm501Device2Job extends BaseDeviceCommJob {
} }
@Override @Override
protected List<Integer> getDeviceIds() { protected int getDeviceId() {
// 端口501对应的设备ID列表 return 2;
return Collections.singletonList(2);
} }
} }
...@@ -20,8 +20,7 @@ public class DeviceComm501Device3Job extends BaseDeviceCommJob { ...@@ -20,8 +20,7 @@ public class DeviceComm501Device3Job extends BaseDeviceCommJob {
} }
@Override @Override
protected List<Integer> getDeviceIds() { protected int getDeviceId() {
// 端口501对应的设备ID列表 return 3;
return Collections.singletonList(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