dacoo-data-sdk-yongfeng/src/main/java/com/cisdi/data/AMETEKSurfaceVision/gateway/SurfaceVisionIoSession.java
2024-09-04 14:38:10 +08:00

292 lines
10 KiB
Java
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package com.cisdi.data.AMETEKSurfaceVision.gateway;
import com.alibaba.fastjson.JSON;
import com.cisdi.data.AMETEKSurfaceVision.DynamicCodeActionParamDTO;
import com.cisdi.data.AMETEKSurfaceVision.DynamicCodeActionParamDTO.PropertyConfig;
import com.cisdi.data.common.exception.BusinessException;
import com.cisdi.data.sdk.consts.ServiceName;
import com.cisdi.data.sdk.gateway.message.SocketMessage;
import com.cisdi.data.sdk.gateway.netty.IoSession;
import com.cisdi.data.sdk.gateway.netty.impl.AbstractIoSession;
import com.cisdi.data.sdk.service.DynamicCodecService;
import com.cisdi.data.sdk.service.SendService;
import com.cisdi.data.sdk.service.Service;
import com.cisdi.data.sdk.vo.ExeResultVo;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* 表检仪协议会话
*
* @author tzz
*/
public class SurfaceVisionIoSession extends AbstractIoSession implements IoSession {
private long lastAliveTime = System.currentTimeMillis();
private static Logger logger = LoggerFactory.getLogger(SurfaceVisionIoSession.class);
private String deviceId = null;
private String gwPrefixCache = null;
private final static byte[] beat = {0x07,0x7C,0x24,0x0D,0x0A};
private int count = 1;
// 初始化为0的原子整型变量作为计数器,用作发送命令的replayId,初始值为1
/** 当前下发命令replayId */
private Integer currentCount = -1;
public void setCurrentSend(SurfaceVisionSocketReturnMessage currentSend) {
this.currentSend = currentSend;
}
/** 当前下发命令信息 */
private SurfaceVisionSocketReturnMessage currentSend = null;
public void increment() {
if (count < SurfaceVisionConstants.MAX_COUNT) {
count++;
// 自增1并返回新值
}
else {
count = 1;
}
}
public int getCount() {
return count;
// 获取当前计数器的值
}
public SurfaceVisionIoSession(String deviceId) {
this.deviceId = deviceId;
}
@Override
public String[] getDeviceIds() {
return new String[0];
}
/** 获取当前下发电文点位配置信息 */
private List<PropertyConfig> getPropertyConfig(String msgKeyName){
//获取DynamicService
Service service = serviceProvider.getByName(ServiceName.DynamicCodec);
if (service == null || !(service instanceof DynamicCodecService)) {
throw new BusinessException("获取DynamicService失败");
}
//获取网关ID
String runId = socketGateway.getInstanceVo().getRunId();
//获取点位配置信息
DynamicCodecService dynamicCodecService = (DynamicCodecService)service;
String actionParam = dynamicCodecService.findByRunIdAndMsgKey(runId, msgKeyName);
DynamicCodeActionParamDTO dto = null;
try {
dto = JSON.parseObject(actionParam, DynamicCodeActionParamDTO.class);
} catch (Exception e) {
throw new BusinessException("连接id:" + runId + "电文号:" + msgKeyName + "json转换错误", e);
}
if (dto == null || dto.getPropertyList() == null || dto.getPropertyList().isEmpty()) {
throw new BusinessException("连接id:" + runId + "电文号:" + msgKeyName + "属性列表为空");
}
//返回点位信息
return dto.getPropertyList();
}
@Override
public void onRead(Object message) {
//获取表检仪上送或返回消息
ByteBuf inBuf = (ByteBuf) message;
int length = inBuf.readableBytes();
//将消息头和消息体拆包,解析出消息头信息
SurfaceVisionFrameInputVo vo = SurfaceVisionVoDecoder.Decode(inBuf);
logger.info("AMETEKSurfaceVision收到 msg: {}", vo);
//消息头,也是电文信息
String msgKey = vo.getMsgKey();
try {
//通过消息头判断返回消息类型
if(vo.getBeatType()){
//判断是否心跳信息
lastAliveTime = System.currentTimeMillis();
logger.info("接收到心跳消息,当前时间为:{}", lastAliveTime);
} else if (msgKey.startsWith(SurfaceVisionConstants.RETURN_HEADER1)) {
//非Query命令正常返回消息
//解码
SurfaceVisionVoDecoder.DecodeReturn(vo);
//组装返回信息判断replayId是否一致
ExeResultVo sendResult = new ExeResultVo();
if (!currentCount.equals(vo.getReplayId())) {
logger.info("AMETEKSurfaceVision收到 msgkey: {} 消息:{}, ReplayId{} 与实际发送下去的:{},不一致"
, msgKey, vo, vo.getReplayId(), currentCount);
sendResult.setSuccess(false);
sendResult.setMessage("返回消息replayId与发送消息replayId不符");
} else {
sendResult.setSuccess(vo.getStatus());
sendResult.setMessage(vo.getDescription());
}
//组装返回结果
returnData(sendResult);
} else if (SurfaceVisionConstants.RETURN_HEADER2.equals(msgKey)) {
//下发命令异常返回消息
//解码
SurfaceVisionVoDecoder.DecodeReturnError(vo);
ExeResultVo sendResult = new ExeResultVo();
sendResult.setSuccess(vo.getStatus());
sendResult.setMessage(vo.getDescription());
//组装返回结果
returnData(sendResult);
} else if (SurfaceVisionConstants.RETURN_HEADER3.equals(msgKey)) {
//Query命令返回
//解码
SurfaceVisionVoDecoder.DecodeReturnQuery(vo);
ExeResultVo sendResult = new ExeResultVo();
sendResult.setSuccess(vo.getStatus());
sendResult.setMessage(vo.getDescription());
Map<Object, Object> queryData = new HashMap<>();
queryData.putAll(vo.getReturnData());
sendResult.setData(queryData);
//组装返回结果
returnData(sendResult);
} else {
//主动上报消息
//解码
SurfaceVisionVoDecoder.DecodeData(vo, getPropertyConfig(msgKey));
Map<String, Object> realDataMap = vo.getReturnData();
//数据发送到平台
if (vo != null && serviceProvider != null && socketGateway != null) {
SendService service = (SendService) serviceProvider.getByName(ServiceName.Send);
//组装数据包
SocketMessage socketMessage = socketGateway.buildSocketMessage();
socketMessage.setDeviceId(deviceId);
socketMessage.getPropsMap().put(SurfaceVisionConstants.S_V_SEND_PLATFORM_DATA, realDataMap);
socketMessage.setMsgKey(msgKey);
//发送数据
service.sendMessage(socketMessage);
} else {
logger.info("AMETEKSurfaceVision收到 msgkey: {} 消息:{}, 但是不能发到平台", msgKey, JSON.toJSONString(realDataMap));
}
}
}catch (Exception e){
logger.error("AMETEKSurfaceVision接收消息匹配错误, msgKey: {}, msg:{}, error", msgKey, vo, e);
}
if(socketGateway!= null && Boolean.TRUE.equals(socketGateway.getInstanceVo().getLogOpen())) {
logger.info("AMETEKSurfaceVision {} 报文长度:{} vo:{} ", getChannel(), length, JSON.toJSONString(vo));
}
}
/** 设置当前下发命令返回信息 */
private void returnData(ExeResultVo sendResult) {
if(currentSend == null){
throw new BusinessException("下发返回消息没有对应的下发命令");
}
currentSend.setRealData(sendResult);
currentSend.setSendReturnFlag(true);
currentSend = null;
}
@Override
public void onOpen() {
super.onOpen();
logger.info("建立连接channel:{}", getChannel());
}
@Override
public void onClose() {
super.onClose();
}
public void close() {
if(getChannel() != null) {
try {
getChannel().close().sync();
} catch (InterruptedException e) {
logger.warn(e.getLocalizedMessage(), e);
}
}
}
public String gwPrefix() {
if(gwPrefixCache != null) {
return gwPrefixCache;
}
gwPrefixCache = "";
if(socketGateway != null && socketGateway.getInstanceVo() != null) {
gwPrefixCache = "网关Id:" + socketGateway.getInstanceVo().getRunId() + "连接:" + getChannel() + " ";
}else {
gwPrefixCache = "连接:" + getChannel() + " ";
}
return gwPrefixCache;
}
public long getLastAliveTime() {
return lastAliveTime;
}
@Override
public void send(Object message) {
//下发命令
SurfaceVisionSocketReturnMessage returnMsg = (SurfaceVisionSocketReturnMessage) message;
String msgKey = returnMsg.getMsgKey();
//与AMETEKSurfaceVisionSocketProtocol类对应
Map<String, Object> propsMap = (Map<String, Object>)
returnMsg.getPropsMap().get(SurfaceVisionConstants.S_V_SEND_DATA);
//获取下发点位配置
List<PropertyConfig> propertyConfigList = getPropertyConfig(msgKey);
//获取计数器值作为下发命令replayId
int c = getCount();
logger.info("下发数据, 数据:{}, 点位配置:{}, 返回ID:{}", propsMap, propertyConfigList, c);
ByteBuf byteBuf = SurfaceVisionEncoder.Encode(msgKey, propsMap, propertyConfigList, c);
logger.info("下发数据的byteBuf:{}", byteBuf);
//下发命令编码后发送
getChannel().writeAndFlush(byteBuf);
logger.info("下发数据成功");
//缓存当前下发命令信息和replayId
currentSend = returnMsg;
currentCount = c;
//计数器自增
increment();
}
public void sendBeat() {
logger.info("发送心跳");
ByteBuf byteBuf = Unpooled.wrappedBuffer(beat);
getChannel().writeAndFlush(byteBuf);
logger.info("心跳发送成功");
}
}