Commit 1f857407 authored by wanghao's avatar wanghao

1 测试 上电后通信 和 最终完成 定时任务功能

parent bec4920b
package com.zehong.system.task;
import com.zehong.system.domain.TEquipmentAlarmData;
import com.zehong.system.domain.TStoreyInfo;
import com.zehong.system.mapper.TStoreyInfoMapper;
import com.zehong.system.modbus.business.DeviceStatusReaderAndTimeSetter;
import com.zehong.system.modbus.handler.ModbusResultHandler;
import com.zehong.system.service.ITEquipmentAlarmDataService;
import org.apache.commons.lang3.StringUtils;
import org.quartz.Job;
import org.quartz.JobDataMap;
import org.quartz.JobExecutionContext;
......@@ -12,8 +14,10 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
/**
......@@ -37,37 +41,91 @@ public class DeviceCommunicationJob implements Job {
@Override
public void execute(JobExecutionContext context) {
JobDataMap data = context.getJobDetail().getJobDataMap();
String fStoreyId = data.getString("fStoreyId");
log.info("DeviceCommunicationJob.execute 的 fStoreyId:{}", fStoreyId);
long l = Long.parseLong(fStoreyId);
TStoreyInfo tStoreyInfo = tStoreyInfoMapper.selectTStoreyInfoById(l);
// 1. 初始化所有变量,避免空指针
JobDataMap data = null;
String fStoreyIdStr = null;
Long fStoreyId = null;
TStoreyInfo tStoreyInfo = null;
String ip = null;
try {
// 1. 执行Modbus通信
String s = tStoreyInfo.getfPort();
String ip = tStoreyInfo.getfIp();
// 501 的 27个 设备id
List<Integer> registerOffsetsOne = 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);
// 501 对应 27个设备读取状态 并设置时间
deviceStatusReaderAndTimeSetter.startMultiDeviceMonitoring(ip,501, registerOffsetsOne, resultHandler, ModbusResultHandler.createDefaultStopCondition());
// 2. 提取参数(每一步都校验,避免空指针)
data = context.getJobDetail().getJobDataMap();
if (data == null) {
log.error("JobDataMap为空,终止执行");
return;
}
fStoreyIdStr = data.getString("fStoreyId");
if (StringUtils.isBlank(fStoreyIdStr)) {
log.error("fStoreyId参数为空,终止执行");
return;
}
// 3. 转换参数(处理NumberFormatException)
try {
fStoreyId = Long.parseLong(fStoreyIdStr);
} catch (NumberFormatException e) {
log.error("fStoreyId格式错误:{},终止执行", fStoreyIdStr);
return;
}
// 4. 查询设备信息(校验DB查询结果)
tStoreyInfo = tStoreyInfoMapper.selectTStoreyInfoById(fStoreyId);
if (tStoreyInfo == null) {
log.error("未查询到设备信息:fStoreyId={},终止执行", fStoreyId);
return;
}
ip = tStoreyInfo.getfIp();
if (StringUtils.isBlank(ip)) {
log.error("设备IP为空:fStoreyId={},终止执行", fStoreyId);
return;
}
// 5. 执行Modbus通信(业务逻辑,每个调用都加try-catch)
List<Integer> offsets1 = 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);
List<Integer> offsets2 = 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);
List<Integer> offsets3 = Arrays.asList(55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72);
// 502 端口号的 27个 设备id
List<Integer> registerOffsetsTwo = 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);
// 502 对应 27个设备读取状态 并设置时间
deviceStatusReaderAndTimeSetter.startMultiDeviceMonitoring(ip, 502, registerOffsetsTwo, resultHandler, ModbusResultHandler.createDefaultStopCondition());
// 每个Modbus调用单独捕获异常,避免一个设备失败导致整个Job报错
try {
deviceStatusReaderAndTimeSetter.startMultiDeviceMonitoring(ip, 501, offsets1, resultHandler, ModbusResultHandler.createDefaultStopCondition());
log.info("Modbus 501端口通信完成:fStoreyId={}", fStoreyId);
} catch (Exception e) {
log.error("Modbus 501端口通信异常:fStoreyId={}", fStoreyId, e);
// 仅记录日志,不抛出异常
}
try {
deviceStatusReaderAndTimeSetter.startMultiDeviceMonitoring(ip, 502, offsets2, resultHandler, ModbusResultHandler.createDefaultStopCondition());
log.info("Modbus 502端口通信完成:fStoreyId={}", fStoreyId);
} catch (Exception e) {
log.error("Modbus 502端口通信异常:fStoreyId={}", fStoreyId, e);
}
try {
deviceStatusReaderAndTimeSetter.startMultiDeviceMonitoring(ip, 503, offsets3, resultHandler, ModbusResultHandler.createDefaultStopCondition());
log.info("Modbus 503端口通信完成:fStoreyId={}", fStoreyId);
} catch (Exception e) {
log.error("Modbus 503端口通信异常:fStoreyId={}", fStoreyId, e);
}
// 503 端口号的 剩下的设备
List<Integer> registerOffsetsThree = Arrays.asList(55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71,72);
// 503 对应 剩下设备读取状态 并设置时间
deviceStatusReaderAndTimeSetter.startMultiDeviceMonitoring(ip, 503, registerOffsetsThree, resultHandler, ModbusResultHandler.createDefaultStopCondition());
log.info("=== DeviceCommunicationJob 执行成功:fStoreyId={} ===", fStoreyId);
} catch (Exception e) {
// 记录异常
TEquipmentAlarmData alarmData = new TEquipmentAlarmData();
alarmData.setfAlarmType("03"); // 老化层
alarmData.setfEquipmentCode(tStoreyInfo.getfStoreyCode());
alarmData.setfAlarmData("通信失败: " + e.getMessage());
alarmDataService.insertTEquipmentAlarmData(alarmData);
} catch (Throwable e) {
// 6. 捕获所有异常(包括Error,如NoClassDefFoundError)
log.error("=== DeviceCommunicationJob 执行致命异常:fStoreyId={} ===", fStoreyIdStr, e);
// 记录告警(内部异常也不抛出,确保Job不传播任何错误)
try {
if (tStoreyInfo != null && StringUtils.isNotBlank(tStoreyInfo.getfStoreyCode())) {
TEquipmentAlarmData alarm = new TEquipmentAlarmData();
alarm.setfAlarmType("03");
alarm.setfEquipmentCode(tStoreyInfo.getfStoreyCode());
alarm.setfAlarmData("通信任务异常:" + e.getMessage());
alarm.setfCreateTime(new Date());
alarmDataService.insertTEquipmentAlarmData(alarm);
}
} catch (Exception alarmEx) {
log.error("=== 告警记录失败(不影响触发器) ===", alarmEx);
}
// 绝对禁止抛出任何异常!!!
}
}
}
......@@ -46,49 +46,134 @@ public class FinalExecutionJob implements Job {
private RobotArmCommandMapper robotArmCommandMapper;
@Override
public void execute(JobExecutionContext context) {
JobDataMap data = context.getJobDetail().getJobDataMap();
String fStoreyId = data.getString("fStoreyId");
String fPowerOutageIp = data.getString("fPowerOutageIp");
String fPowerOutagePort = data.getString("fPowerOutagePort");
TStoreyInfo tStoreyInfo = tStoreyInfoMapper.selectTStoreyInfoById(Long.parseLong(fStoreyId));
if(tStoreyInfo == null || StringUtils.isBlank(fPowerOutagePort) || StringUtils.isBlank(fPowerOutageIp)) {
// 记录异常
TEquipmentAlarmData alarmData = new TEquipmentAlarmData();
alarmData.setfAlarmType("03"); // 老化层
alarmData.setfEquipmentCode(fStoreyId);
alarmData.setfAlarmData("71小时到老化层业务逻辑时数据丢失");
alarmDataService.insertTEquipmentAlarmData(alarmData);
} else{
// 1. 初始化变量,避免空指针
JobDataMap data = null;
String fStoreyIdStr = null;
String fPowerOutageIp = null;
String fPowerOutagePortStr = null;
Long fStoreyId = null;
Integer fPowerOutagePort = null;
TStoreyInfo tStoreyInfo = null;
try {
// 2. 提取并校验所有参数
data = context.getJobDetail().getJobDataMap();
if (data == null) {
log.error("JobDataMap为空,终止执行");
return;
}
fStoreyIdStr = data.getString("fStoreyId");
fPowerOutageIp = data.getString("fPowerOutageIp");
fPowerOutagePortStr = data.getString("fPowerOutagePort");
if (StringUtils.isAnyBlank(fStoreyIdStr, fPowerOutageIp, fPowerOutagePortStr)) {
log.error("参数缺失:fStoreyId={}, ip={}, port={},终止执行", fStoreyIdStr, fPowerOutageIp, fPowerOutagePortStr);
return;
}
// 3. 参数格式转换(处理NumberFormatException)
try {
log.info("设备[{}]开始执行最终业务逻辑", tStoreyInfo.getfStoreyCode());
fStoreyId = Long.parseLong(fStoreyIdStr);
fPowerOutagePort = Integer.parseInt(fPowerOutagePortStr);
} catch (NumberFormatException e) {
log.error("参数格式错误:fStoreyId={}, port={},终止执行", fStoreyIdStr, fPowerOutagePortStr);
return;
}
// 1. 执行业务逻辑
String s = tStoreyInfo.getfStoreyCode().split("-")[1];
int i = Integer.parseInt(s);
executeBusinessLogic(fPowerOutageIp,Integer.parseInt(fPowerOutagePort),(i - 1));
// 4. 查询设备信息
tStoreyInfo = tStoreyInfoMapper.selectTStoreyInfoById(fStoreyId);
if (tStoreyInfo == null) {
log.error("未查询到设备信息:fStoreyId={},终止执行", fStoreyId);
return;
}
// 2. 更新任务状态
// 5. 执行业务逻辑(Modbus写操作,单独捕获异常)
String storeyCode = tStoreyInfo.getfStoreyCode();
if (StringUtils.isBlank(storeyCode)) {
log.error("设备编码为空:fStoreyId={},终止执行", fStoreyId);
return;
}
int registerOffsets;
try {
registerOffsets = Integer.parseInt(storeyCode.split("-")[1]) - 1;
} catch (Exception e) {
log.error("设备编码解析失败:storeyCode={},终止执行", storeyCode);
return;
}
// Modbus写操作(容错:失败不影响后续清理任务)
try {
executeBusinessLogic(fPowerOutageIp, fPowerOutagePort, registerOffsets);
log.info("Modbus写操作完成:fStoreyId={}", fStoreyId);
} catch (Exception e) {
log.error("Modbus写操作异常:fStoreyId={}", fStoreyId, e);
// 记录告警,但不终止执行(后续清理任务必须执行)
recordAlarm(tStoreyInfo, "Modbus写操作失败:" + e.getMessage());
}
// 6. 更新设备状态(DB操作单独捕获异常)
try {
tStoreyInfo.setfStatus("0");
tStoreyInfo.setfAgingStartTime(null);
tStoreyInfoService.updateTStoreyInfo(tStoreyInfo);
log.info("设备状态更新完成:fStoreyId={}", fStoreyId);
} catch (Exception e) {
log.error("设备状态更新异常:fStoreyId={}", fStoreyId, e);
recordAlarm(tStoreyInfo, "设备状态更新失败:" + e.getMessage());
}
// 3. 清理相关任务
cleanUpJobs(fStoreyId,context);
// 4. 发送 下料指令
createRoboticArm(tStoreyInfo.getfTrayCode(),tStoreyInfo.getfStoreyCode(),tStoreyInfo.getBlankingCommand());
// 7. 清理任务(Quartz操作单独捕获异常)
try {
cleanUpJobs(fStoreyId, context);
log.info("任务清理完成:fStoreyId={}", fStoreyId);
} catch (Exception e) {
log.error("任务清理异常:fStoreyId={}", fStoreyId, e);
recordAlarm(tStoreyInfo, "任务清理失败:" + e.getMessage());
}
log.info("设备[{}]最终业务逻辑执行完成", fStoreyId);
// 8. 发送机械臂指令(单独捕获异常)
try {
createRoboticArm(tStoreyInfo.getfTrayCode(), storeyCode, tStoreyInfo.getBlankingCommand());
log.info("机械臂指令发送完成:fStoreyId={}", fStoreyId);
} catch (Exception e) {
// 记录异常
TEquipmentAlarmData alarmData = new TEquipmentAlarmData();
alarmData.setfAlarmType("03"); // 老化层
alarmData.setfEquipmentCode(tStoreyInfo.getfStoreyCode());
alarmData.setfAlarmData("老化层清除任务时失败");
alarmDataService.insertTEquipmentAlarmData(alarmData);
log.error("机械臂指令发送异常:fStoreyId={}", fStoreyId, e);
recordAlarm(tStoreyInfo, "机械臂指令发送失败:" + e.getMessage());
}
log.info("=== FinalExecutionJob 执行完成:fStoreyId={} ===", fStoreyId);
} catch (Throwable e) {
// 9. 捕获所有异常(包括Error)
log.error("=== FinalExecutionJob 致命异常:fStoreyId={} ===", fStoreyIdStr, e);
// 记录告警(即使设备信息为空,也尝试记录)
try {
if (tStoreyInfo != null && StringUtils.isNotBlank(tStoreyInfo.getfStoreyCode())) {
recordAlarm(tStoreyInfo, "最终任务致命异常:" + e.getMessage());
} else {
TEquipmentAlarmData alarm = new TEquipmentAlarmData();
alarm.setfAlarmType("03");
alarm.setfEquipmentCode(fStoreyIdStr);
alarm.setfAlarmData("最终任务致命异常:" + e.getMessage());
alarm.setfCreateTime(new Date());
alarmDataService.insertTEquipmentAlarmData(alarm);
}
} catch (Exception alarmEx) {
log.error("=== 告警记录失败 ===", alarmEx);
}
// 禁止抛出任何异常!!!
}
}
// 辅助方法:记录告警(抽离,避免代码重复)
private void recordAlarm(TStoreyInfo tStoreyInfo, String alarmMsg) {
try {
TEquipmentAlarmData alarm = new TEquipmentAlarmData();
alarm.setfAlarmType("03");
alarm.setfEquipmentCode(tStoreyInfo.getfStoreyCode());
alarm.setfAlarmData(alarmMsg);
alarm.setfCreateTime(new Date());
alarmDataService.insertTEquipmentAlarmData(alarm);
log.info("告警记录完成:{}", tStoreyInfo.getfStoreyCode());
} catch (Exception e) {
log.error("告警记录失败:{}", tStoreyInfo.getfStoreyCode(), e);
}
}
......@@ -105,12 +190,19 @@ public class FinalExecutionJob implements Job {
notifyCommandsUpdate();
}
private void cleanUpJobs(String deviceId,JobExecutionContext context) throws SchedulerException {
// 删除通信任务
scheduler.deleteJob(new JobKey("COMM_" + deviceId, "DEVICE_TASKS"));
// 删除自身任务
scheduler.deleteJob(context.getJobDetail().getKey());
private void cleanUpJobs(Long fStoreyId,JobExecutionContext context) throws SchedulerException {
// 清理通信任务
JobKey commJobKey = new JobKey("COMM_" + fStoreyId, "DEVICE_TASKS");
if (scheduler.checkExists(commJobKey)) {
boolean commDeleted = scheduler.deleteJob(commJobKey);
log.info("通信任务清理结果:{}({})", commDeleted ? "成功" : "失败", commJobKey.getName());
}
// 清理自身任务
JobKey selfJobKey = context.getJobDetail().getKey();
if (scheduler.checkExists(selfJobKey)) {
boolean selfDeleted = scheduler.deleteJob(selfJobKey);
log.info("自身任务清理结果:{}({})", selfDeleted ? "成功" : "失败", selfJobKey.getName());
}
}
// ... 业务逻辑方法
......
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