Commit 2103aee4 authored by wanghao's avatar wanghao

1 老化 第一阶段 和 第三阶段 写时间 后 时间比对调整。

parent 2aa9911b
...@@ -1113,65 +1113,168 @@ public class Modbus4jUtils { ...@@ -1113,65 +1113,168 @@ public class Modbus4jUtils {
} }
/** /**
// 写入并验证年份
// allSuccess &= writeAndVerifyField(master, deviceId, 4, (short) year, "年份", year);
// 写入并验证月份
// allSuccess &= writeAndVerifyField(master, deviceId, 5, (short) month, "月份", month);
// allSuccess &= writeAndVerifyField(master, deviceId, 6, (short) day, "日期", day);
// 写入并验证小时
// allSuccess &= writeAndVerifyField(master, deviceId, 7, (short) hour, "小时", hour);
// 写入并验证分钟
// allSuccess &= writeAndVerifyField(master, deviceId, 8, (short) minute, "分钟", minute);
* 增强版:写入并实时验证每个字段 * 增强版:写入并实时验证每个字段
*/ */
/**
* 增强版:写入并实时验证每个字段(增加重试机制)
*/
public static boolean writeCurrentTimeToDeviceEnhanced(ModbusMaster master, int deviceId, WriteCurrentTimeVo writeCurrentTimeVo) { public static boolean writeCurrentTimeToDeviceEnhanced(ModbusMaster master, int deviceId, WriteCurrentTimeVo writeCurrentTimeVo) {
try { final int MAX_RETRIES = 3;
int retryCount = 0;
int year = writeCurrentTimeVo.getYear(); while (retryCount < MAX_RETRIES) {
int month = writeCurrentTimeVo.getMonth(); try {
int day = writeCurrentTimeVo.getDay(); retryCount++;
int hour = writeCurrentTimeVo.getHour(); log.info("第{}次尝试设置设备{}时间...", retryCount, deviceId);
int minute = writeCurrentTimeVo.getMinute();
log.info("开始设置设备{}时间: {}-{}-{} {}:{}", int year = writeCurrentTimeVo.getYear();
deviceId, year, month, day, hour, minute); int month = writeCurrentTimeVo.getMonth();
int day = writeCurrentTimeVo.getDay();
int hour = writeCurrentTimeVo.getHour();
int minute = writeCurrentTimeVo.getMinute();
// 逐个写入并验证 log.info("开始设置设备{}时间: {}-{}-{} {}:{}", deviceId, year, month, day, hour, minute);
boolean allSuccess = true;
// 写入并验证年份 // 逐个写入并验证
allSuccess &= writeAndVerifyField(master, deviceId, 4, (short) year, "年份", year); boolean allSuccess = true;
Thread.sleep(500);
// 写入并验证月份 // 1. 写入操作(可以使用for循环优化,但保留清晰的结构便于调试)
allSuccess &= writeAndVerifyField(master, deviceId, 5, (short) month, "月份", month); allSuccess &= Modbus4jUtils.writeRegister(master, deviceId, 4, (short) year);
Thread.sleep(500); Thread.sleep(2000);
allSuccess &= writeAndVerifyField(master, deviceId, 6, (short) day, "日期", day); allSuccess &= Modbus4jUtils.writeRegister(master, deviceId, 5, (short) month);
Thread.sleep(500); Thread.sleep(2000);
// 写入并验证小时 allSuccess &= Modbus4jUtils.writeRegister(master, deviceId, 6, (short) day);
allSuccess &= writeAndVerifyField(master, deviceId, 7, (short) hour, "小时", hour); Thread.sleep(2000);
Thread.sleep(500);
// 写入并验证分钟 allSuccess &= Modbus4jUtils.writeRegister(master, deviceId, 7, (short) hour);
allSuccess &= writeAndVerifyField(master, deviceId, 8, (short) minute, "分钟", minute); Thread.sleep(2000);
Thread.sleep(500);
if (allSuccess) { allSuccess &= Modbus4jUtils.writeRegister(master, deviceId, 8, (short) minute);
// 最终整体验证 Thread.sleep(2000);
Thread.sleep(500);
int[] ints = readDeviceRegisters(master, deviceId); if (allSuccess) {
int[] ints = readDeviceRegisters(master, deviceId);
int deviceYear = ints[4];
int deviceMonth = ints[5];
int deviceDay = ints[6];
int deviceHour = ints[7];
int deviceMinute = ints[8];
if (isTimeConsistent(deviceYear, deviceMonth, deviceDay, deviceHour, deviceMinute, year, month, day, hour, minute)) {
log.info("设备{}时间设置全部完成且验证通过", deviceId);
return true;
} else {
log.info("设备{}时间设置完成,但最终验证失败,准备重试...", deviceId);
// 验证失败,等待一下再重试
if (retryCount < MAX_RETRIES) {
Thread.sleep(3000); // 重试前等待3秒
continue;
}
}
} else {
log.info("设备{}时间设置过程中出现失败,准备重试...", deviceId);
// 写入失败,等待一下再重试
if (retryCount < MAX_RETRIES) {
Thread.sleep(3000); // 重试前等待3秒
continue;
}
}
if (verifyTimeRegisters(ints, year, month, day, hour, minute)) { // 最后一次尝试失败
log.info("设备{}时间设置全部完成且验证通过", deviceId); if (retryCount == MAX_RETRIES) {
return true; log.info("设备{}时间设置失败,已达最大重试次数{}", deviceId, MAX_RETRIES);
return false;
}
} catch (Exception e) {
log.info("设备{}时间写入异常,准备重试...", deviceId, e);
// 异常情况也等待后重试
if (retryCount < MAX_RETRIES) {
try {
Thread.sleep(3000);
} catch (InterruptedException ie) {
Thread.currentThread().interrupt();
log.info("重试等待被打断", ie);
return false;
}
} else { } else {
log.warn("设备{}时间设置完成,但最终验证失败", deviceId); log.info("设备{}时间写入异常,已达最大重试次数{}", deviceId, MAX_RETRIES, e);
return false; return false;
} }
} else {
log.error("设备{}时间设置过程中出现失败", deviceId);
return false;
} }
}
} catch (Exception e) { return false;
log.error("设备{}时间写入异常", deviceId, e); }
/**
* 判断设备时间与系统时间是否一致(差异在2分钟内)
* 考虑跨年、跨月等边界情况
*/
public static boolean isTimeConsistent(int deviceYear, int deviceMonth, int deviceDay,
int deviceHour, int deviceMinute,
int systemYear, int systemMonth, int systemDay,
int systemHour, int systemMinute) {
// 1. 首先检查年份差异(考虑跨年)
if (Math.abs(deviceYear - systemYear) > 1) {
log.info("年份差异超过1年: 设备{}年 vs 系统{}年", deviceYear, systemYear);
return false; return false;
} }
}
// 2. 转换为总分钟数进行比较(考虑跨年、跨月、跨日)
long deviceTotalMinutes = calculateTotalMinutes(deviceYear, deviceMonth, deviceDay, deviceHour, deviceMinute);
long systemTotalMinutes = calculateTotalMinutes(systemYear, systemMonth, systemDay, systemHour, systemMinute);
long minuteDiff = Math.abs(deviceTotalMinutes - systemTotalMinutes);
log.info("时间差异比较: 设备分钟数={}, 系统分钟数={}, 差异={}分钟", deviceTotalMinutes, systemTotalMinutes, minuteDiff);
// 3. 差异在2分钟内认为一致
return minuteDiff <= 2;
}
/**
* 计算从参考时间点(如2000年)开始的总分钟数
* 用于准确比较时间差异,考虑跨年跨月
*/
private static long calculateTotalMinutes(int year, int month, int day, int hour, int minute) {
// 使用2000-01-01 00:00:00作为参考点
Calendar cal = Calendar.getInstance();
cal.set(Calendar.YEAR, 2000);
cal.set(Calendar.MONTH, Calendar.JANUARY);
cal.set(Calendar.DAY_OF_MONTH, 1);
cal.set(Calendar.HOUR_OF_DAY, 0);
cal.set(Calendar.MINUTE, 0);
cal.set(Calendar.SECOND, 0);
cal.set(Calendar.MILLISECOND, 0);
long baseTimeInMillis = cal.getTimeInMillis();
// 设置目标时间
cal.set(Calendar.YEAR, year);
cal.set(Calendar.MONTH, month - 1); // 转换为Calendar月份(0-based)
cal.set(Calendar.DAY_OF_MONTH, day);
cal.set(Calendar.HOUR_OF_DAY, hour);
cal.set(Calendar.MINUTE, minute);
cal.set(Calendar.SECOND, 0);
cal.set(Calendar.MILLISECOND, 0);
long targetTimeInMillis = cal.getTimeInMillis();
// 返回总分钟数
return (targetTimeInMillis - baseTimeInMillis) / (1000 * 60);
}
/** /**
* 写入并验证单个字段(带重试机制) * 写入并验证单个字段(带重试机制)
*/ */
...@@ -1195,20 +1298,17 @@ public class Modbus4jUtils { ...@@ -1195,20 +1298,17 @@ public class Modbus4jUtils {
continue; // 继续下一次重试 continue; // 继续下一次重试
} }
// 2. 等待设备处理(保持原有逻辑)
Thread.sleep(2000);
// 3. 读取验证 // 3. 读取验证
int[] ints = readDeviceRegisters(master, deviceId); // int[] ints = readDeviceRegisters(master, deviceId);
if (ints.length > address && ints[address] == expectedValue) { // if (ints.length > address && ints[address] == expectedValue) {
log.info("{}验证通过,写入值: {}", fieldName, expectedValue); // log.info("{}验证通过,写入值: {}", fieldName, expectedValue);
return true; // 成功,直接返回 // return true; // 成功,直接返回
} else { // } else {
int actualValue = ints.length > address ? ints[address] : -1; // int actualValue = ints.length > address ? ints[address] : -1;
log.warn("第{}次{}验证失败,期望: {},实际: {}", // log.warn("第{}次{}验证失败,期望: {},实际: {}",
retry, fieldName, expectedValue, actualValue); // retry, fieldName, expectedValue, actualValue);
// 验证失败,继续下一次重试 // // 验证失败,继续下一次重试
} // }
} catch (Exception e) { } catch (Exception e) {
log.error("第{}次写入{}时发生异常", retry, fieldName, e); log.error("第{}次写入{}时发生异常", retry, fieldName, e);
......
package com.zehong.system.task; package com.zehong.system.task;
import com.serotonin.modbus4j.ModbusMaster; import com.serotonin.modbus4j.ModbusMaster;
import com.sun.org.apache.xpath.internal.operations.Mod;
import com.zehong.system.domain.PalletDeviceBinding; 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;
...@@ -170,16 +169,14 @@ public class AgingStageOneProcessJob implements Job { ...@@ -170,16 +169,14 @@ public class AgingStageOneProcessJob implements Job {
if (!allSuccess) { if (!allSuccess) {
log.warn("设备{}写入时间失败: ip={}, port={}", deviceId, ip, port); log.warn("设备{}写入时间失败: ip={}, port={}", deviceId, ip, port);
binding.setWriteTimeStatus("0"); binding.setWriteTimeStatus("0");
palletDeviceBindingMapper.updatePalletDeviceBinding(binding); } else {
errorCount.incrementAndGet(); binding.setRecordYear(String.valueOf(writeCurrentTimeVo.getYear()));
return false; binding.setRecordMonth(String.valueOf(writeCurrentTimeVo.getMonth()));
binding.setRecordDate(String.valueOf(writeCurrentTimeVo.getDay()));
binding.setRecordHour(String.valueOf(writeCurrentTimeVo.getHour()));
binding.setRecordMinute(String.valueOf(writeCurrentTimeVo.getMinute()));
binding.setWriteTimeStatus("1");
} }
binding.setRecordYear(String.valueOf(writeCurrentTimeVo.getYear()));
binding.setRecordMonth(String.valueOf(writeCurrentTimeVo.getMonth()));
binding.setRecordDate(String.valueOf(writeCurrentTimeVo.getDay()));
binding.setRecordHour(String.valueOf(writeCurrentTimeVo.getHour()));
binding.setRecordMinute(String.valueOf(writeCurrentTimeVo.getMinute()));
binding.setWriteTimeStatus("1");
} }
// 5. 写入自检让设备开始自检,跟 上面的状态没关系 // 5. 写入自检让设备开始自检,跟 上面的状态没关系
writeSelfCheckStatus(master, deviceId, binding); writeSelfCheckStatus(master, deviceId, binding);
...@@ -188,16 +185,19 @@ public class AgingStageOneProcessJob implements Job { ...@@ -188,16 +185,19 @@ public class AgingStageOneProcessJob implements Job {
palletDeviceBindingMapper.updatePalletDeviceBinding(binding); palletDeviceBindingMapper.updatePalletDeviceBinding(binding);
log.info("设备{}处理完成: ip={}, port={}, status={}", deviceId, ip, port, result[1]); log.info("设备{}处理完成: ip={}, port={}, status={}", deviceId, ip, port, result[1]);
if((result[1] == 1 || result[1] == 3 || result[1] == 4) && "0".equals(binding.getWriteTimeStatus())) {
errorCount.incrementAndGet();
return false;
}
return true; return true;
} catch (Exception e) { } catch (Exception e) {
log.info("设备{}处理异常: ip={}, port={}", deviceId, ip, port, e); log.info("设备{}处理异常: ip={}, port={}", deviceId, ip, port, e);
if(binding == null) { if(binding != null) {
binding = palletDeviceBindingMapper.selectByTrayIdAndIndex(ip, deviceId); binding.setStatus("5");
binding.setWriteTimeStatus("0");
palletDeviceBindingMapper.updatePalletDeviceBinding(binding);
} }
binding.setStatus("5");
binding.setWriteTimeStatus("0");
palletDeviceBindingMapper.updatePalletDeviceBinding(binding);
errorCount.incrementAndGet(); errorCount.incrementAndGet();
return false; return false;
} finally { } finally {
......
...@@ -292,7 +292,7 @@ public class AgingStageThreeProcessJob implements Job { ...@@ -292,7 +292,7 @@ public class AgingStageThreeProcessJob implements Job {
systemYear, systemMonth, systemDay, systemHour, systemMinute); systemYear, systemMonth, systemDay, systemHour, systemMinute);
// 3. 比较时间差异 // 3. 比较时间差异
if (isTimeConsistent(deviceYear, deviceMonth, deviceDay, deviceHour, deviceMinute, if (Modbus4jUtils.isTimeConsistent(deviceYear, deviceMonth, deviceDay, deviceHour, deviceMinute,
systemYear, systemMonth, systemDay, systemHour, systemMinute)) { systemYear, systemMonth, systemDay, systemHour, systemMinute)) {
// 时间一致 // 时间一致
handleTimeConsistent(deviceId, binding); handleTimeConsistent(deviceId, binding);
...@@ -310,38 +310,12 @@ public class AgingStageThreeProcessJob implements Job { ...@@ -310,38 +310,12 @@ public class AgingStageThreeProcessJob implements Job {
} }
} }
/**
* 判断设备时间与系统时间是否一致(差异在2分钟内)
* 考虑跨年、跨月等边界情况
*/
private boolean isTimeConsistent(int deviceYear, int deviceMonth, int deviceDay,
int deviceHour, int deviceMinute,
int systemYear, int systemMonth, int systemDay,
int systemHour, int systemMinute) {
// 1. 首先检查年份差异(考虑跨年)
if (Math.abs(deviceYear - systemYear) > 1) {
log.debug("年份差异超过1年: 设备{}年 vs 系统{}年", deviceYear, systemYear);
return false;
}
// 2. 转换为总分钟数进行比较(考虑跨年、跨月、跨日)
long deviceTotalMinutes = calculateTotalMinutes(deviceYear, deviceMonth, deviceDay, deviceHour, deviceMinute);
long systemTotalMinutes = calculateTotalMinutes(systemYear, systemMonth, systemDay, systemHour, systemMinute);
long minuteDiff = Math.abs(deviceTotalMinutes - systemTotalMinutes);
log.debug("时间差异比较: 设备分钟数={}, 系统分钟数={}, 差异={}分钟",
deviceTotalMinutes, systemTotalMinutes, minuteDiff);
// 3. 差异在2分钟内认为一致
return minuteDiff <= 2;
}
/** /**
* 处理时间一致的情况 * 处理时间一致的情况
*/ */
private void handleTimeConsistent(int deviceId, PalletDeviceBinding binding) { private void handleTimeConsistent(int deviceId, PalletDeviceBinding binding) {
log.info("设备{}时间与系统时间一致,无需更新", deviceId); log.info("设备{}时间与系统时间一致,无需更新", deviceId);
binding.setWriteTimeStatus("1");
binding.setRunTimeStatus("1"); // 时间状态正常 binding.setRunTimeStatus("1"); // 时间状态正常
log.info("设备{}时间检查完成:时间一致", deviceId); log.info("设备{}时间检查完成:时间一致", deviceId);
} }
...@@ -383,39 +357,6 @@ public class AgingStageThreeProcessJob implements Job { ...@@ -383,39 +357,6 @@ public class AgingStageThreeProcessJob implements Job {
recordAlarmByBinding(binding, "设备时间更新异常: " + e.getMessage()); recordAlarmByBinding(binding, "设备时间更新异常: " + e.getMessage());
} }
} }
/**
* 计算从参考时间点(如2000年)开始的总分钟数
* 用于准确比较时间差异,考虑跨年跨月
*/
private long calculateTotalMinutes(int year, int month, int day, int hour, int minute) {
// 使用2000-01-01 00:00:00作为参考点
Calendar cal = Calendar.getInstance();
cal.set(Calendar.YEAR, 2000);
cal.set(Calendar.MONTH, Calendar.JANUARY);
cal.set(Calendar.DAY_OF_MONTH, 1);
cal.set(Calendar.HOUR_OF_DAY, 0);
cal.set(Calendar.MINUTE, 0);
cal.set(Calendar.SECOND, 0);
cal.set(Calendar.MILLISECOND, 0);
long baseTimeInMillis = cal.getTimeInMillis();
// 设置目标时间
cal.set(Calendar.YEAR, year);
cal.set(Calendar.MONTH, month - 1); // 转换为Calendar月份(0-based)
cal.set(Calendar.DAY_OF_MONTH, day);
cal.set(Calendar.HOUR_OF_DAY, hour);
cal.set(Calendar.MINUTE, minute);
cal.set(Calendar.SECOND, 0);
cal.set(Calendar.MILLISECOND, 0);
long targetTimeInMillis = cal.getTimeInMillis();
// 返回总分钟数
return (targetTimeInMillis - baseTimeInMillis) / (1000 * 60);
}
/** /**
* 写入当前时间到设备 * 写入当前时间到设备
*/ */
......
...@@ -228,7 +228,7 @@ public class RealTimeReadAgingDataFunction { ...@@ -228,7 +228,7 @@ public class RealTimeReadAgingDataFunction {
/** /**
* 处理单个设备(仅读取) * 处理单个设备(仅读取)
*/ */
private CompletableFuture<DeviceResult> processDevice(String ip, int port, int deviceId) { private CompletableFuture<DeviceResult> processDevice(String ip, int port, int deviceId) {
return CompletableFuture.supplyAsync(() -> { return CompletableFuture.supplyAsync(() -> {
try { try {
// 1. 异步读取设备数据 // 1. 异步读取设备数据
...@@ -478,4 +478,4 @@ public class RealTimeReadAgingDataFunction { ...@@ -478,4 +478,4 @@ public class RealTimeReadAgingDataFunction {
'}'; '}';
} }
} }
} }
\ No newline at end of file
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