Commit 79410fee authored by wanghao's avatar wanghao

1 点数数据表 增加 继电器状态 等五个字段 DDL维护。

2 点位数据vo及历史记录vo 及mapper增加 继电器状态 等五个字段。
3 老化最终流程 执行 读取 继电器状态  等5个状态的 操作,待跟硬件对接。
parent 98287cc1
......@@ -22,4 +22,21 @@ http://36.138.180.82:8087/mes/pcba/devices/acceptAgingCalibrationResults
"recordHour":"13",
"recordMinute":"14"
}
]
\ No newline at end of file
]
ALTER TABLE `t_pallet_device_binding`
ADD COLUMN `f_write_self_check_status` INT(16) DEFAULT NULL COMMENT '写入自检状态(可以是空,0-失败,1-成功)',
ADD COLUMN `f_relay_status` INT(16) DEFAULT NULL COMMENT '继电器状态(0-初始,1-动作)',
ADD COLUMN `f_pulse_status` INT(16) DEFAULT NULL COMMENT '脉冲状态(0-初始,1-动作)',
ADD COLUMN `f_module_status` INT(16) DEFAULT NULL COMMENT '模组状态(0-异常,1-正常)',
ADD COLUMN `f_sim_card_status` INT(16) DEFAULT NULL COMMENT 'SIM卡状态(0-异常,1-正常)',
ADD COLUMN `f_network_status` INT(16) DEFAULT NULL COMMENT '网络状态(0-异常,1-正常)';
ALTER TABLE `t_pallet_device_upload_history`
ADD COLUMN `f_write_self_check_status` INT(16) DEFAULT NULL COMMENT '写入自检状态(可以是空,0-失败,1-成功)',
ADD COLUMN `f_relay_status` INT(16) DEFAULT NULL COMMENT '继电器状态(0-初始,1-动作)',
ADD COLUMN `f_pulse_status` INT(16) DEFAULT NULL COMMENT '脉冲状态(0-初始,1-动作)',
ADD COLUMN `f_module_status` INT(16) DEFAULT NULL COMMENT '模组状态(0-异常,1-正常)',
ADD COLUMN `f_sim_card_status` INT(16) DEFAULT NULL COMMENT 'SIM卡状态(0-异常,1-正常)',
ADD COLUMN `f_network_status` INT(16) DEFAULT NULL COMMENT '网络状态(0-异常,1-正常)';
\ No newline at end of file
......@@ -98,6 +98,35 @@ public class MesDeviceDomain extends BaseEntity {
*/
private String calibrationConcentrationStatus;
/**
* 写自检状态 空 是没写 0-失败;1-成功
*/
private Integer writeSelfCheckStatus;
/**
* 继电器状态 0:初始 1:动作
*/
private Integer relayStatus;
/**
* 脉冲状态 0:初始 1:动作
*/
private Integer pulseStatus;
/**
* 模块状态 0:异常 1:正常
*/
private Integer moduleStatus;
/**
* SIM卡状态 0:异常 1:正常
*/
private Integer simCardStatus;
/**
* 网络状态 0:异常 1:正常
*/
private Integer networkStatus;
public String getMotherboardCode() {
return motherboardCode;
}
......@@ -241,4 +270,52 @@ public class MesDeviceDomain extends BaseEntity {
public void setRunTimeStatus(String runTimeStatus) {
this.runTimeStatus = runTimeStatus;
}
public Integer getWriteSelfCheckStatus() {
return writeSelfCheckStatus;
}
public void setWriteSelfCheckStatus(Integer writeSelfCheckStatus) {
this.writeSelfCheckStatus = writeSelfCheckStatus;
}
public Integer getRelayStatus() {
return relayStatus;
}
public void setRelayStatus(Integer relayStatus) {
this.relayStatus = relayStatus;
}
public Integer getPulseStatus() {
return pulseStatus;
}
public void setPulseStatus(Integer pulseStatus) {
this.pulseStatus = pulseStatus;
}
public Integer getModuleStatus() {
return moduleStatus;
}
public void setModuleStatus(Integer moduleStatus) {
this.moduleStatus = moduleStatus;
}
public Integer getSimCardStatus() {
return simCardStatus;
}
public void setSimCardStatus(Integer simCardStatus) {
this.simCardStatus = simCardStatus;
}
public Integer getNetworkStatus() {
return networkStatus;
}
public void setNetworkStatus(Integer networkStatus) {
this.networkStatus = networkStatus;
}
}
......@@ -146,6 +146,37 @@ public class PalletDeviceBinding extends BaseEntity
* 0-预热;1-正常;3-传感器故障;4-报警;5-通讯故障; 只有是4的时候显示正常,其他的都是异常
*/
private String calibrationConcentrationStatus;
/**
* 写自检状态 空 是没写 0-失败;1-成功
*/
private Integer writeSelfCheckStatus;
/**
* 继电器状态 0:初始 1:动作
*/
private Integer relayStatus;
/**
* 脉冲状态 0:初始 1:动作
*/
private Integer pulseStatus;
/**
* 模块状态 0:异常 1:正常
*/
private Integer moduleStatus;
/**
* SIM卡状态 0:异常 1:正常
*/
private Integer simCardStatus;
/**
* 网络状态 0:异常 1:正常
*/
private Integer networkStatus;
public String getStatus() {
return status;
}
......@@ -370,17 +401,94 @@ public class PalletDeviceBinding extends BaseEntity
this.calibrationConcentrationStatus = calibrationConcentrationStatus;
}
public Integer getWriteSelfCheckStatus() {
return writeSelfCheckStatus;
}
public void setWriteSelfCheckStatus(Integer writeSelfCheckStatus) {
this.writeSelfCheckStatus = writeSelfCheckStatus;
}
public Integer getRelayStatus() {
return relayStatus;
}
public void setRelayStatus(Integer relayStatus) {
this.relayStatus = relayStatus;
}
public Integer getPulseStatus() {
return pulseStatus;
}
public void setPulseStatus(Integer pulseStatus) {
this.pulseStatus = pulseStatus;
}
public Integer getModuleStatus() {
return moduleStatus;
}
public void setModuleStatus(Integer moduleStatus) {
this.moduleStatus = moduleStatus;
}
public Integer getSimCardStatus() {
return simCardStatus;
}
public void setSimCardStatus(Integer simCardStatus) {
this.simCardStatus = simCardStatus;
}
public Integer getNetworkStatus() {
return networkStatus;
}
public void setNetworkStatus(Integer networkStatus) {
this.networkStatus = networkStatus;
}
@Override
public String toString() {
return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
.append("palletDeviceBindingId", getPalletDeviceBindingId())
.append("trayId", getTrayId())
.append("deviceCode", getDeviceCode())
.append("row", getRow())
.append("col", getCol())
.append("bindingTime", getBindingTime())
.append("unbindingTime", getUnbindingTime())
.append("createTime", getCreateTime())
.toString();
return new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE)
.append("palletDeviceBindingId", getPalletDeviceBindingId())
.append("trayId", getTrayId())
.append("fTrayCode", getfTrayCode())
.append("deviceCode", getDeviceCode())
.append("row", getRow())
.append("col", getCol())
.append("index", getIndex())
.append("number", getNumber())
.append("bindingTime", getBindingTime())
.append("unbindingTime", getUnbindingTime())
.append("status", getStatus())
.append("recordYear", getRecordYear())
.append("recordMonth", getRecordMonth())
.append("recordDate", getRecordDate())
.append("recordHour", getRecordHour())
.append("recordMinute", getRecordMinute())
.append("writeTimeStatus", getWriteTimeStatus())
.append("adjustmentZeroAd", getAdjustmentZeroAd())
.append("zeroStatus", getZeroStatus())
.append("calibrationAd", getCalibrationAd())
.append("calibrationAdStatus", getCalibrationAdStatus())
.append("concentration", getConcentration())
.append("runTimeStatus", getRunTimeStatus())
.append("realTimeAd", getRealTimeAd())
.append("realTimeStatus", getRealTimeStatus())
.append("calibrationConcentration", getCalibrationConcentration())
.append("calibrationConcentrationStatus", getCalibrationConcentrationStatus())
.append("writeSelfCheckStatus", getWriteSelfCheckStatus())
.append("relayStatus", getRelayStatus())
.append("pulseStatus", getPulseStatus())
.append("moduleStatus", getModuleStatus())
.append("simCardStatus", getSimCardStatus())
.append("networkStatus", getNetworkStatus())
.append("createTime", getCreateTime())
.append("updateTime", getUpdateTime())
.append("createBy", getCreateBy())
.append("updateBy", getUpdateBy())
.toString();
}
}
......@@ -128,6 +128,36 @@ public class PalletDeviceUploadHistory extends BaseEntity
* 0-预热;1-正常;3-传感器故障;4-报警;5-通讯故障; 只有是4的时候显示正常,其他的都是异常
*/
private String calibrationConcentrationStatus;
/**
* 写自检状态 空 是没写 0-失败;1-成功
*/
private Integer writeSelfCheckStatus;
/**
* 继电器状态 0:初始 1:动作
*/
private Integer relayStatus;
/**
* 脉冲状态 0:初始 1:动作
*/
private Integer pulseStatus;
/**
* 模块状态 0:异常 1:正常
*/
private Integer moduleStatus;
/**
* SIM卡状态 0:异常 1:正常
*/
private Integer simCardStatus;
/**
* 网络状态 0:异常 1:正常
*/
private Integer networkStatus;
public void setId(Long id)
{
this.id = id;
......@@ -369,34 +399,90 @@ public class PalletDeviceUploadHistory extends BaseEntity
this.calibrationConcentrationStatus = calibrationConcentrationStatus;
}
public Integer getWriteSelfCheckStatus() {
return writeSelfCheckStatus;
}
public void setWriteSelfCheckStatus(Integer writeSelfCheckStatus) {
this.writeSelfCheckStatus = writeSelfCheckStatus;
}
public Integer getRelayStatus() {
return relayStatus;
}
public void setRelayStatus(Integer relayStatus) {
this.relayStatus = relayStatus;
}
public Integer getPulseStatus() {
return pulseStatus;
}
public void setPulseStatus(Integer pulseStatus) {
this.pulseStatus = pulseStatus;
}
public Integer getModuleStatus() {
return moduleStatus;
}
public void setModuleStatus(Integer moduleStatus) {
this.moduleStatus = moduleStatus;
}
public Integer getSimCardStatus() {
return simCardStatus;
}
public void setSimCardStatus(Integer simCardStatus) {
this.simCardStatus = simCardStatus;
}
public Integer getNetworkStatus() {
return networkStatus;
}
public void setNetworkStatus(Integer networkStatus) {
this.networkStatus = networkStatus;
}
@Override
public String toString() {
return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
.append("id", getId())
.append("trayId", getTrayId())
.append("deviceCode", getDeviceCode())
.append("row", getRow())
.append("col", getCol())
.append("index", getIndex())
.append("number", getNumber())
.append("bindingTime", getBindingTime())
.append("unbindingTime", getUnbindingTime())
.append("createTime", getCreateTime())
.append("status", getStatus())
.append("recordYear", getRecordYear())
.append("recordMonth", getRecordMonth())
.append("recordDate", getRecordDate())
.append("recordHour", getRecordHour())
.append("recordMinute", getRecordMinute())
.append("writeTimeStatus", getWriteTimeStatus())
.append("adjustmentZeroAd", getAdjustmentZeroAd())
.append("zeroStatus", getZeroStatus())
.append("calibrationAd", getCalibrationAd())
.append("calibrationStatus", getCalibrationStatus())
.append("concentration", getConcentration())
.append("runTimeStatus", getRunTimeStatus())
.append("realTimeAd", getRealTimeAd())
.append("realTimeAdStatus", getRealTimeAdStatus())
.toString();
return "PalletDeviceUploadHistory{" +
"id=" + id +
", trayId=" + trayId +
", trayCode='" + trayCode + '\'' +
", deviceCode='" + deviceCode + '\'' +
", row=" + row +
", col=" + col +
", index=" + index +
", number=" + number +
", bindingTime=" + bindingTime +
", unbindingTime=" + unbindingTime +
", status='" + status + '\'' +
", recordYear='" + recordYear + '\'' +
", recordMonth='" + recordMonth + '\'' +
", recordDate='" + recordDate + '\'' +
", recordHour='" + recordHour + '\'' +
", recordMinute='" + recordMinute + '\'' +
", writeTimeStatus='" + writeTimeStatus + '\'' +
", adjustmentZeroAd='" + adjustmentZeroAd + '\'' +
", zeroStatus='" + zeroStatus + '\'' +
", calibrationAd='" + calibrationAd + '\'' +
", calibrationStatus='" + calibrationStatus + '\'' +
", concentration='" + concentration + '\'' +
", runTimeStatus='" + runTimeStatus + '\'' +
", realTimeAd=" + realTimeAd +
", realTimeAdStatus='" + realTimeAdStatus + '\'' +
", calibrationConcentration=" + calibrationConcentration +
", calibrationConcentrationStatus='" + calibrationConcentrationStatus + '\'' +
", writeSelfCheckStatus=" + writeSelfCheckStatus +
", relayStatus=" + relayStatus +
", pulseStatus=" + pulseStatus +
", moduleStatus=" + moduleStatus +
", simCardStatus=" + simCardStatus +
", networkStatus=" + networkStatus +
'}';
}
}
......@@ -54,8 +54,6 @@ public interface PalletDeviceBindingMapper
*/
public int insertPalletDeviceBinding(PalletDeviceBinding palletDeviceBinding);
public int resetAll(Long trayId);
public int deleteAllByTrayId(Long trayId);
public int batchInsertPalletDeviceBinding(@Param("palletDeviceBindingList") List<PalletDeviceBinding> palletDeviceBindingList);
......@@ -72,6 +70,8 @@ public interface PalletDeviceBindingMapper
public int unbindDevice(Long palletDeviceBindingId);
public int resetAll(Long trayId);
public int batchUpdateDeviceCode(@Param("palletDeviceBindingList") List<PalletDeviceBinding> palletDeviceBindingList);
public int batchUpdateAdAndStatus(@Param("palletDeviceBindingList") List<PalletDeviceBinding> palletDeviceBindingList);
......
......@@ -9,9 +9,10 @@ import com.serotonin.modbus4j.exception.ErrorResponseException;
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.locator.BaseLocator;
import com.serotonin.modbus4j.msg.*;
import com.zehong.system.domain.PalletDeviceBinding;
import com.zehong.system.modbus.handler.ModbusResultHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
......@@ -35,6 +36,9 @@ public class Modbus4jUtils {
private static final int MAX_RETRIES = 3; // 最大重试次数
private static final int RETRY_DELAY = 500; // 重试延迟(ms)// 监控参数
private static final int MONITOR_INTERVAL = 5000; // 监控间隔(ms)
// Modbus配置:取消内置重试,统一用自定义重试
private static final int MODBUS_CONN_TIMEOUT_MS = 3000; // 连接超时:3秒
private static final int CUSTOM_RETRY_TIMES = 2; // 自定义重试次数:1次
// 监控控制标志
private static final AtomicBoolean monitoring = new AtomicBoolean(false);
......@@ -48,7 +52,6 @@ public class Modbus4jUtils {
modbusFactory = new ModbusFactory();
}
}
/**
* 获取master
*
......@@ -73,24 +76,34 @@ public class Modbus4jUtils {
return master;
}
// -------------------------- Modbus工具方法(显式抛出异常)--------------------------
/**
* 动态获取 modubus master
* @param ip ip
* @param port port
* @return r
* @throws ModbusInitException m
* 创建Modbus连接(取消内置重试,统一自定义重试)
*/
public static ModbusMaster getMaster(String ip, int port) throws ModbusInitException {
public static ModbusMaster createModbusMaster(String ip, int port) throws ModbusInitException {
IpParameters params = new IpParameters();
params.setHost(ip);
params.setPort(port);
ModbusMaster master = modbusFactory.createTcpMaster(params, false);// TCP 协议
master.setTimeout(3000); // 设置超时时间
master.setRetries(3); // 设置重试次数
TcpMaster master = (TcpMaster) modbusFactory.createTcpMaster(params, true);
master.setTimeout(MODBUS_CONN_TIMEOUT_MS);
master.setRetries(0);
master.init();
return master;
}
/**
* 销毁Modbus连接(反射失败直接抛出异常,显式暴露问题)
*/
public static void destroyModbusMaster(ModbusMaster master, int deviceId) {
if (master != null) {
try {
master.destroy();
} catch (Exception e) {
log.debug("设备{}: ModbusMaster销毁异常", deviceId, e);
}
}
}
/**
* 读取[01 Coil Status 0x]类型 开关数据
*
......@@ -180,7 +193,7 @@ public class Modbus4jUtils {
ModbusMaster master = null;
try {
master = getMaster("192.168.1.11", 503);
master = createModbusMaster("192.168.1.11", 503);
boolean[] booleans = readDiscreteInputs(master, 1, 0, 2);
if(master != null) {
......@@ -208,7 +221,7 @@ public class Modbus4jUtils {
public static boolean[] getRoboticArmExitConveyorData(String ip, int port) {
ModbusMaster master = null;
try {
master = getMaster(ip, port);
master = createModbusMaster(ip, port);
boolean[] booleans = readDiscreteInputs(master, 1, 0, 2);
if(master != null) {
......@@ -778,7 +791,7 @@ public class Modbus4jUtils {
ModbusMaster modbusMaster = null;
try {
// 读取 第1个 pcba 板子的数据
modbusMaster = getMaster("192.168.2.1", 501);
modbusMaster = createModbusMaster("192.168.2.1", 501);
writeCurrentTimeToDevice(modbusMaster, 1);
} catch (Exception e) {
e.printStackTrace();
......@@ -820,6 +833,64 @@ public class Modbus4jUtils {
}
}
/**
* 带重试的设备读取
*/
public static int[] readDeviceWithRetry(String ip, int port, int deviceId) {
ModbusMaster master = null;
int[] lastResult = null; // 用于记录最后一次读取的结果(无论是否满足停止条件)
try {
// 只创建一次ModbusMaster,循环内复用
master = Modbus4jUtils.createModbusMaster(ip, port);
for (int retry = 0; retry <= CUSTOM_RETRY_TIMES; retry++) {
try {
// 执行读取操作,获取本次结果
int[] currentResult = readDeviceRegisters(master, deviceId);
// 更新最后一次结果(无论是否满足停止条件,都记录)
lastResult = currentResult;
// 检查停止条件,如果满足则提前返回(无需等到重试耗尽)
if (ModbusResultHandler.createDefaultStopCondition().test(currentResult)) {
log.info("设备{}第{}次读取成功(满足条件): ip={}, port={}",
deviceId, retry + 1, ip, port);
return currentResult;
}
// 未满足条件且不是最后一次重试,休眠后继续
if (retry < CUSTOM_RETRY_TIMES) {
log.info("设备{}第{}次读取未满足条件,准备重试: ip={}, port={}",
deviceId, retry + 1, ip, port);
Thread.sleep(200);
}
} catch (Exception e) {
// 本次读取发生异常,记录日志但不中断重试(继续下一次)
log.warn("设备{}第{}次读取发生异常: ip={}, port={}",
deviceId, retry + 1, ip, port, e);
// 如果是最后一次重试,异常时lastResult可能为null(需后续处理)
}
}
// 循环结束(重试耗尽),此时lastResult为最后一次的结果(可能是正常读取但不满足条件,或null)
log.info("设备{}重试次数耗尽,返回最后一次结果: ip={}, port={}",
deviceId, ip, port);
} catch (Exception e) {
// 捕获创建ModbusMaster或休眠时的异常(非读取操作的异常)
log.error("设备{}连接创建或休眠失败: ip={}, port={}",
deviceId, ip, port, e);
throw new RuntimeException("设备连接或操作异常", e);
} finally {
// 无论结果如何,最终销毁连接
destroyModbusMaster(master, deviceId);
}
// 处理最后一次结果可能为null的情况(例如所有重试都异常)
if (lastResult == null) {
throw new RuntimeException("设备所有读取尝试均失败(无有效结果)");
}
return lastResult;
}
/**
* 读取设备寄存器(线程安全版)
*/
......
......@@ -117,6 +117,13 @@ public class CalibrationResultEventHandler {
mesDeviceDomain.setRecordDate(palletDeviceBinding.getRecordDate());
mesDeviceDomain.setRecordHour(palletDeviceBinding.getRecordHour());
mesDeviceDomain.setRecordMinute(palletDeviceBinding.getRecordMinute());
// 写入自检状态 继电器状态 脉冲状态 模块状态 SIM状态 网络状态
mesDeviceDomain.setWriteSelfCheckStatus(palletDeviceBinding.getWriteSelfCheckStatus());
mesDeviceDomain.setRelayStatus(palletDeviceBinding.getRelayStatus());
mesDeviceDomain.setPulseStatus(palletDeviceBinding.getPulseStatus());
mesDeviceDomain.setModuleStatus(palletDeviceBinding.getModuleStatus());
mesDeviceDomain.setSimCardStatus(palletDeviceBinding.getSimCardStatus());
mesDeviceDomain.setNetworkStatus(palletDeviceBinding.getNetworkStatus());
mesDeviceDomains.add(mesDeviceDomain);
}
......@@ -437,6 +444,14 @@ public class CalibrationResultEventHandler {
history.setCalibrationConcentration(binding.getCalibrationConcentration());
history.setCalibrationConcentrationStatus(binding.getCalibrationConcentrationStatus());
// 写入自检状态 继电器状态 脉冲状态 模组状态 SIM卡状态 网络状态
history.setWriteSelfCheckStatus(binding.getWriteSelfCheckStatus());
history.setRelayStatus(binding.getRelayStatus());
history.setPulseStatus(binding.getPulseStatus());
history.setModuleStatus(binding.getModuleStatus());
history.setSimCardStatus(binding.getSimCardStatus());
history.setNetworkStatus(binding.getNetworkStatus());
return history;
}
......
package com.zehong.system.task;
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.util.Modbus4jUtils;
import com.zehong.system.service.ITEquipmentAlarmDataService;
import org.apache.commons.lang3.StringUtils;
......@@ -47,12 +38,7 @@ public class DeviceCommunicationJob implements Job {
// 超时控制:必须小于Cron周期(假设Cron为5分钟,这里留1分钟缓冲)
private static final int TOTAL_TASK_TIMEOUT_SEC = 240; // 任务总超时:4分钟
private static final int SINGLE_DEVICE_TIMEOUT_SEC = 10; // 单个设备超时:10秒
// Modbus配置:取消内置重试,统一用自定义重试
private static final int MODBUS_CONN_TIMEOUT_MS = 3000; // 连接超时:3秒
private static final int CUSTOM_RETRY_TIMES = 2; // 自定义重试次数:1次
// Modbus寄存器配置
private static final int REG_START_ADDR = 0;
private static final int REG_READ_COUNT = 10;
// 全局线程池 - 避免重复创建
private static final ExecutorService GLOBAL_DEVICE_EXECUTOR = new ThreadPoolExecutor(
......@@ -61,9 +47,6 @@ public class DeviceCommunicationJob implements Job {
r -> new Thread(r, "global-modbus-device"),
new ThreadPoolExecutor.CallerRunsPolicy()
);
// 工厂(单例)
private static final ModbusFactory modbusFactory = new ModbusFactory();
// -------------------------- 依赖注入 --------------------------
@Resource
private ITEquipmentAlarmDataService alarmDataService;
......@@ -95,7 +78,7 @@ public class DeviceCommunicationJob implements Job {
allPorts.get(TOTAL_TASK_TIMEOUT_SEC, TimeUnit.SECONDS);
log.info("任务执行成功: fStoreyId={}, 耗时={}ms",
log.info("DeviceCommunicationJob任务执行成功: fStoreyId={}, 耗时={}ms",
storeyIdStr, System.currentTimeMillis() - startTime);
} catch (TimeoutException e) {
......@@ -158,7 +141,7 @@ public class DeviceCommunicationJob implements Job {
PalletDeviceBinding binding = null;
try {
// 1. 读取设备数据
int[] result = readDeviceWithRetry(ip, port, deviceId);
int[] result = Modbus4jUtils.readDeviceWithRetry(ip, port, deviceId);
// 2. 查询设备绑定信息
binding = palletDeviceBindingMapper.selectByTrayIdAndIndex(ip, deviceId);
......@@ -178,7 +161,7 @@ public class DeviceCommunicationJob implements Job {
// 4. 条件写入时间
if (result[1] == 1 || result[1] == 3 || result[1] == 4) {
// 重用之前的master连接进行写操作
master = createModbusMaster(ip, port);
master = Modbus4jUtils.createModbusMaster(ip, port);
writeCurrentTimeToDevice(master, deviceId, binding);
}
......@@ -201,7 +184,7 @@ public class DeviceCommunicationJob implements Job {
errorCount.incrementAndGet();
return false;
} finally {
destroyModbusMaster(master, deviceId);
Modbus4jUtils.destroyModbusMaster(master, deviceId);
}
}, GLOBAL_DEVICE_EXECUTOR);
}
......@@ -232,64 +215,6 @@ public class DeviceCommunicationJob implements Job {
}
}
/**
* 带重试的设备读取
*/
private int[] readDeviceWithRetry(String ip, int port, int deviceId) {
ModbusMaster master = null;
int[] lastResult = null; // 用于记录最后一次读取的结果(无论是否满足停止条件)
try {
// 只创建一次ModbusMaster,循环内复用
master = createModbusMaster(ip, port);
for (int retry = 0; retry <= CUSTOM_RETRY_TIMES; retry++) {
try {
// 执行读取操作,获取本次结果
int[] currentResult = readDeviceRegisters(master, deviceId);
// 更新最后一次结果(无论是否满足停止条件,都记录)
lastResult = currentResult;
// 检查停止条件,如果满足则提前返回(无需等到重试耗尽)
if (ModbusResultHandler.createDefaultStopCondition().test(currentResult)) {
log.info("设备{}第{}次读取成功(满足条件): ip={}, port={}",
deviceId, retry + 1, ip, port);
return currentResult;
}
// 未满足条件且不是最后一次重试,休眠后继续
if (retry < CUSTOM_RETRY_TIMES) {
log.info("设备{}第{}次读取未满足条件,准备重试: ip={}, port={}",
deviceId, retry + 1, ip, port);
Thread.sleep(200);
}
} catch (Exception e) {
// 本次读取发生异常,记录日志但不中断重试(继续下一次)
log.warn("设备{}第{}次读取发生异常: ip={}, port={}",
deviceId, retry + 1, ip, port, e);
// 如果是最后一次重试,异常时lastResult可能为null(需后续处理)
}
}
// 循环结束(重试耗尽),此时lastResult为最后一次的结果(可能是正常读取但不满足条件,或null)
log.info("设备{}重试次数耗尽,返回最后一次结果: ip={}, port={}",
deviceId, ip, port);
} catch (Exception e) {
// 捕获创建ModbusMaster或休眠时的异常(非读取操作的异常)
log.error("设备{}连接创建或休眠失败: ip={}, port={}",
deviceId, ip, port, e);
throw new RuntimeException("设备连接或操作异常", e);
} finally {
// 无论结果如何,最终销毁连接
destroyModbusMaster(master, deviceId);
}
// 处理最后一次结果可能为null的情况(例如所有重试都异常)
if (lastResult == null) {
throw new RuntimeException("设备所有读取尝试均失败(无有效结果)");
}
return lastResult;
}
/**
* 写入当前时间到设备
*/
......@@ -327,58 +252,15 @@ public class DeviceCommunicationJob implements Job {
log.error("设备{}时间写入异常", deviceId, e);
recordAlarmByBinding(binding, "设备时间写入异常: " + e.getMessage());
}
}
// -------------------------- Modbus工具方法(显式抛出异常)--------------------------
/**
* 创建Modbus连接(取消内置重试,统一自定义重试)
*/
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.init();
return master;
}
/**
* 读取设备寄存器(异常直接抛出)
*/
private int[] readDeviceRegisters(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)) {
log.info("无效Modbus响应类型:" + response.getClass().getName() + ",deviceId=" + deviceId);
}
assert response instanceof ReadHoldingRegistersResponse;
ReadHoldingRegistersResponse regResp = (ReadHoldingRegistersResponse) response;
short[] signedVals = regResp.getShortData();
int[] unsignedVals = new int[signedVals.length];
for (int i = 0; i < signedVals.length; i++) {
unsignedVals[i] = signedVals[i] & 0xFFFF; // 转换为无符号整数
// 20251206 写完时间写自检,写自检就在时间后边写就行,不管时间写不写成功
try {
Modbus4jUtils.writeRegister(master, deviceId, 15, (short) 1);
binding.setWriteSelfCheckStatus(1);
} catch (Exception e) {
binding.setWriteSelfCheckStatus(0);
}
log.info("设备寄存器读取结果:deviceId={},值={}", deviceId, Arrays.toString(unsignedVals));
return unsignedVals;
}
/**
* 销毁Modbus连接(反射失败直接抛出异常,显式暴露问题)
*/
private void destroyModbusMaster(ModbusMaster master, int deviceId) {
if (master != null) {
try {
master.destroy();
} catch (Exception e) {
log.debug("设备{}: ModbusMaster销毁异常", deviceId, e);
}
}
}
// -------------------------- 辅助方法(日志/告警)--------------------------
......
package com.zehong.system.task;
import com.serotonin.modbus4j.ModbusFactory;
import com.serotonin.modbus4j.ModbusMaster;
import com.serotonin.modbus4j.exception.ModbusInitException;
import com.serotonin.modbus4j.exception.ModbusTransportException;
import com.zehong.common.utils.StringUtils;
import com.zehong.system.domain.RobotArmCommand;
import com.zehong.system.domain.PalletDeviceBinding;
import com.zehong.system.domain.TEquipmentAlarmData;
import com.zehong.system.domain.TStoreyInfo;
import com.zehong.system.domain.TTrayInfo;
import com.zehong.system.mapper.RobotArmCommandMapper;
import com.zehong.system.mapper.PalletDeviceBindingMapper;
import com.zehong.system.mapper.TStoreyInfoMapper;
import com.zehong.system.mapper.TTrayInfoMapper;
import com.zehong.system.modbus.util.Modbus4jUtils;
import com.zehong.system.service.IRobotArmCommandService;
import com.zehong.system.service.ITEquipmentAlarmDataService;
import com.zehong.system.service.ITStoreyInfoService;
import com.zehong.system.service.websocket.RobotArmWebSocketHandler;
import org.quartz.*;
import org.slf4j.Logger;
......@@ -22,17 +22,26 @@ import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;
/**
* @author lenovo
* @date 2025/6/25
* @description TODO
* @description 老化最终执行任务
*/
@Component
public class FinalExecutionJob implements Job {
private static final Logger log = LoggerFactory.getLogger(FinalExecutionJob.class);
// -------------------------- 常量配置(统一管理,避免魔法值)--------------------------
// 超时控制:必须小于Cron周期(假设Cron为5分钟,这里留1分钟缓冲)
private static final int TOTAL_TASK_TIMEOUT_SEC = 240; // 任务总超时:4分钟
private static final int SINGLE_DEVICE_TIMEOUT_SEC = 10; // 单个设备超时:10秒
@Resource
private RobotArmWebSocketHandler robotArmWebSocketHandler;
@Resource
......@@ -48,16 +57,27 @@ public class FinalExecutionJob implements Job {
@Resource
private IRobotArmCommandService robotArmCommandService;
@Resource
private PalletDeviceBindingMapper palletDeviceBindingMapper;
// 全局线程池 - 避免重复创建
private static final ExecutorService GLOBAL_DEVICE_EXECUTOR = new ThreadPoolExecutor(
50, 100, 60, TimeUnit.SECONDS,
new LinkedBlockingQueue<>(500),
r -> new Thread(r, "final-global-modbus-device"),
new ThreadPoolExecutor.CallerRunsPolicy()
);
// 工厂(单例)
private static final ModbusFactory modbusFactory = new ModbusFactory();
@Override
public void execute(JobExecutionContext context) {
// 1. 初始化变量,避免空指针
JobDataMap data;
String fPowerOutageIp;
Long fStoreyId = null;
Integer fPowerOutagePort;
int fPowerOutagePort;
TStoreyInfo tStoreyInfo = null;
TTrayInfo tTrayInfo;
long startTime = System.currentTimeMillis();
try {
// 2. 提取并校验所有参数
......@@ -109,6 +129,23 @@ public class FinalExecutionJob implements Job {
// recordAlarm(tStoreyInfo, "Modbus写操作失败:" + e.getMessage());
// }
// 20251206 读取 继电器状态 脉冲状态 模组状态 SIM卡状态 网络状态
// 并行处理3个端口
// List<CompletableFuture<Void>> portFutures = Arrays.asList(
// processPort(tStoreyInfo, 501, 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)),
// processPort(tStoreyInfo, 502, 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)),
// processPort(tStoreyInfo, 503, Arrays.asList(55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72))
// );
// // 等待所有端口完成,带总超时
// CompletableFuture<Void> allPorts = CompletableFuture.allOf(
// portFutures.toArray(new CompletableFuture[0])
// );
//
// allPorts.get(TOTAL_TASK_TIMEOUT_SEC, TimeUnit.SECONDS);
//
// log.info("FinalExecutionJob 任务执行成功: fStoreyId={}, 耗时={}ms",
// tStoreyInfo.getfStoreyId(), System.currentTimeMillis() - startTime);
// 6. 更新设备状态(DB操作单独捕获异常)
try {
tStoreyInfo.setfStatus("4");
......@@ -161,7 +198,99 @@ public class FinalExecutionJob implements Job {
log.error("=== FinalExecutionJob finally:fStoreyId={} ===", fStoreyId);
}
}
/**
* 处理单个端口的所有设备
*/
private CompletableFuture<Void> processPort(TStoreyInfo storeyInfo, int port, List<Integer> deviceIds) {
return CompletableFuture.runAsync(() -> {
String ip = storeyInfo.getfIp();
String storeyIdStr = storeyInfo.getfStoreyId().toString();
log.info("开始端口通信: ip={}, port={}, 设备数={}", ip, port, deviceIds.size());
AtomicInteger errorCount = new AtomicInteger(0);
// 并行处理该端口的所有设备
List<CompletableFuture<Boolean>> deviceFutures = deviceIds.stream()
.map(deviceId -> processDeviceWithWrite(ip, port, deviceId, errorCount))
.collect(Collectors.toList());
try {
// 等待该端口所有设备完成
CompletableFuture<Void> allDevices = CompletableFuture.allOf(
deviceFutures.toArray(new CompletableFuture[0])
);
// 端口超时 = 设备数 * 单设备超时 / 并发因子
int portTimeout = Math.max(30, deviceIds.size() * SINGLE_DEVICE_TIMEOUT_SEC / 5);
allDevices.get(portTimeout, TimeUnit.SECONDS);
} catch (TimeoutException e) {
log.warn("端口{}通信超时: ip={}, fStoreyId={}", port, ip, storeyIdStr);
recordAlarm(storeyInfo, "端口" + port + "通信超时");
} catch (Exception e) {
log.error("端口{}通信异常: ip={}, fStoreyId={}", port, ip, storeyIdStr, e);
}
if (errorCount.get() > 0) {
log.warn("端口{}部分设备失败: 失败数={}, fStoreyId={}",
port, errorCount.get(), storeyIdStr);
}
log.info("端口通信完成: ip={}, port={}, fStoreyId={}", ip, port, storeyIdStr);
}, GLOBAL_DEVICE_EXECUTOR);
}
/**
* 处理单个设备(读取 + 条件写入)
*/
private CompletableFuture<Boolean> processDeviceWithWrite(String ip, int port, int deviceId, AtomicInteger errorCount) {
return CompletableFuture.supplyAsync(() -> {
PalletDeviceBinding binding;
try {
// 1. 读取设备数据
int[] result = Modbus4jUtils.readDeviceWithRetry(ip, port, deviceId);
// 2. 查询设备绑定信息
binding = palletDeviceBindingMapper.selectByTrayIdAndIndex(ip, deviceId);
if (binding == null) {
log.warn("未找到设备绑定: ip={}, deviceId={}", ip, deviceId);
recordAlarm(null, "ip:" + ip + ",port:" + port + ",deviceId:" + deviceId, "未找到设备绑定");
errorCount.incrementAndGet();
return false;
}
// 5. 更新数据库
palletDeviceBindingMapper.updatePalletDeviceBinding(binding);
log.debug("设备{}处理完成: ip={}, port={}, status={}", deviceId, ip, port, result[1]);
return true;
} catch (Exception e) {
log.info("设备{}处理异常: ip={}, port={}", deviceId, ip, port, e);
errorCount.incrementAndGet();
return false;
}
}, GLOBAL_DEVICE_EXECUTOR);
}
/**
* 记录告警(兼容设备信息为空的场景)
*/
private void recordAlarm(TStoreyInfo storeyInfo, String equipmentCode, String alarmData) {
try {
TEquipmentAlarmData alarm = new TEquipmentAlarmData();
alarm.setfAlarmType("03"); // 老化层告警
alarm.setfEquipmentCode(storeyInfo != null ? storeyInfo.getfStoreyCode() : equipmentCode);
alarm.setfAlarmData(alarmData);
alarm.setfCreateTime(new Date());
alarmDataService.insertTEquipmentAlarmData(alarm);
log.debug("告警记录成功:设备编码={},内容={}", alarm.getfEquipmentCode(), alarmData);
} catch (Exception e) {
log.error("告警记录失败:设备编码={},内容={}", equipmentCode, alarmData, e);
}
}
// 辅助方法:记录告警(抽离,避免代码重复)
private void recordAlarm(TStoreyInfo tStoreyInfo, String alarmMsg) {
try {
......@@ -198,7 +327,7 @@ public class FinalExecutionJob implements Job {
// 10 层
ModbusMaster master;
try {
master = Modbus4jUtils.getMaster(fPowerOutageIp, fPowerOutagePort);
master = Modbus4jUtils.createModbusMaster(fPowerOutageIp, fPowerOutagePort);
Boolean aBoolean = Modbus4jUtils.writeCoil(master, 1,registerOffsets,false );
} catch (ModbusInitException | ModbusTransportException e) {
throw new RuntimeException(e);
......
package com.zehong.system.task;
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.SysRealTimeAdRange;
import com.zehong.system.domain.TEquipmentAlarmData;
......@@ -16,11 +9,13 @@ import com.zehong.system.domain.TStoreyInfo;
import com.zehong.system.mapper.PalletDeviceBindingMapper;
import com.zehong.system.mapper.SysRealTimeAdRangeMapper;
import com.zehong.system.mapper.TStoreyInfoMapper;
import com.zehong.system.modbus.handler.ModbusResultHandler;
import com.zehong.system.modbus.util.Modbus4jUtils;
import com.zehong.system.service.ITEquipmentAlarmDataService;
import org.apache.commons.lang3.StringUtils;
import org.quartz.*;
import org.quartz.DisallowConcurrentExecution;
import org.quartz.Job;
import org.quartz.JobDataMap;
import org.quartz.JobExecutionContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
......@@ -48,12 +43,7 @@ public class PrepareFinalExecutionJob implements Job {
// 超时控制:必须小于Cron周期(假设Cron为5分钟,这里留1分钟缓冲)
private static final int TOTAL_TASK_TIMEOUT_SEC = 240; // 任务总超时:4分钟
private static final int SINGLE_DEVICE_TIMEOUT_SEC = 10; // 单个设备超时:10秒
// Modbus配置:取消内置重试,统一用自定义重试
private static final int MODBUS_CONN_TIMEOUT_MS = 3000; // 连接超时:3秒
private static final int CUSTOM_RETRY_TIMES = 2; // 自定义重试次数:1次
// Modbus寄存器配置
private static final int REG_START_ADDR = 0;
private static final int REG_READ_COUNT = 10;
// 全局线程池 - 避免重复创建
private static final ExecutorService GLOBAL_DEVICE_EXECUTOR = new ThreadPoolExecutor(
......@@ -62,9 +52,6 @@ public class PrepareFinalExecutionJob implements Job {
r -> new Thread(r, "prepare-global-modbus-device"),
new ThreadPoolExecutor.CallerRunsPolicy()
);
// 工厂(单例)
private static final ModbusFactory modbusFactory = new ModbusFactory();
// -------------------------- 依赖注入 --------------------------
@Resource
private ITEquipmentAlarmDataService alarmDataService;
......@@ -85,6 +72,11 @@ public class PrepareFinalExecutionJob implements Job {
try {
TStoreyInfo storeyInfo = validateAndGetStoreyInfo(storeyIdStr);
if(storeyInfo == null) {
log.info("无效的storeyId: {}", storeyIdStr);
recordAlarm(null, storeyIdStr, "PrepareFinalExecutionJob无效的storeyId");
return;
}
// 并行处理3个端口
List<CompletableFuture<Void>> portFutures = Arrays.asList(
......@@ -100,14 +92,14 @@ public class PrepareFinalExecutionJob implements Job {
allPorts.get(TOTAL_TASK_TIMEOUT_SEC, TimeUnit.SECONDS);
log.info("任务执行成功: fStoreyId={}, 耗时={}ms",
log.info("PrepareFinalExecutionJob任务执行成功: fStoreyId={}, 耗时={}ms",
storeyIdStr, System.currentTimeMillis() - startTime);
} catch (TimeoutException e) {
log.warn("任务执行超时: fStoreyId={}", storeyIdStr);
log.info("任务执行超时: fStoreyId={}", storeyIdStr);
recordAlarm(null, storeyIdStr, "任务执行超时");
} catch (Exception e) {
log.error("任务执行异常: fStoreyId={}", storeyIdStr, e);
log.info("任务执行异常: fStoreyId={}", storeyIdStr, e);
recordAlarm(null, storeyIdStr, "任务执行异常: " + e.getMessage());
}
}
......@@ -163,7 +155,7 @@ public class PrepareFinalExecutionJob implements Job {
PalletDeviceBinding binding = null;
try {
// 1. 读取设备数据
int[] result = readDeviceWithRetry(ip, port, deviceId);
int[] result = Modbus4jUtils.readDeviceWithRetry(ip, port, deviceId);
// 2. 查询设备绑定信息
binding = palletDeviceBindingMapper.selectByTrayIdAndIndex(ip, deviceId);
......@@ -193,7 +185,7 @@ public class PrepareFinalExecutionJob implements Job {
// 4. 条件写入时间
if (result[1] == 1 || result[1] == 3 || result[1] == 4) {
// 重用之前的master连接进行写操作
master = createModbusMaster(ip, port);
master = Modbus4jUtils.createModbusMaster(ip, port);
checkAndUpdateTime(master, deviceId, binding);
} else {
binding.setStatus(result[1] +"");
......@@ -217,7 +209,7 @@ public class PrepareFinalExecutionJob implements Job {
errorCount.incrementAndGet();
return false;
} finally {
destroyModbusMaster(master, deviceId);
Modbus4jUtils.destroyModbusMaster(master, deviceId);
}
}, GLOBAL_DEVICE_EXECUTOR);
}
......@@ -248,65 +240,6 @@ public class PrepareFinalExecutionJob implements Job {
}
}
/**
* 带重试的设备读取
*/
private int[] readDeviceWithRetry(String ip, int port, int deviceId) {
ModbusMaster master = null;
int[] lastResult = null; // 用于记录最后一次读取的结果(无论是否满足停止条件)
try {
// 只创建一次ModbusMaster,循环内复用
master = createModbusMaster(ip, port);
for (int retry = 0; retry <= CUSTOM_RETRY_TIMES; retry++) {
try {
// 执行读取操作,获取本次结果
int[] currentResult = readDeviceRegisters(master, deviceId);
// 更新最后一次结果(无论是否满足停止条件,都记录)
lastResult = currentResult;
// 检查停止条件,如果满足则提前返回(无需等到重试耗尽)
if (ModbusResultHandler.createDefaultStopCondition().test(currentResult)) {
log.info("设备{}第{}次读取成功(满足条件): ip={}, port={}",
deviceId, retry + 1, ip, port);
return currentResult;
}
// 未满足条件且不是最后一次重试,休眠后继续
if (retry < CUSTOM_RETRY_TIMES) {
log.info("设备{}第{}次读取未满足条件,准备重试: ip={}, port={}",
deviceId, retry + 1, ip, port);
Thread.sleep(200);
}
} catch (Exception e) {
// 本次读取发生异常,记录日志但不中断重试(继续下一次)
log.warn("设备{}第{}次读取发生异常: ip={}, port={}",
deviceId, retry + 1, ip, port, e);
// 如果是最后一次重试,异常时lastResult可能为null(需后续处理)
}
}
// 循环结束(重试耗尽),此时lastResult为最后一次的结果(可能是正常读取但不满足条件,或null)
log.info("设备{}重试次数耗尽,返回最后一次结果: ip={}, port={}",
deviceId, ip, port);
} catch (Exception e) {
// 捕获创建ModbusMaster或休眠时的异常(非读取操作的异常)
log.error("设备{}连接创建或休眠失败: ip={}, port={}",
deviceId, ip, port, e);
throw new RuntimeException("设备连接或操作异常", e);
} finally {
// 无论结果如何,最终销毁连接
destroyModbusMaster(master, deviceId);
}
// 处理最后一次结果可能为null的情况(例如所有重试都异常)
if (lastResult == null) {
throw new RuntimeException("设备所有读取尝试均失败(无有效结果)");
}
return lastResult;
}
/**
* 检查并更新时间
*/
......@@ -514,58 +447,6 @@ public class PrepareFinalExecutionJob implements Job {
recordAlarmByBinding(binding, "设备时间写入异常: " + e.getMessage());
}
}
// -------------------------- Modbus工具方法(显式抛出异常)--------------------------
/**
* 创建Modbus连接(取消内置重试,统一自定义重试)
*/
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.init();
return master;
}
/**
* 读取设备寄存器(异常直接抛出)
*/
private int[] readDeviceRegisters(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)) {
log.info("无效Modbus响应类型:" + response.getClass().getName() + ",deviceId=" + deviceId);
}
assert response instanceof ReadHoldingRegistersResponse;
ReadHoldingRegistersResponse regResp = (ReadHoldingRegistersResponse) response;
short[] signedVals = regResp.getShortData();
int[] unsignedVals = new int[signedVals.length];
for (int i = 0; i < signedVals.length; i++) {
unsignedVals[i] = signedVals[i] & 0xFFFF; // 转换为无符号整数
}
log.info("设备寄存器读取结果:deviceId={},值={}", deviceId, Arrays.toString(unsignedVals));
return unsignedVals;
}
/**
* 销毁Modbus连接(反射失败直接抛出异常,显式暴露问题)
*/
private void destroyModbusMaster(ModbusMaster master, int deviceId) {
if (master != null) {
try {
master.destroy();
} catch (Exception e) {
log.debug("设备{}: ModbusMaster销毁异常", deviceId, e);
}
}
}
// -------------------------- 辅助方法(日志/告警)--------------------------
/**
......
......@@ -36,6 +36,13 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<result property="calibrationConcentration" column="f_calibration_concentration" />
<result property="calibrationConcentrationStatus" column="f_calibration_concentration_status" />
<result property="writeSelfCheckStatus" column="f_write_self_check_status" />
<result property="relayStatus" column="f_relay_status" />
<result property="pulseStatus" column="f_pulse_status" />
<result property="moduleStatus" column="f_module_status" />
<result property="simCardStatus" column="f_sim_card_status" />
<result property="networkStatus" column="f_network_status" />
</resultMap>
<sql id="selectPalletDeviceBindingVo">
......@@ -66,7 +73,13 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
palDeviceBinding.f_real_time_ad,
palDeviceBinding.f_real_time_ad_status,
palDeviceBinding.f_calibration_concentration,
palDeviceBinding.f_calibration_concentration_status
palDeviceBinding.f_calibration_concentration_status,
palDeviceBinding.f_write_self_check_status,
palDeviceBinding.f_relay_status,
palDeviceBinding.f_pulse_status,
palDeviceBinding.f_module_status,
palDeviceBinding.f_sim_card_status,
palDeviceBinding.f_network_status
from t_pallet_device_binding palDeviceBinding
left join t_tray_info trayInfo on trayInfo.f_tray_id = palDeviceBinding.f_tray_id
</sql>
......@@ -144,7 +157,13 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
f_real_time_ad,
f_real_time_ad_status,
f_calibration_concentration,
f_calibration_concentration_status
f_calibration_concentration_status,
f_write_self_check_status,
f_relay_status,
f_pulse_status,
f_module_status,
f_sim_card_status,
f_network_status
from t_pallet_device_binding palDeviceBinding where palDeviceBinding.f_tray_id = (
SELECT
trayInfo.f_tray_id
......@@ -203,7 +222,13 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
f_real_time_ad = null,
f_real_time_ad_status = null,
f_calibration_concentration = null,
f_calibration_concentration_status = null
f_calibration_concentration_status = null,
f_write_self_check_status = null,
f_relay_status = null,
f_pulse_status = null,
f_module_status = null,
f_sim_card_status = null,
f_network_status = null
where f_tray_id = #{trayId}
</update>
<insert id="insertPalletDeviceBinding" parameterType="PalletDeviceBinding" useGeneratedKeys="true" keyProperty="palletDeviceBindingId">
......@@ -254,7 +279,13 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
f_real_time_ad = null,
f_real_time_ad_status = null,
f_calibration_concentration = null,
f_calibration_concentration_status = null
f_calibration_concentration_status = null,
f_write_self_check_status = null,
f_relay_status = null,
f_pulse_status = null,
f_module_status = null,
f_sim_card_status = null,
f_network_status = null
where f_pallet_device_binding_id = #{palletDeviceBindingId}
</update>
<update id="updatePalletDeviceBinding" parameterType="PalletDeviceBinding">
......@@ -289,6 +320,12 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="calibrationConcentration != null">f_calibration_concentration = #{calibrationConcentration},</if>
<if test="calibrationConcentrationStatus != null">f_calibration_concentration_status = #{calibrationConcentrationStatus},</if>
<if test="writeSelfCheckStatus != null">f_write_self_check_status = #{writeSelfCheckStatus},</if>
<if test="relayStatus != null">f_relay_status = #{relayStatus},</if>
<if test="pulseStatus != null">f_pulse_status = #{pulseStatus},</if>
<if test="moduleStatus != null">f_module_status = #{moduleStatus},</if>
<if test="simCardStatus != null">f_sim_card_status = #{simCardStatus},</if>
<if test="networkStatus != null">f_network_status = #{networkStatus},</if>
</trim>
where f_pallet_device_binding_id = #{palletDeviceBindingId}
</update>
......@@ -338,7 +375,13 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
f_real_time_ad = null,
f_real_time_ad_status = null,
f_calibration_concentration = null,
f_calibration_concentration_status = null
f_calibration_concentration_status = null,
f_write_self_check_status = null,
f_relay_status = null,
f_pulse_status = null,
f_module_status = null,
f_sim_card_status = null,
f_network_status = null
<choose>
<when test="item.deviceCode != null">
, f_device_code = #{item.deviceCode}
......@@ -369,7 +412,13 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
f_real_time_ad = null,
f_real_time_ad_status = null,
f_calibration_concentration = null,
f_calibration_concentration_status = null
f_calibration_concentration_status = null,
f_write_self_check_status = null,
f_relay_status = null,
f_pulse_status = null,
f_module_status = null,
f_sim_card_status = null,
f_network_status = null
where f_tray_id = #{trayId}
</update>
......
......@@ -33,6 +33,13 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<result property="calibrationConcentration" column="f_calibration_concentration" />
<result property="calibrationConcentrationStatus" column="f_calibration_concentration_status" />
<result property="writeSelfCheckStatus" column="f_write_self_check_status" />
<result property="relayStatus" column="f_relay_status" />
<result property="pulseStatus" column="f_pulse_status" />
<result property="moduleStatus" column="f_module_status" />
<result property="simCardStatus" column="f_sim_card_status" />
<result property="networkStatus" column="f_network_status" />
</resultMap>
<sql id="selectPalletDeviceUploadHistoryVo">
......@@ -63,7 +70,13 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
palDeviceBinding.f_real_time_ad,
palDeviceBinding.f_real_time_ad_status,
palDeviceBinding.f_calibration_concentration,
palDeviceBinding.f_calibration_concentration_status
palDeviceBinding.f_calibration_concentration_status,
palDeviceBinding.f_write_self_check_status,
palDeviceBinding.f_relay_status,
palDeviceBinding.f_pulse_status,
palDeviceBinding.f_module_status,
palDeviceBinding.f_sim_card_status,
palDeviceBinding.f_network_status
from t_pallet_device_upload_history palDeviceBinding
left join t_tray_info trayInfo on trayInfo.f_tray_id = palDeviceBinding.f_tray_id
</sql>
......@@ -108,7 +121,13 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
f_real_time_ad,
f_real_time_ad_status,
f_calibration_concentration,
f_calibration_concentration_status
f_calibration_concentration_status,
f_write_self_check_status,
f_relay_status,
f_pulse_status,
f_module_status,
f_sim_card_status,
f_network_status
</trim>
values
<foreach collection="list" item="item" separator=",">
......@@ -138,7 +157,13 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
#{item.realTimeAd},
#{item.realTimeAdStatus},
#{item.calibrationConcentration},
#{item.calibrationConcentrationStatus}
#{item.calibrationConcentrationStatus},
#{item.writeSelfCheckStatus},
#{item.relayStatus},
#{item.pulseStatus},
#{item.moduleStatus},
#{item.simCardStatus},
#{item.networkStatus}
</trim>
</foreach>
</insert>
......@@ -171,6 +196,13 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="realTimeAdStatus != null">f_real_time_ad_status,</if>
<if test="calibrationConcentration != null">#{calibrationConcentration},</if>
<if test="calibrationConcentrationStatus != null">#{calibrationConcentrationStatus},</if>
<if test="writeSelfCheckStatus != null">#{writeSelfCheckStatus},</if>
<if test="relayStatus != null">#{relayStatus},</if>
<if test="pulseStatus != null">#{pulseStatus},</if>
<if test="moduleStatus != null">#{moduleStatus},</if>
<if test="simCardStatus != null">#{simCardStatus},</if>
<if test="networkStatus != null">#{networkStatus},</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="trayId != null">#{trayId},</if>
......@@ -199,6 +231,13 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="realTimeAdStatus != null">#{realTimeAdStatus},</if>
<if test="calibrationConcentration != null">#{calibrationConcentration},</if>
<if test="calibrationConcentrationStatus != null">#{calibrationConcentrationStatus},</if>
<if test="writeSelfCheckStatus != null">#{writeSelfCheckStatus},</if>
<if test="relayStatus != null">#{relayStatus},</if>
<if test="pulseStatus != null">#{pulseStatus},</if>
<if test="moduleStatus != null">#{moduleStatus},</if>
<if test="simCardStatus != null">#{simCardStatus},</if>
<if test="networkStatus != null">#{networkStatus},</if>
</trim>
</insert>
......@@ -231,6 +270,14 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="realTimeAdStatus != null">f_real_time_ad_status = #{realTimeAdStatus},</if>
<if test="calibrationConcentration != null">f_calibration_concentration = #{calibrationConcentration},</if>
<if test="calibrationConcentrationStatus != null">f_calibration_concentration_status = #{calibrationConcentrationStatus},</if>
<if test="writeSelfCheckStatus != null">f_write_self_check_status = #{writeSelfCheckStatus},</if>
<if test="relayStatus != null">f_relay_status = #{relayStatus},</if>
<if test="pulseStatus != null">f_pulse_status = #{pulseStatus},</if>
<if test="moduleStatus != null">f_module_status = #{moduleStatus},</if>
<if test="simCardStatus != null">f_sim_card_status = #{simCardStatus},</if>
<if test="networkStatus != null">f_network_status = #{networkStatus},</if>
</trim>
where f_id = #{id}
</update>
......
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