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<String, Map<String, String>> 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<String, String> 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<String, String> 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<String, String> 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<Double> 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<String, String> 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<Double> 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<Double> 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<GrainTemp> 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<GrainTH> 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<Double> temps, ReMessage msg,
|
GatewayDevice device, BaseReqData reqData) {
|
|
//TODO
|
}
|
|
|
}
|