package com.fzzy.protocol.zldz.analysis; import com.fzzy.api.utils.BytesUtil; import com.fzzy.api.utils.ContextUtil; import com.fzzy.gateway.data.BaseReqData; import com.fzzy.gateway.entity.GatewayDevice; import com.fzzy.io.request.BaseRequest; import com.fzzy.protocol.ProtocolUtils; import com.fzzy.protocol.zldz.data.ReMessage; import com.fzzy.protocol.zldz.service.ZldzGatewayGrainService; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.springframework.stereotype.Component; import org.springframework.transaction.annotation.Transactional; import javax.annotation.Resource; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; /** * 粮情解析 * * @author Andy */ @Slf4j @Component(AnalysisGrain.BEAN_ID) public class AnalysisGrain { public static final String BEAN_ID = "zldz.analysisGrain"; @Resource private ZldzGatewayGrainService zldzGatewayGrainService; public static Map> contextMap = new HashMap<>(); public static double ERROR_CHECK_TAG = -100.0; public static double FAULT_CHECK_TAG = 85.0; public static double ERROR_CHECK_TAG2 = 50; public static double MAX_TEMP = -50.0; public static double MIN_TEMP = 50.0; /** * 后台发送请求后,终端的响应 * * @param reMessage * @param device */ public void analysis8815(ReMessage reMessage, GatewayDevice device) { BaseRequest request = new BaseRequest(); request.setSerId(device.getId()); request.setCompanyId(device.getOrgId()); request.setIp(reMessage.getIp()); request.setPort(reMessage.getPort()); request.setSerName(device.getDeviceName()); zldzGatewayGrainService.reply8815(request); } /** * 接收到粮情的回复 * * @param reMessage * @param device */ public void reply8817(ReMessage reMessage, GatewayDevice device) { String bodyMsg = reMessage.getBody().getContent(); log.info("分机------>>>平台:收到的粮情信息-{}-{}", device.getDeviceName(), reMessage.getStrMsg()); // Step1根据需要简化需要的信息 String ua = bodyMsg.substring(0 * 2, 1 * 2); log.debug("获取到的电压信息,系统不保留={}", ua); // 总包数 // int sumPacket = BytesUtil.hexToInt(bodyMsg.substring(1 * 2, 1 * 2 + 1 // * 2)); // 当前包 String hexCurPacket = bodyMsg.substring(2 * 2, 2 * 2 + 1 * 2); // int curPacket = BytesUtil.hexToInt(hexCurPacket); BaseRequest request = new BaseRequest(); request.setSerId(device.getDeviceSn()); request.setCompanyId(device.getOrgId()); request.setIp(reMessage.getIp()); request.setPort(reMessage.getPort()); request.setSerName(device.getDeviceName()); zldzGatewayGrainService.reply8817(request, hexCurPacket); } public void analysis8817(ReMessage msg, GatewayDevice device) { // 接到信息回复--主机 reply8817(msg, device); BaseReqData reqData = ProtocolUtils.getSyncReq(device.getDepotIdSys()); if (null == reqData) { log.warn("---------没有获取到当前仓库的请求,不执行解析-----{}", device.getDeviceName()); return; } analysisStep(msg, device, reqData); } /** * 开始解析 * * @param device * @param msg * @throws Exception */ private void analysisStep(ReMessage msg, GatewayDevice device, BaseReqData reqData) { // 粮情的批次号重新根据频率调整 msg.setBatchId(ContextUtil.getDefaultBatchId()); String bodyMsg = msg.getBody().getContent(); log.debug("{}=收到的粮情信息={}", device.getDeviceName(), msg.getStrMsg()); // Step1根据需要简化需要的信息 String ua = bodyMsg.substring(0 * 2, 1 * 2); log.debug("获取到的电压信息,系统不保留={}", ua); // 总包数 int sumPacket = BytesUtil.hexToInt(bodyMsg.substring(1 * 2, 1 * 2 + 1 * 2)); // 当前包 String hexCurPacket = bodyMsg.substring(2 * 2, 2 * 2 + 1 * 2); int curPacket = BytesUtil.hexToInt(hexCurPacket); log.debug("分机={},包总数={},当前包={}", device.getDeviceName(), sumPacket, curPacket); // 粮食温度信息 String grainStr = bodyMsg.substring(3 * 2); String contextKey = this.buildContextKey(msg, device.getDepotIdSys()); String curKey = this.buildCurKey(msg, curPacket); Map curMap = contextMap.get(contextKey); if (null == curMap) { curMap = new HashMap<>(); contextMap.put(contextKey, curMap); } contextMap.get(contextKey).put(curKey, grainStr); // 数据准备好,开始执行解析 if (curPacket == sumPacket) { analysisStep0(msg, device, reqData, contextKey, sumPacket); log.info("分机------>>>平台:命令类型=8817--粮情全部收到,开始解析-{}", device.getDeviceName()); } } private void analysisStep0(ReMessage msg, GatewayDevice device, BaseReqData reqData, String contextKey, int sumPacket) { Map curMap = contextMap.get(contextKey); if (StringUtils.isEmpty(device.getCableCir())) { analysisStep1(msg, device, reqData, curMap, sumPacket); } else { analysisStep2(msg, device, reqData, curMap, sumPacket); } } /** * 圆筒仓的粮情解析 * * @param packetMap * @param sumPackets */ private void analysisStep2(ReMessage msg, GatewayDevice device, BaseReqData reqData, Map packetMap, int sumPackets) { String[] cableRuleAtt = device.getCableRule().split("-"); String[] cableCirAtt = device.getCableCir().split("-"); if (cableRuleAtt.length != cableCirAtt.length) { log.error("分机------>>>平台:当前仓库:{},布线规则不正确,无法解析粮情信息……", device.getDeviceName()); return; } // 获取最大的层配置--默认每一圈都一样 int layMax = Integer.valueOf(cableCirAtt[0]); for (int i = 0; i < cableCirAtt.length; i++) { if (Integer.valueOf(cableCirAtt[i]) >= layMax) layMax = Integer.valueOf(cableCirAtt[i]); } // 获取完整的粮情包信息 String strPoints = ""; for (int i = 1; i <= sumPackets; i++) { strPoints += packetMap.get(buildCurKey(msg, i)); } log.info("------筒仓完整的粮情报文={}------", strPoints); int sumNum = 0, cableZ = 1;// sumNum 共多少根电缆;cableZ 层的最大值,锥形仓补齐最大层 for (int i = 0; i < cableCirAtt.length; i++) { if (Integer.valueOf(cableCirAtt[i]) > cableZ) { cableZ = Integer.valueOf(cableCirAtt[i]); } sumNum += Integer.valueOf(cableRuleAtt[i]); } // 根据层行列获取指定长度 int start = 0; int len = 4 * cableZ * sumNum; strPoints = strPoints.substring(start, start + len); log.info("分机------>>>平台:返回粮情完整信息,分机={}", device.getDeviceName()); // 将粮情解析成数组 List temps = new ArrayList<>(); double tempValue; String temp; int curLay = 1;//所在层从1开始 int curRoot = 1;//所在根 int curCir = 1;//所在圈 int cirLay = 1;//当前圈的层 for (int i = 0; i < strPoints.length() / 4; i++) { temp = strPoints.substring(i * 4, i * 4 + 4); if (temp == null) { temp = "0000"; } tempValue = BytesUtil.hexToInt(BytesUtil.tran_LH(temp)) / 10.0; //非正常值 if (tempValue > ERROR_CHECK_TAG2) { tempValue = ProtocolUtils.ERROR_TEMP; } // 故障值处理 if (tempValue >= FAULT_CHECK_TAG) { tempValue = ProtocolUtils.FAULT_TEMP; } // 备用值 if (tempValue == ERROR_CHECK_TAG) { tempValue = ProtocolUtils.ERROR_TEMP; //验证是不是锥形仓补偿值 curLay = (i % layMax) + 1; curRoot = (i / layMax) + 1; curCir = getCurCir(curRoot, cableRuleAtt); cirLay = Integer.valueOf(cableCirAtt[curCir - 1]); //比如配置了5层但是当前是6层,说明当前点为补偿点 if (curLay > cirLay) { tempValue = ProtocolUtils.ADD_TEMP; } else { temps.add(tempValue); } } else { temps.add(tempValue); } } // 将集合解析成坐标数据 addPoint2(temps, msg, device, reqData); } /** * 获取当前跟所在圈 * * @param curRoot * @param cableRuleAtt * @return */ private int getCurCir(int curRoot, String[] cableRuleAtt) { int sum = 0; for (int i = 0; i < cableRuleAtt.length; i++) { sum += Integer.valueOf(cableRuleAtt[i]); if (curRoot <= sum) return i + 1; } return 1; } /** * 平方仓的解析,解析需要考虑当前是否启用的一分机多仓 * * @param depotConf * @param msg * @param ser * @param exeRequest * @param packetMap * @param sumPackets */ private void analysisStep1(ReMessage msg, GatewayDevice device, BaseReqData reqData, Map packetMap, int sumPackets) { // 获取完整的粮情包信息 String strPoints = ""; for (int i = 1; i <= sumPackets; i++) { strPoints += packetMap.get(buildCurKey(msg, i)); } String[] attCable = device.getCableRule().split("-"); int cableZ = Integer.valueOf(attCable[0]); int cableY = Integer.valueOf(attCable[1]); int cableX = Integer.valueOf(attCable[2]); // 根据层行列获取指定长度 int start = 4 * (device.getCableStart() - 1) * cableZ * cableY; int len = 4 * cableZ * cableY * cableX; log.info("分机------>>>平台:返回粮情完整信息,分机={}", device.getDeviceName()); strPoints = strPoints.substring(start, start + len); // 将粮情解析成数组 List temps = new ArrayList<>(); double tempValue; String temp; for (int i = 0; i < strPoints.length() / 4; i++) { temp = strPoints.substring(i * 4, i * 4 + 4); if (temp == null) { temp = "0000"; } tempValue = BytesUtil.hexToInt(BytesUtil.tran_LH(temp)) / 10.0; // 说明解析的数据有问题 if (tempValue == ERROR_CHECK_TAG || tempValue == ERROR_CHECK_TAG2) { tempValue = ProtocolUtils.ERROR_TEMP; } // 故障值处理 if (tempValue >= FAULT_CHECK_TAG) { tempValue = ProtocolUtils.FAULT_TEMP; } temps.add(tempValue); } // 将集合解析成坐标数据 addPoint1(temps, msg, device, reqData); } private String buildCurKey(ReMessage msg, int curPacket) { return msg.getSourceId() + "_" + curPacket; } private String buildContextKey(ReMessage msg, String depotId) { return msg.getCompanyId() + "_" + msg.getSourceId() + "_" + depotId; } /** * 平房仓,解析第二步,解析到坐标数据 * * @param temps * @throws Exception */ private void addPoint1(List temps, ReMessage msg, GatewayDevice device, BaseReqData reqData) { //TODO } /** * 圆筒仓解析步骤 * * @param temps * @param msg */ private void addPoint2(List temps, ReMessage msg, GatewayDevice device, BaseReqData reqData) { //TODO } }