Merge remote-tracking branch 'origin/master'
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user