package com.fzzy.protocol.youxian0.analysis;
|
|
import com.alibaba.fastjson.JSONObject;
|
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.cmd.ReMessageBuilder;
|
import com.fzzy.protocol.data.THDto;
|
import com.fzzy.protocol.youxian0.ServiceUtils;
|
import com.fzzy.protocol.youxian0.data.GrainRoot;
|
import lombok.extern.slf4j.Slf4j;
|
import org.springframework.stereotype.Component;
|
|
import javax.annotation.Resource;
|
import java.net.InetAddress;
|
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 = "youxian0.analysisService";
|
|
@Resource
|
private GatewayRemoteManager gatewayRemoteManager;
|
|
private static Map<String, GrainRoot> contextGrainRoot = new HashMap<>();
|
|
/**
|
* 用于存放返回的仓温仓湿信息
|
*/
|
public static Map<String, THDto> contextMapTH = new HashMap<>();
|
|
|
/**
|
* 协议解析
|
* <p>
|
* 7E 00 02 02 00 77 00 00 A0 FF FF 66 FF 04 BE 01 64 6A 6B 6A 68 CE 02 A4 BB BA BA B4 CE 03 E4 32 3D 32 3D CE 04 44 BC B3 BC B3 20 47 7E
|
*
|
* @param address
|
* @param port
|
* @param strMsg
|
*/
|
public void analysis(InetAddress address, int port, String strMsg) {
|
|
//分机ID
|
int start = 2 * 2;
|
String deviceSn = strMsg.substring(start, start + 2);
|
deviceSn = BytesUtil.hexToInt(deviceSn) + "";
|
|
|
//命令ID
|
start = 5 * 2;
|
String msgIdHex = strMsg.substring(start, start + 2);
|
int msgId = BytesUtil.hexToInt(msgIdHex);
|
|
//命令类型
|
start = 11 * 2;
|
String funId = strMsg.substring(start, start + 2);
|
|
|
GatewayDevice device = GatewayUtils.getCacheByDeviceSn(deviceSn);
|
|
//粮情返回
|
if (ServiceUtils.FUNCTION_66.equalsIgnoreCase(funId)) {
|
|
log.info("---------开始解析粮情信息---------");
|
try{
|
this.analysisGrainStep1(device, msgId, strMsg);
|
}catch (Exception e){
|
log.error(e.getMessage(),e);
|
}
|
|
log.info("---------解析粮情信息结束---------");
|
}
|
|
//温湿度返回
|
if (ServiceUtils.FUNCTION_68.equalsIgnoreCase(funId)) {
|
log.info("---------开始解析仓温湿度信息---------");
|
try{
|
this.analysisGrainTh(device, strMsg);
|
}catch (Exception e){
|
log.error(e.getMessage(),e);
|
}
|
|
}
|
|
}
|
|
private void analysisGrainTh(GatewayDevice device, String strMsg) {
|
try{
|
THDto th = new THDto();
|
|
//TODO----->>> 待解析调整,先用外部气象信息
|
//7E 00 01 01 00 06 00 00 A0 FF FF 68 1A 05 CC 16 3A 62 36 7E
|
//系统气象站信息
|
// WeatherWebDto weather = WeatherWebDto.contextMap.get("default");
|
// th.setTempIn(Double.valueOf(weather.getTem()) - 2);
|
// th.setHumidityIn(Double.valueOf(weather.getHumidity()) - 10);
|
double t,h;
|
String temp = strMsg.substring(30,32);
|
t = BytesUtil.hexToInt(temp)/2;
|
log.info("温度:{}",t);
|
temp = strMsg.substring(32,34);
|
h = BytesUtil.hexToInt(temp);
|
log.info("湿度:{}",h);
|
th.setTempIn(t);
|
th.setHumidityIn(h);
|
this.add2ThMap(device.getDepotIdSys(), th);
|
}catch (Exception e){
|
log.error(e.getMessage(),e);
|
}
|
|
}
|
|
|
/**
|
* 粮情解析
|
* <p>
|
* 7E 00 02 02 00 77 00 00 A0 FF FF 66 FF 04 BE 01 64 6A 6B 6A 68 CE
|
* 02 A4 BB BA BA B4 CE 03 E4 32 3D 32 3D CE 04 44 BC B3 BC B3 20 47 7E
|
*
|
* @param device
|
* @param msgId 命令ID
|
*/
|
private void analysisGrainStep1(GatewayDevice device, int msgId, String strMsg) {
|
String[] attCable = device.getCableRule().split("-");
|
int cableZ = Integer.valueOf(attCable[0]);
|
int cableY = Integer.valueOf(attCable[1]);
|
int cableX = Integer.valueOf(attCable[2]);
|
log.info("z={},x={},y={}",cableZ,cableX,cableY);
|
//获取请求信息
|
BaseReqData reqData = ProtocolUtils.getSyncReq(device.getDepotIdSys());
|
if (null == reqData) {
|
log.error("---------没有获取到请求信息,不执行解析------{}", device.getDeviceName());
|
return;
|
}
|
//只保留粮情信息
|
int start = 15 * 2;
|
strMsg = strMsg.substring(start);
|
|
GrainRoot grainRoot = new GrainRoot();
|
grainRoot.setKey(buildGrainRootKey(device.getDeviceSn(), msgId));
|
grainRoot.setNum(msgId);
|
|
String tempStr = "";
|
for (int j = 0;j<cableY;j++){
|
tempStr = strMsg.substring((6+2*cableZ) * j,(6+2*cableZ) * j + (6+2*cableZ) );
|
//密钥和点数 02 A4 BB BA BA B4
|
String kyeNumHex = tempStr.substring(2, 4);
|
String kyeNumBin = BytesUtil.toBinary8String(BytesUtil.hexToInt(kyeNumHex));
|
|
String key = "00000" + kyeNumBin.substring(0, 3);
|
int keyValue = BytesUtil.hexToInt(BytesUtil.bin2Hex(key));
|
key = "0000" + kyeNumBin.substring(4);
|
int numValue = BytesUtil.hexToInt(BytesUtil.bin2Hex(key));
|
|
//02 A4 BB BA BA B4
|
start = 2 * 2;
|
String tempHex;
|
|
double point = 0;
|
for (int i = 0; i < numValue; i++) {
|
start = start + i * 2;
|
tempHex = tempStr.substring(start, start + 2);
|
//实际温度=密钥*密钥*37(溢出为无符号字节)再异或加密后的温度/2。
|
point = this.getGrainTemp(keyValue, tempHex);
|
log.info("--------解析后的温度点----{}---{}", tempHex, point);
|
grainRoot.getPoints().add(point);
|
start = 2 * 2;
|
}
|
}
|
|
this.add2GrainMap(grainRoot);
|
|
//判断是不是最后一包数据,如果是最后一包执行解析
|
|
if (grainRoot.getNum() == cableX) {
|
analysisGrainStep2(reqData, cableZ, cableY, cableX);
|
}
|
}
|
|
/**
|
* 封装粮情点位
|
*
|
* @param reqData
|
* @param cableZ
|
* @param cableY
|
* @param cableX
|
*/
|
private void analysisGrainStep2(BaseReqData reqData, int cableZ, int cableY, int cableX) {
|
|
List<Double> points = new ArrayList<>();
|
GrainRoot root;
|
List<Double> t = null;
|
for (int i = 1; i <= cableX; i++) {
|
root = this.getGrainRoot(buildGrainRootKey(reqData.getDevice().getDeviceSn(), i));
|
|
if (null == root || null == root.getPoints()) {
|
log.error("-----------解析获取所有粮情检测点失败,取消执行---------{}---{}", reqData.getDevice().getDeviceName(),i);
|
;
|
t = new ArrayList<>();
|
for (int x = 0;x<cableY*cableZ;x++
|
) {
|
t.add(-100.00);
|
}
|
//return;
|
points.addAll(t);
|
}else{
|
points.addAll(root.getPoints());
|
}
|
|
}
|
|
//执行封装解析
|
analysisGrainStep3(reqData, cableZ, cableY, cableX, points);
|
}
|
|
private void analysisGrainStep3(BaseReqData reqData, int cableZ, int cableY, int cableX, List<Double> points) {
|
|
GatewayDevice device = reqData.getDevice();
|
//数据封装
|
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<GrainTemp> temperature = new ArrayList<>();
|
//根号
|
int cableNum = 1, position = 0;
|
|
double curTemp;
|
int x = 0, y = 0, z = 0;
|
for (int i = 0; i < points.size(); i++) {
|
curTemp = points.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 + ""));
|
|
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<GrainTH> ths = new ArrayList<>();
|
|
|
//获取温湿度
|
THDto thDto = this.getGrainTh(device.getDepotIdSys());
|
|
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);
|
}
|
|
private synchronized void add2GrainMap(GrainRoot grainRoot) {
|
contextGrainRoot.put(grainRoot.getKey(), grainRoot);
|
}
|
|
private GrainRoot getGrainRoot(String key) {
|
return contextGrainRoot.get(key);
|
}
|
|
private String buildGrainRootKey(String deviceSn, int num) {
|
return deviceSn + "_" + num;
|
}
|
|
/**
|
* 计算粮情温度
|
* 实际温度=密钥*密钥*37(溢出为无符号字节)再异或加密后的温度/2。
|
* 举例说明:第三个字节BB实际温度是5*5*37=039D取9D^(0xBB)=38/2=19;
|
*
|
* @param keyValue
|
* @param tempHex
|
* @return
|
*/
|
private double getGrainTemp(int keyValue, String tempHex) {
|
int value = keyValue * keyValue * 37;
|
String valueHex = BytesUtil.intToHexStr(value);
|
|
valueHex = valueHex.substring(2);
|
|
int num1 = BytesUtil.hexToInt(valueHex);
|
int num2 = BytesUtil.hexToInt(tempHex);
|
if((num1 ^ num2) / 2.0 > 35){
|
return -100.00;
|
}else {
|
return (num1 ^ num2) / 2.0;
|
}
|
|
}
|
|
private void add2ThMap(String depotIdSys, THDto th) {
|
String key = "TH_" + depotIdSys;
|
contextMapTH.put(key, th);
|
}
|
|
private THDto getGrainTh(String depotIdSys) {
|
String key = "TH_" + depotIdSys;
|
return contextMapTH.get(key);
|
}
|
}
|