package com.fzzy.protocol.zldz.analysis; import com.alibaba.fastjson.JSONObject; import com.fzzy.api.data.GatewayDeviceType; import com.fzzy.api.utils.BytesUtil; import com.fzzy.api.utils.ContextUtil; import com.fzzy.api.utils.NumberUtil; import com.fzzy.gateway.GatewayUtils; import com.fzzy.gateway.api.GatewayDeviceReportService; import com.fzzy.gateway.api.GatewayRemoteManager; import com.fzzy.gateway.data.BaseReqData; import com.fzzy.gateway.data.WeatherWebDto; import com.fzzy.gateway.entity.GatewayDevice; import com.fzzy.gateway.hx2023.ScConstant; import com.fzzy.gateway.hx2023.data.*; import com.fzzy.io.request.BaseRequest; import com.fzzy.protocol.ProtocolUtils; import com.fzzy.protocol.bhzn.v0.cmd.ReMessageBuilder; import com.fzzy.protocol.data.THDto; 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 javax.persistence.criteria.CriteriaBuilder; 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; @Resource private GatewayRemoteManager gatewayRemoteManager; 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 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 * (Integer.valueOf(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, device, reqData, cableX, cableY, cableZ); } 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, GatewayDevice device, BaseReqData reqData, int cableX, int cableY, int cableZ) { //数据封装 GrainData grain = new GrainData(); grain.setMessageId(ScConstant.getMessageId()); grain.setDeviceId(device.getDeviceId()); grain.setTimestamp(System.currentTimeMillis() + ""); ClientHeaders headers = new ClientHeaders(); headers.setDeviceName(device.getDeviceName()); headers.setProductId(device.getProductId()); headers.setOrgId(device.getOrgId()); headers.setMsgId(reqData.getMessageId()); grain.setHeaders(headers); GrainOutPut outPut = new GrainOutPut(); double max = ReMessageBuilder.MAX_TEMP, min = ReMessageBuilder.MIN_TEMP, sumT = 0.0, sumNum = cableX * cableY * cableZ; List temperature = new ArrayList<>(); //根号 int cableNum = 1, position = 0; double curTemp; int x = 0, y = 0, z = 0; for (int i = 0; i < temps.size(); i++) { curTemp = temps.get(i); position = i; z = i % cableZ + 1; x = i / (cableZ * cableY); y = x * (cableZ * cableY); y = (i - y) / cableZ; //根号 cableNum = (i / cableZ) + 1; temperature.add(new GrainTemp(cableNum + "", z + "", curTemp + "", position + "")); //求最大最小值 if (curTemp < -900) { sumNum--; } else { sumT += curTemp; if (curTemp > max) { max = curTemp; } if (curTemp < min) { min = curTemp; } } } if (sumNum == 0) { sumNum = 1; log.warn("---当前粮情采集异常--"); } //过滤比较用的最大最小值 if (max == ReMessageBuilder.MAX_TEMP) { max = 0.0; } if (min == ReMessageBuilder.MIN_TEMP) { min = 0.0; } outPut.setTemperature(temperature); outPut.setAvgTemperature(NumberUtil.keepPrecision((sumT / sumNum), 1) + ""); outPut.setMinTemperature(min + ""); outPut.setMaxTemperature(min + ""); List ths = new ArrayList<>(); THDto thDto = ProtocolUtils.getCacheTh(device.getDeviceId()); if (null == thDto) thDto = new THDto(); ths.add(new GrainTH(thDto.getTempIn() != null ? thDto.getTempIn() + "" : "", thDto.getHumidityIn() != null ? thDto.getHumidityIn() + "" : "", "1")); outPut.setTemperatureAndhumidity(ths); grain.setOutput(JSONObject.toJSONString(outPut)); GatewayDevice gatewayDeviceWeather = GatewayUtils.getCacheByDeviceTypeOne(GatewayDeviceType.TYPE_09.getCode()); //系统气象站信息 WeatherWebDto weather = WeatherWebDto.contextMap.get("default"); //气象信息 GrainWeather weatherStation = new GrainWeather(); weatherStation.setMessageId(ScConstant.getMessageId()); weatherStation.setMessgeId(weatherStation.getMessageId()); if (null != gatewayDeviceWeather) { weatherStation.setId(gatewayDeviceWeather.getDeviceId()); } else { weatherStation.setId(device.getDeviceId()); } weatherStation.setAirPressure(weather.getPressure()); weatherStation.setHumidity(weather.getHumidity()); weatherStation.setPm(weather.getAir_pm25()); weatherStation.setRadiation("0"); weatherStation.setRainfallAmount(weather.getWea()); weatherStation.setTemperature(weather.getTem()); weatherStation.setWindDirection(weather.getWin()); weatherStation.setWindPower(weather.getWin_meter()); weatherStation.setWindSpeed(weather.getWin_speed()); grain.setWeatherStation(JSONObject.toJSONString(weatherStation)); //封装好的数据 log.info("---粮情机械封装完成----开始执行推送"); reqData.setData(JSONObject.toJSONString(grain)); doPushGrain(reqData,grain); } private void doPushGrain(BaseReqData reqData,GrainData grainData) { GatewayDeviceReportService reportService = gatewayRemoteManager.getDeviceReportService(reqData.getDevice().getPushProtocol()); if (null == reportService) { log.error("------------粮情推送失败,系统不存在当前协议执行类----{}", reqData.getDevice().getDeviceName()); return; } reportService.reportGrainData(reqData); reqData.setData(reportService.grainData2GatewayApiInfoKafka(grainData,reqData.getDevice()).getData()); reportService.reportGrainDataByKafka(reqData); } /** * 圆筒仓解析步骤 * * @param temps * @param msg */ private void addPoint2(List temps, ReMessage msg, GatewayDevice device, BaseReqData reqData) { //TODO } }