package com.fzzy.protocol.bhzn.v0.analysis; import com.alibaba.fastjson.JSONObject; import com.fzzy.api.Constant; import com.fzzy.api.data.ApiCommonDevice; import com.fzzy.api.data.GatewayDeviceType; import com.fzzy.api.utils.BytesUtil; 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.protocol.ProtocolUtils; import com.fzzy.protocol.bhzn.v0.cmd.CommandBuild; import com.fzzy.protocol.bhzn.v0.cmd.ReMessageBuilder; import com.fzzy.protocol.bhzn.v0.data.IoMessage; import com.fzzy.protocol.bhzn.v0.server.BhznGrainV0ServerEngine; import com.fzzy.protocol.bhzn.v0.server.BhznGrainV0ServerUtils; import com.fzzy.protocol.data.THDto; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; import javax.annotation.Resource; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; /** * 协议解析 */ @Slf4j @Component(AnalysisService.BEAN_ID) public class AnalysisService { public static final String BEAN_ID = "bhzn0.analysisService"; @Resource private GatewayRemoteManager gatewayRemoteManager; /** * 针对分包粮情报文进行封装 */ public static Map contextMapGrain = new HashMap<>(); /** * 用于存放返回的仓温仓湿信息 */ public static Map contextMapTH = new HashMap<>(); /** * @param sessionKey ip:port */ public void analysis(String sessionKey, IoMessage message) throws Exception { //注册 if (BhznGrainV0ServerUtils.FUNCTION_ID_F1.equals(message.getFunctionId())) { log.info("主机------->>平台:注册信息报文={}", message); //DO NOTHING return; } //心跳 if (BhznGrainV0ServerUtils.FUNCTION_ID_F2.equals(message.getFunctionId())) { //DO NOTHING return; } // 93 解析仓温仓湿,并返回收到报文 if (BhznGrainV0ServerUtils.FUNCTION_ID_93.equals(message.getFunctionId())) { log.info("主机------->>平台:温湿度信息报文={}", message); analysisTh(message); return; } // 92 解析粮温,并返回收到报文 if (BhznGrainV0ServerUtils.FUNCTION_ID_92.equals(message.getFunctionId())) { log.info("主机------->>平台:粮情信息报文={}", message); analysisGrain(message); } } /** * 暂时不支持义分机多仓模式,--平房仓 * * @param message */ private void analysisGrain(IoMessage message) { try { //根据分机SN获取设备配置信息 GatewayDevice gatewayDevice = GatewayUtils.getCacheByDeviceSn(message.getAddr()); if (null == gatewayDevice) { replayGrain(message); log.error("主机-------->>平台,解析粮情失败,未获取到系统设备配置信息:" + message.getAddr()); return; } //根据分机地址获取分机信息 ApiCommonDevice commonDevice = Constant.getCommonDeviceCache(message.getIp()); if (commonDevice == null) { replayGrain(message); log.error("主机-------->>平台,解析粮情失败,未获取到系统粮情主机配置:" + message.getAddr()); return; } //获取请求信息 BaseReqData reqData = ProtocolUtils.getSyncReq(gatewayDevice.getDepotIdSys()); if (null == reqData) { replayGrain(message); log.error("主机-------->>平台,解析粮情失败,未获取到粮情请求信息:" + message.getAddr()); return; } // 判断数据有没有收取完整 String[] attCable = gatewayDevice.getCableRule().split("-"); int cableZ = Integer.valueOf(attCable[0]); int cableY = Integer.valueOf(attCable[1]); int cableX = Integer.valueOf(attCable[2]); int sumPoint = cableZ * cableY * cableX; //获取当前粮情温度报文 String grainHex = message.getContent().substring(16); //当前报文温度点数 int curPoint = BytesUtil.hexToInt(BytesUtil.tran_LH(message.getContent().substring(4, 8))); //如果当前包的数据个数大于等于当前仓库的配置点位则表示单包返回 if (curPoint >= sumPoint) { log.info("分机------>>>平台:粮情数据单包=" + grainHex); //返回粮情接收信息 replayGrain(message); analysisGrain2(message, reqData, grainHex); return; } //表示分包传递 String key = "GRAIN_" + message.getAddr(); String oldGrainHex = contextMapGrain.get(key) == null ? "" : contextMapGrain.get(key); //获取当前包起始点的层行列 int hang = BytesUtil.hexToInt(BytesUtil.tran_LH(message.getContent().substring(8, 10))); int lie = BytesUtil.hexToInt(BytesUtil.tran_LH(message.getContent().substring(10, 12))); int ceng = BytesUtil.hexToInt(BytesUtil.tran_LH(message.getContent().substring(12, 14))); if (hang > 0 || lie > 0 || ceng > 0) { //说明非第一包数据 grainHex = oldGrainHex + grainHex; } if (grainHex.length() >= sumPoint * 4) { //返回粮情接收信息 replayGrain(message); log.info("分机------>>>平台:粮情数据多包,完整数据=" + grainHex); analysisGrain2(message, reqData, grainHex); return; } else { log.info("分机------>>>平台:将第一包数据存入内存=" + grainHex); contextMapGrain.put(key, grainHex); replayGrain(message); } } catch (Exception e) { log.error(e.getMessage(), e); } } /** * 返回粮情收到报文信息,需要注意:如果存在分包情况下,需要等所有包收到后返回 * * @param message */ private void replayGrain(IoMessage message) throws InterruptedException { Thread.sleep(50); String hexStr = CommandBuild.getMsgGrainReply(message.getAddr()); log.info("平台--------->>>主机,返回粮情报文收到信息,报文={}", hexStr); BhznGrainV0ServerEngine.push(message.getIp(), message.getPort(), BytesUtil.hexStrToBytes(hexStr)); } private void analysisGrain2(IoMessage message, BaseReqData reqData, String grainStr) { GatewayDevice device = reqData.getDevice(); // 获取完整的粮情包信息 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 = 0; int len = 4 * cableZ * cableY * cableX; log.info("分机------>>>平台:返回粮情完整信息,分机={}", device.getDeviceName()); String strPoints = grainStr.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"; } if (ReMessageBuilder.ERROR_TAG.equals(temp)) { tempValue = ProtocolUtils.ERROR_TEMP; } else { tempValue = BytesUtil.hexToInt(BytesUtil.tran_LH(temp)) / 10.0; } // 故障值处理 if (tempValue >= ReMessageBuilder.FAULT_CHECK_TAG) { tempValue = ProtocolUtils.FAULT_TEMP; } temps.add(tempValue); } THDto thDto = this.getTH(message); if (null != thDto) { log.info("-------THDto--={}", thDto); } //清空 String key = "GRAIN_" + message.getAddr(); contextMapGrain.put(key, null); // 将集合解析成坐标数据 addPoint1(temps, reqData, thDto); } /** * 平房仓,解析第二步,解析到坐标数据 * * @param temps * @throws Exception */ private void addPoint1(List temps, BaseReqData reqData, THDto thDto) { GatewayDevice device = reqData.getDevice(); String[] attCable = device.getCableRule().split("-"); int cableZ = Integer.valueOf(attCable[0]); int cableY = Integer.valueOf(attCable[1]); int cableX = Integer.valueOf(attCable[2]); //数据封装 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<>(); 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); } private void doPushGrain(BaseReqData reqData) { GatewayDeviceReportService reportService = gatewayRemoteManager.getDeviceReportService(reqData.getDevice().getPushProtocol()); if (null == reportService) { log.error("------------粮情推送失败,系统不存在当前协议执行类----{}", reqData.getDevice().getDeviceName()); return; } reportService.reportGrainData(reqData); } private void analysisTh(IoMessage message) { try { THDto th = new THDto(); String data = message.getContent(); String houseNo = data.substring(0, 2); int depotId = BytesUtil.hexToInt(houseNo); String t = data.substring(4, 8); String h = data.substring(8, 12); double humy; String temp; int symbol = 0; //符号位 double tempValue; if (ReMessageBuilder.ERROR_TAG.equals(t)) { temp = "0000"; } else { temp = BytesUtil.tran_LH(t); } temp = BytesUtil.hexString2binaryString(temp, 16); //符号位 symbol = Integer.valueOf(temp.substring(0, 1)); //获取温度值 tempValue = BytesUtil.biannary2Decimal(temp.substring(6)) / 10; //若为负,则补码:取反加1 if (symbol == 1) { tempValue = 0.0 - BytesUtil.twoToString(temp) / 10; } th.setTempIn(tempValue); if (ReMessageBuilder.ERROR_TAG.equals(h)) { humy = 0.0; } else { humy = (double) BytesUtil.hexToBigInt(BytesUtil.tran_LH(h)) / 10; } th.setHumidityIn(humy); log.info("主机--------->>>平台,解析仓温仓湿信息,仓库={},结果={}", depotId, th.toString()); String key = "TH_" + depotId; contextMapTH.put(key, th); } catch (Exception e) { log.error(e.getMessage(), e); } finally { String hexStr = CommandBuild.getMsgTHReply(message.getAddr()); log.info("平台--------->>>主机,返回仓温仓湿收到信息,报文={}", hexStr); BhznGrainV0ServerEngine.push(message.getIp(), message.getPort(), BytesUtil.hexStrToBytes(hexStr)); } } private THDto getTH(IoMessage message) { String data = message.getContent(); String houseNo = data.substring(0, 2); Integer depotId = BytesUtil.hexToInt(houseNo); String key = "TH_" + depotId; return contextMapTH.get(key); } }