Merge remote-tracking branch 'origin/master'

This commit is contained in:
cdf
2025-08-12 10:39:32 +08:00
2 changed files with 314 additions and 107 deletions

View File

@@ -11,130 +11,260 @@ import com.njcn.gather.detection.pojo.vo.SocketDataMsg;
import com.njcn.gather.detection.pojo.vo.SocketMsg;
import com.njcn.gather.detection.pojo.vo.WebSocketVO;
import com.njcn.gather.detection.util.socket.*;
import com.njcn.gather.detection.util.socket.cilent.NettyClient;
import com.njcn.gather.detection.util.socket.cilent.NettyDevClientHandler;
import com.njcn.gather.detection.util.socket.websocket.WebServiceManager;
import com.njcn.gather.device.pojo.vo.PreDetection;
import com.njcn.gather.device.service.IPqDevService;
import com.njcn.gather.script.pojo.po.SourceIssue;
import com.njcn.gather.system.pojo.enums.DicDataEnum;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import java.util.*;
import java.util.stream.Collectors;
/**
* 程控源Socket响应处理服务
* <p>
* 该服务类负责处理来自程控源设备的Socket消息响应包括
* - 源初始化响应处理
* - 检测流程控制和状态管理
* - 相序检测、系数校验等特定检测类型的响应处理
* - WebSocket消息推送给前端用户
* - 错误处理和连接管理
* </p>
* <p>
* 主要处理的操作类型:
* - YJC_YTXJY: 源通信校验/源初始化
* - YJC_XUJY: 相序检测
* - FORMAL_REAL: 正式检测
* - Coefficient_Check: 系数校验
* - QUITE_SOURCE: 退出源连接
* </p>
*
* @author CN_Gather Detection Team
* @version 1.0
* @since 2023
*/
@Slf4j
@Service
@RequiredArgsConstructor
public class SocketSourceResponseService {
/**
* 向webSocket客户端发送消息
* 设备信息服务,提供设备基础信息查询功能
*/
private final SocketDevResponseService socketDevResponseService;
private final IPqDevService iPqDevService;
/**
* Socket连接管理器负责管理设备和源的Socket连接
*/
private final SocketManager socketManager;
/**
* 发送WebSocket消息到指定用户页面
* <p>
* 将数据对象转换为JSON字符串并通过WebSocket推送给前端用户
* 用于实时通知用户检测进度、状态变化或错误信息。
* </p>
*
* @param userPageId 用户页面ID用于标识消息接收方
* @param data 要发送的数据对象将被转换为JSON格式
*/
private void sendWebSocketMessage(String userPageId, Object data) {
WebServiceManager.sendMsg(userPageId, JSON.toJSONString(data));
}
/**
* 发送错误消息并退出源连接
* <p>
* 当检测过程中发生错误时,执行以下操作:
* 1. 主动断开与程控源的连接
* 2. 构造包含错误信息的Socket消息
* 3. 通过WebSocket将错误信息推送给前端用户
* </p>
*
* @param param 检测参数包含用户页面ID等信息
* @param socketDataMsg 原始Socket消息用于构造响应消息
* @param errorMessage 具体的错误描述信息
*/
private void sendErrorAndQuit(PreDetectionParam param, SocketDataMsg socketDataMsg, String errorMessage) {
CnSocketUtil.quitSendSource(param);
SocketMsg<String> socketMsg = new SocketMsg<>();
socketMsg.setRequestId(socketDataMsg.getRequestId());
socketMsg.setOperateCode(socketDataMsg.getOperateCode());
socketMsg.setData(errorMessage);
sendWebSocketMessage(param.getUserPageId(), socketMsg);
}
/**
* 发送错误消息并退出源连接(使用枚举消息)
* <p>
* 重载方法,使用预定义的错误码枚举来获取标准化的错误消息。
* 确保错误信息的一致性和规范性。
* </p>
*
* @param param 检测参数
* @param socketDataMsg 原始Socket消息
* @param errorCode 错误码枚举,包含标准化的错误描述
*/
private void sendErrorAndQuit(PreDetectionParam param, SocketDataMsg socketDataMsg, SourceResponseCodeEnum errorCode) {
sendErrorAndQuit(param, socketDataMsg, errorCode.getMessage());
}
/**
* 当前检测会话中的设备列表
* <p>
* 存储正在进行检测的设备信息,包含设备基本信息和监测点配置。
* 注意:该字段存在线程安全问题,建议后续重构为线程安全的设计。
* </p>
*/
private List<PreDetection> devList = new ArrayList<>();
/**
* 当前检测会话中的监测点ID列表
* <p>
* 从设备列表中提取的所有监测点ID集合用于向设备发送数据请求时指定监测范围。
* 与devList字段保持同步更新。
* </p>
*/
private List<String> monitorIdList = new ArrayList<>();
/**
* 程控源响应消息处理主入口
* <p>
* 根据消息中的操作码,分发到相应的处理方法:
* - 解析Socket消息提取操作码
* - 根据操作码类型调用对应的处理方法
* - 支持检测计划模式和模拟测试模式的区分处理
* </p>
* <p>
* 支持的操作类型:
* - YJC_YTXJY: 源通信校验/源初始化
* - YJC_XUJY: 相序检测
* - FORMAL_REAL: 正式检测
* - Coefficient_Check: 系数校验
* - QUITE_SOURCE: 退出源连接
* </p>
*
* @param param 检测参数包含用户ID、设备ID、计划ID等关键信息
* @param msg 从程控源接收的原始Socket消息
* @throws Exception 当消息解析失败或处理过程中发生异常时抛出
*/
public void deal(PreDetectionParam param, String msg) throws Exception {
// 解析接收到的Socket消息
SocketDataMsg socketDataMsg = MsgUtil.socketDataMsg(msg);
// 从requestId中提取操作码requestId格式为操作码_步骤标识
String[] tem = socketDataMsg.getRequestId().split(CnSocketUtil.STEP_TAG);
SourceOperateCodeEnum enumByCode = SourceOperateCodeEnum.getDictDataEnumByCode(tem[0]);
if (ObjectUtil.isNotNull(enumByCode)) {
switch (enumByCode) {
//源初始化
// 源初始化处理根据是否有计划ID判断是正式检测还是模拟检测
case YJC_YTXJY:
if (ObjectUtil.isNotNull(param.getPlanId())) {
// 有计划ID正式检测模式源初始化成功后启动设备检测
detectionDev(param, socketDataMsg);
} else {
// 程控源-源通信校验
// 无计划ID模拟检测模式仅进行源通信校验
handleYtxjySimulate(param, socketDataMsg);
}
break;
//相序检测
// 相序检测:检测设备的相序是否正确
case YJC_XUJY:
phaseSequenceDev(param, socketDataMsg);
break;
//正式检测
// 正式检测根据是否有计划ID选择不同的处理方式
case FORMAL_REAL:
if (ObjectUtil.isNotNull(param.getPlanId())) {
// 有计划ID向设备发送检测参数
senParamToDev(param, socketDataMsg);
} else {
// 无计划ID模拟测试模式
handleSimulateTest(param, socketDataMsg);
}
break;
//系数校验
// 系数校验:验证设备的计量系数是否准确
case Coefficient_Check:
coefficient(param, socketDataMsg);
break;
// 退出源连接:清理资源并关闭连接
case QUITE_SOURCE:
quitDeal(socketDataMsg, param);
break;
// YXT操作暂未实现具体功能
case YXT:
// TODO: 实现YXT操作的具体逻辑
break;
default:
// todo... 要日志记录或者websocket送到前端友好提示用户
// TODO: 记录未知操作码到日志,并向前端发送友好提示
break;
}
} else {
// todo... 要日志记录或者websocket送到前端友好提示用户
System.out.println("fggggggggggggggggggggg" + enumByCode);
// TODO: 向前端发送错误提示
log.error("程控源响应消息操作码解析失败,原始消息: {}, 解析结果: {}", msg, enumByCode);
}
}
/**
* 处理模拟检测中的源通信校验响应
* <p>
* 在模拟检测模式下(非计划检测),处理程控源的通信校验响应:
* - 成功时根据参数决定是否向前端发送WebSocket消息
* - 业务未处理:直接转发消息给前端
* - 各种错误情况:统一处理为退出源连接并通知前端
* </p>
* <p>
* 支持的错误类型包括:
* - 源连接错误、程控源错误、测试项解析错误
* - 源控制错误、目标源错误、未初始化错误
* - 未知错误、无法响应错误
* </p>
*
* @param param 检测参数包含用户信息和WebSocket消息发送控制
* @param socketDataMsg 程控源返回的响应消息
*/
private void handleYtxjySimulate(PreDetectionParam param, SocketDataMsg socketDataMsg) {
SourceResponseCodeEnum dictDataEnumByCode = SourceResponseCodeEnum.getDictDataEnumByCode(socketDataMsg.getCode());
if (ObjectUtil.isNotNull(dictDataEnumByCode)) {
switch (dictDataEnumByCode) {
case SUCCESS:
// 源初始化成功根据参数控制是否发送WebSocket消息
if (param.getSendWebMsg()) {
WebServiceManager.sendMsg(param.getUserPageId(), JSON.toJSONString(socketDataMsg));
sendWebSocketMessage(param.getUserPageId(), socketDataMsg);
}
System.out.println(param.getSendWebMsg() + "模拟检测-源初始化成功");
log.info("模拟检测源初始化成功,用户: {}, WebSocket发送: {}",
param.getUserPageId(), param.getSendWebMsg());
break;
case UNPROCESSED_BUSINESS:
WebServiceManager.sendMsg(param.getUserPageId(), JSON.toJSONString(socketDataMsg));
// 业务暂未处理:直接转发消息给前端等待处理
sendWebSocketMessage(param.getUserPageId(), socketDataMsg);
break;
// 各种错误情况:源连接错误、程控源控制错误、测试项解析错误等
case SOURCE_CONNECTION_ERROR:
CnSocketUtil.quitSendSource(param);
WebServiceManager.sendMsg(param.getUserPageId(), JSON.toJSONString(socketDataMsg));
break;
case CONTROLLED_SOURCE_ERROR:
CnSocketUtil.quitSendSource(param);
WebServiceManager.sendMsg(param.getUserPageId(), JSON.toJSONString(socketDataMsg));
break;
case TEST_ITEM_PARSING_ERROR:
CnSocketUtil.quitSendSource(param);
WebServiceManager.sendMsg(param.getUserPageId(), JSON.toJSONString(socketDataMsg));
break;
case SOURCE_CONTROL_ERROR:
CnSocketUtil.quitSendSource(param);
WebServiceManager.sendMsg(param.getUserPageId(), JSON.toJSONString(socketDataMsg));
break;
case TARGET_SOURCE_ERROR:
CnSocketUtil.quitSendSource(param);
WebServiceManager.sendMsg(param.getUserPageId(), JSON.toJSONString(socketDataMsg));
break;
case NOT_INITIALIZED:
CnSocketUtil.quitSendSource(param);
WebServiceManager.sendMsg(param.getUserPageId(), JSON.toJSONString(socketDataMsg));
break;
case UNKNOWN_ERROR:
CnSocketUtil.quitSendSource(param);
WebServiceManager.sendMsg(param.getUserPageId(), JSON.toJSONString(socketDataMsg));
break;
case UNABLE_TO_RESPOND:
// 所有错误情况统一处理:退出源连接并通知前端
CnSocketUtil.quitSendSource(param);
WebServiceManager.sendMsg(param.getUserPageId(), JSON.toJSONString(socketDataMsg));
sendWebSocketMessage(param.getUserPageId(), socketDataMsg);
break;
default:
// 未识别的响应码:发送通用错误消息
WebServiceManager.sendUnknownErrorMessage(param.getUserPageId());
break;
}
@@ -152,19 +282,15 @@ public class SocketSourceResponseService {
if (ObjectUtil.isNotNull(dictDataEnumByCode)) {
switch (dictDataEnumByCode) {
case SUCCESS:
WebServiceManager.sendMsg(param.getUserPageId(), JSON.toJSONString(socketDataMsg));
System.out.println("模拟检测-源成功执行脚本" + JSON.toJSONString(socketDataMsg));
sendWebSocketMessage(param.getUserPageId(), socketDataMsg);
log.info("模拟检测源成功执行脚本,用户: {}, 响应消息: {}",
param.getUserPageId(), JSON.toJSONString(socketDataMsg));
break;
case UNPROCESSED_BUSINESS:
WebServiceManager.sendMsg(param.getUserPageId(), JSON.toJSONString(socketDataMsg));
sendWebSocketMessage(param.getUserPageId(), socketDataMsg);
break;
default:
CnSocketUtil.quitSendSource(param);
SocketMsg<String> socketMsg = new SocketMsg<>();
socketMsg.setRequestId(socketDataMsg.getRequestId());
socketMsg.setOperateCode(socketDataMsg.getOperateCode());
socketMsg.setData(dictDataEnumByCode.getMessage());
WebServiceManager.sendMsg(param.getUserPageId(), JSON.toJSONString(socketMsg));
sendErrorAndQuit(param, socketDataMsg, dictDataEnumByCode);
break;
}
}
@@ -173,6 +299,23 @@ public class SocketSourceResponseService {
/**
* 系数校验源数据返回处理
* <p>
* 处理系数校验阶段程控源的响应消息:
* 1. 成功时:向前端推送响应信息,然后向设备发送数据请求
* 2. 构造设备数据请求参数,包含监测点列表和数据类型
* 3. 设置固定的读取参数读取3次数据忽略前4次
* 4. 请求的数据类型:实时电压有效值(real$VRMS)和实时电流有效值(real$IRMS)
* </p>
* <p>
* 数据请求配置:
* - 监测点使用当前会话的monitorIdList
* - 数据类型:["real$VRMS", "real$IRMS"]
* - 读取次数3次
* - 忽略次数4次预热数据
* </p>
*
* @param param 检测参数
* @param socketDataMsg 程控源响应消息
*/
private void coefficient(PreDetectionParam param, SocketDataMsg socketDataMsg) {
SourceResponseCodeEnum dictDataEnumByCode = SourceResponseCodeEnum.getDictDataEnumByCode(socketDataMsg.getCode());
@@ -181,29 +324,28 @@ public class SocketSourceResponseService {
switch (dictDataEnumByCode) {
case SUCCESS:
//向前端推送信息
WebServiceManager.sendMsg(param.getUserPageId(), JSON.toJSONString(socketDataMsg));
sendWebSocketMessage(param.getUserPageId(), socketDataMsg);
String s = param.getUserPageId() + CnSocketUtil.DEV_TAG;
socketMsg.setRequestId(SourceOperateCodeEnum.Coefficient_Check.getValue());
socketMsg.setOperateCode(SourceOperateCodeEnum.DEV_DATA_REQUEST_02.getValue());
DevPhaseSequenceParam phaseSequenceParam = new DevPhaseSequenceParam();
phaseSequenceParam.setMoniterIdList(monitorIdList);
// 系数校验固定检测项:实时电压有效值和实时电流有效值
phaseSequenceParam.setDataType(Arrays.asList("real$VRMS", "real$IRMS"));
// 读取3次数据用于系数计算
phaseSequenceParam.setReadCount(3);
// 忽略前4次数据等待测量稳定
phaseSequenceParam.setIgnoreCount(4);
socketMsg.setData(JSON.toJSONString(phaseSequenceParam));
SocketManager.sendMsg(s, JSON.toJSONString(socketMsg));
break;
case UNPROCESSED_BUSINESS:
WebServiceManager.sendMsg(param.getUserPageId(), JSON.toJSONString(socketDataMsg));
sendWebSocketMessage(param.getUserPageId(), socketDataMsg);
break;
default:
CnSocketUtil.quitSendSource(param);
socketMsg.setRequestId(socketDataMsg.getRequestId());
socketMsg.setOperateCode(socketDataMsg.getOperateCode());
socketMsg.setData(dictDataEnumByCode.getMessage());
WebServiceManager.sendMsg(param.getUserPageId(), JSON.toJSONString(socketMsg));
sendErrorAndQuit(param, socketDataMsg, dictDataEnumByCode);
break;
}
}
@@ -222,7 +364,7 @@ public class SocketSourceResponseService {
switch (dictDataEnumByCode) {
case SUCCESS:
//todo 前端推送收到的消息暂未处理好
WebServiceManager.sendMsg(param.getUserPageId(), JSON.toJSONString(socketDataMsg));
sendWebSocketMessage(param.getUserPageId(), socketDataMsg);
//开始设备通讯检测(发送设备初始化)
Map<String, List<PreDetection>> map = new HashMap<>(1);
map.put("deviceList", FormalTestManager.devList);
@@ -235,39 +377,18 @@ public class SocketSourceResponseService {
socketManager.smartSendToDevice(param, json);
break;
case UNPROCESSED_BUSINESS:
WebServiceManager.sendMsg(param.getUserPageId(), JSON.toJSONString(socketDataMsg));
sendWebSocketMessage(param.getUserPageId(), socketDataMsg);
break;
case SOURCE_CONNECTION_ERROR:
CnSocketUtil.quitSendSource(param);
WebServiceManager.sendMsg(param.getUserPageId(), JSON.toJSONString(socketDataMsg));
break;
case CONTROLLED_SOURCE_ERROR:
CnSocketUtil.quitSendSource(param);
WebServiceManager.sendMsg(param.getUserPageId(), JSON.toJSONString(socketDataMsg));
break;
case TEST_ITEM_PARSING_ERROR:
CnSocketUtil.quitSendSource(param);
WebServiceManager.sendMsg(param.getUserPageId(), JSON.toJSONString(socketDataMsg));
break;
case SOURCE_CONTROL_ERROR:
CnSocketUtil.quitSendSource(param);
WebServiceManager.sendMsg(param.getUserPageId(), JSON.toJSONString(socketDataMsg));
break;
case TARGET_SOURCE_ERROR:
CnSocketUtil.quitSendSource(param);
WebServiceManager.sendMsg(param.getUserPageId(), JSON.toJSONString(socketDataMsg));
break;
case NOT_INITIALIZED:
CnSocketUtil.quitSendSource(param);
WebServiceManager.sendMsg(param.getUserPageId(), JSON.toJSONString(socketDataMsg));
break;
case UNKNOWN_ERROR:
CnSocketUtil.quitSendSource(param);
WebServiceManager.sendMsg(param.getUserPageId(), JSON.toJSONString(socketDataMsg));
break;
case UNABLE_TO_RESPOND:
CnSocketUtil.quitSendSource(param);
WebServiceManager.sendMsg(param.getUserPageId(), JSON.toJSONString(socketDataMsg));
sendWebSocketMessage(param.getUserPageId(), socketDataMsg);
break;
default:
// todo... 这种情况是报文的状态码不一致,需要记录到日志表,以便问题追踪
@@ -292,7 +413,7 @@ public class SocketSourceResponseService {
switch (dictDataEnumByCode) {
case SUCCESS:
//向前端推送信息
WebServiceManager.sendMsg(param.getUserPageId(), JSON.toJSONString(socketDataMsg));
sendWebSocketMessage(param.getUserPageId(), socketDataMsg);
String s = param.getUserPageId() + CnSocketUtil.DEV_TAG;
socketMsg.setRequestId(SourceOperateCodeEnum.YJC_XUJY.getValue());
@@ -304,24 +425,23 @@ public class SocketSourceResponseService {
DevPhaseSequenceParam phaseSequenceParam = new DevPhaseSequenceParam();
phaseSequenceParam.setMoniterIdList(moniterIdList);
// 相序检测项:电压有效值、电压角度、电流有效值、电流角度
phaseSequenceParam.setDataType(Arrays.asList("real$VRMS", "real$VA", "real$IRMS", "real$IA"));
// 相序检测只需要读取1次数据
phaseSequenceParam.setReadCount(1);
// 忽略前10次数据确保相序稳定
phaseSequenceParam.setIgnoreCount(10);
socketMsg.setData(JSON.toJSONString(phaseSequenceParam));
SocketManager.sendMsg(s, JSON.toJSONString(socketMsg));
break;
case UNPROCESSED_BUSINESS:
WebServiceManager.sendMsg(param.getUserPageId(), JSON.toJSONString(socketDataMsg));
sendWebSocketMessage(param.getUserPageId(), socketDataMsg);
break;
case MESSAGE_PARSING_ERROR:
CnSocketUtil.quitSendSource(param);
break;
default:
CnSocketUtil.quitSendSource(param);
socketMsg.setRequestId(socketDataMsg.getRequestId());
socketMsg.setOperateCode(socketDataMsg.getOperateCode());
socketMsg.setData(dictDataEnumByCode.getMessage());
WebServiceManager.sendMsg(param.getUserPageId(), JSON.toJSONString(socketMsg));
sendErrorAndQuit(param, socketDataMsg, dictDataEnumByCode);
break;
}
}
@@ -329,10 +449,28 @@ public class SocketSourceResponseService {
/**
* 组装和装置要数据
* 正式检测时向设备发送参数请求
* <p>
* 当程控源成功执行脚本后,根据检测项目类型向设备发送相应的数据请求:
* 1. 获取源脚本信息,确定检测类型和数据类型
* 2. 根据检测类型设置不同的读取参数:
* - 闪变(F)忽略1次读取2次使用DEV_DATA_REQUEST_01
* - 暂态(VOLTAGE)忽略5次读取1次使用DEV_DATA_REQUEST_03
* - 其他类型忽略5次读取5次根据数据类型选择操作码
* 3. 构造设备数据请求并发送
* 4. 向前端推送检测开始信息
* </p>
* <p>
* 检测参数配置:
* - 闪变检测ignoreCount=1, readCount=2
* - 暂态检测ignoreCount=5, readCount=1
* - 常规检测ignoreCount=5, readCount=5
* - 实时数据使用DEV_DATA_REQUEST_02
* - 分钟数据使用DEV_DATA_REQUEST_01
* </p>
*
* @param param
* @param socketDataMsg
* @param param 检测参数,包含用户和设备信息
* @param socketDataMsg 程控源成功响应消息
*/
private void senParamToDev(PreDetectionParam param, SocketDataMsg socketDataMsg) {
SourceResponseCodeEnum dictDataEnumByCode = SourceResponseCodeEnum.getDictDataEnumByCode(socketDataMsg.getCode());
@@ -343,42 +481,71 @@ public class SocketSourceResponseService {
//向前端推送信息
// webSocketHandler.sendMsgToUser(param.getUserPageId(), JSON.toJSONString(socketDataMsg));
// 构造设备通道标识用户ID + 设备标签
String s = param.getUserPageId() + CnSocketUtil.DEV_TAG;
// 获取当前检测的源脚本信息,包含检测类型和数据要求
SourceIssue sourceIssue = SocketManager.getSourceList().get(0);
List<String> comm = sourceIssue.getDevValueTypeList(); //形如:类型&小项code这种形式。例如real$VRMS、real$IRMS
System.out.println("向装置下发的参数>>>>>>>>" + comm);
// 数据类型列表,格式real$VRMS、real$IRMS
List<String> comm = sourceIssue.getDevValueTypeList();
log.debug("向设备下发检测参数,用户: {}, 数据类型: {}", param.getUserPageId(), comm);
// 设置请求ID正式检测操作码 + 步骤标识 + 检测类型
socketMsg.setRequestId(SourceOperateCodeEnum.FORMAL_REAL.getValue() + CnSocketUtil.STEP_TAG + sourceIssue.getType());
// 根据检测类型设置不同的读取参数和操作码
int ignoreCount;
int readData;
if (DicDataEnum.F.getCode().equals(sourceIssue.getType())) {
// 闪变检测:数据变化较慢,只需少量预热和读取
// 闪变测量稳定性好预热1次即可
ignoreCount = 1;
// 读取2次数据计算闪变值
readData = 2;
socketMsg.setOperateCode(SourceOperateCodeEnum.DEV_DATA_REQUEST_01.getValue());
} else if (DicDataEnum.VOLTAGE.getCode().equals(sourceIssue.getType())) {
// 暂态电压检测:需要更多预热时间,但只读取一次快照
// 暂态事件需要5次预热确保触发稳定
ignoreCount = 5;
// 暂态检测只需要捕获一次事件
readData = 1;
socketMsg.setOperateCode(SourceOperateCodeEnum.DEV_DATA_REQUEST_03.getValue());
} else {
// 常规检测(谐波、不平衡度等):需要多次采样以提高精度
// 常规检测预热5次等待稳定
ignoreCount = 5;
// 读取5次数据进行统计分析
readData = 5;
//区分实时数据还是分钟数据
// 根据数据类型选择相应的请求操作码
if ("real".equals(sourceIssue.getDataType())) {
// 实时数据:瞬时值或有效值
socketMsg.setOperateCode(SourceOperateCodeEnum.DEV_DATA_REQUEST_02.getValue());
} else {
// 分钟数据:统计周期内的平均值或累计值
socketMsg.setOperateCode(SourceOperateCodeEnum.DEV_DATA_REQUEST_01.getValue());
}
}
System.out.println("devList is empty:" + CollectionUtils.isEmpty(devList));
log.debug("检测设备列表状态检查,用户: {}, 设备列表为空: {}",
param.getUserPageId(), CollectionUtils.isEmpty(devList));
//List<String> moniterIdList = devList.stream().flatMap(x -> x.getMonitorList().stream()).map(PreDetection.MonitorListDTO::getLineId).collect(Collectors.toList());
// 构造设备数据请求参数
DevPhaseSequenceParam phaseSequenceParam = new DevPhaseSequenceParam();
// 设置监测点ID列表
phaseSequenceParam.setMoniterIdList(monitorIdList);
// 设置数据类型列表
phaseSequenceParam.setDataType(comm);
// 设置读取次数
phaseSequenceParam.setReadCount(readData);
// 设置忽略次数
phaseSequenceParam.setIgnoreCount(ignoreCount);
socketMsg.setData(JSON.toJSONString(phaseSequenceParam));
// 向设备发送数据请求
SocketManager.sendMsg(s, JSON.toJSONString(socketMsg));
// 构造前端显示的设备列表只包含设备ID和名称
List<DevLineTestResult> devListRes = new ArrayList<>();
devList.forEach(item -> {
DevLineTestResult devLineTestResult = new DevLineTestResult();
@@ -387,21 +554,21 @@ public class SocketSourceResponseService {
devListRes.add(devLineTestResult);
});
// 构造WebSocket消息并推送给前端通知检测开始
WebSocketVO<Object> webSocketVO = new WebSocketVO<>();
// 设置请求ID检测类型 + 开始标识
webSocketVO.setRequestId(socketDataMsg.getRequestId().split(CnSocketUtil.STEP_TAG)[1] + CnSocketUtil.START_TAG);
// 检测描述信息
webSocketVO.setDesc(SocketManager.getSourceList().get(0).getDesc());
// 参与检测的设备列表
webSocketVO.setData(devListRes);
WebServiceManager.sendMsg(param.getUserPageId(), JSON.toJSONString(webSocketVO));
sendWebSocketMessage(param.getUserPageId(), webSocketVO);
break;
case UNPROCESSED_BUSINESS:
WebServiceManager.sendMsg(param.getUserPageId(), JSON.toJSONString(socketDataMsg));
sendWebSocketMessage(param.getUserPageId(), socketDataMsg);
break;
default:
CnSocketUtil.quitSendSource(param);
socketMsg.setRequestId(socketDataMsg.getRequestId());
socketMsg.setOperateCode(socketDataMsg.getOperateCode());
socketMsg.setData(dictDataEnumByCode.getMessage());
WebServiceManager.sendMsg(param.getUserPageId(), JSON.toJSONString(socketMsg));
sendErrorAndQuit(param, socketDataMsg, dictDataEnumByCode);
break;
}
}
@@ -409,7 +576,23 @@ public class SocketSourceResponseService {
/**
* 退出检测返回
* 处理退出检测的响应
* <p>
* 当用户主动退出检测或系统需要终止检测时,处理程控源的退出响应:
* - 成功退出移除Socket连接管理中的用户信息向前端发送成功消息
* - 业务未处理:不做特殊处理
* - 消息解析错误/无法响应:移除用户连接信息
* - 其他错误:调用退出源连接方法
* </p>
* <p>
* 退出流程:
* 1. 解析响应状态码
* 2. 根据状态码执行相应的清理操作
* 3. 确保Socket连接资源得到正确释放
* </p>
*
* @param socketDataMsg 程控源退出响应消息
* @param param 检测参数,包含用户信息
*/
private void quitDeal(SocketDataMsg socketDataMsg, PreDetectionParam param) {
SourceResponseCodeEnum dictDataEnumByCode = SourceResponseCodeEnum.getDictDataEnumByCode(socketDataMsg.getCode());
@@ -417,7 +600,7 @@ public class SocketSourceResponseService {
case SUCCESS:
//通讯校验成功
SocketManager.removeUser(param.getUserPageId() + CnSocketUtil.SOURCE_TAG);
WebServiceManager.sendMsg(param.getUserPageId(), JSON.toJSONString(socketDataMsg));
sendWebSocketMessage(param.getUserPageId(), socketDataMsg);
break;
case UNPROCESSED_BUSINESS:
break;
@@ -435,13 +618,37 @@ public class SocketSourceResponseService {
}
/**
* 初始化检测设备和监测点列表
* <p>
* 在开始检测前,根据检测参数初始化当前会话的设备信息:
* 1. 清空之前的设备列表和监测点列表
* 2. 根据设备ID列表查询设备详细信息
* 3. 从设备信息中提取所有监测点的线路ID
* 4. 同步更新XiNumberManager中的设备列表
* </p>
* <p>
* 该方法通常在检测开始前调用,确保后续的检测流程能够获取到正确的
* 设备配置和监测点信息。
* </p>
*
* @param param 检测参数包含要检测的设备ID列表
*/
public void initList(PreDetectionParam param) {
// 清空现有列表,为新的检测会话做准备
devList.clear();
monitorIdList.clear();
// 查询设备详细信息,包含监测点配置
this.devList = iPqDevService.getDevInfo(param.getDevIds());
this.monitorIdList = devList.stream().flatMap(x -> x.getMonitorList().stream())
// 提取所有设备的监测点线路ID
this.monitorIdList = devList.stream()
.flatMap(x -> x.getMonitorList().stream())
.map(PreDetection.MonitorListDTO::getLineId)
.collect(Collectors.toList());
// 同步更新系数管理器中的设备列表
XiNumberManager.xiDevList = devList;
}

View File

@@ -37,7 +37,7 @@ public class CnSocketUtil {
socketMsg.setRequestId(SourceOperateCodeEnum.QUITE.getValue());
socketMsg.setOperateCode(SourceOperateCodeEnum.QUIT_INIT_03.getValue());
SocketManager.sendMsg(param.getUserPageId() + DEV_TAG, JSON.toJSONString(socketMsg));
WebServiceManager.removePreDetectionParam();
WebServiceManager.removePreDetectionParam(param.getUserPageId());
}
/**
@@ -51,7 +51,7 @@ public class CnSocketUtil {
jsonObject.put("sourceId", param.getSourceId());
socketMsg.setData(jsonObject.toJSONString());
SocketManager.sendMsg(param.getUserPageId() + SOURCE_TAG, JSON.toJSONString(socketMsg));
WebServiceManager.removePreDetectionParam();
WebServiceManager.removePreDetectionParam(param.getUserPageId());
}
@@ -64,7 +64,7 @@ public class CnSocketUtil {
socketMsg.setRequestId(SourceOperateCodeEnum.QUITE.getValue());
socketMsg.setOperateCode(SourceOperateCodeEnum.QUIT_INIT_02.getValue());
SocketManager.sendMsg(loginName + CONTRAST_DEV_TAG, JSON.toJSONString(socketMsg));
WebServiceManager.removePreDetectionParam();
WebServiceManager.removePreDetectionParam(loginName);
FormalTestManager.currentStep=SourceOperateCodeEnum.QUITE;
}
}