帧结构(报文结构)
示例:681A68B35303810D00C00059000000826110000001106000004508090A3516
-
681A68:开始字符串 字符串长度 开始字符串 -
B3为控制域(数据类型) 1)0000B—雨量;
- 0001B—水位;
- 0010B—流量(水量);
- 0011B—流速;
- 0100B—闸位;
- 0101B—功率;
- 0110B—气压;
- 0111B—风速(风向);
- 1000B—水温;
- 1001B—水质;
- 1010B—土壤含水率;
- 1011B—水压;
- 1100B—1111B 备用。
- 5303810D00为地址域(测站地址) 22 24 06为行政区代码 07 00测站地址
- 0059000000826110000001106000004508090A 用户数据(报文正文)
- 35: 校验CS
- 16: 结束字符(固定)
用户数据域解析(正文解析)
正文需要从后面开始解析
正文:0059000000826110000001106000004508090A
-
后10位为时间 :004508090A //00(秒-十位个位)45(分-十位个位)08(时-十位个位)09(日-十位个位),解析后为09日 08:45:00 年月需要自己补充。 -
再往前8位 01106000为报警值 转换为2进制 00000001000100000000011000000000 (每位转成4位2进制数不足补0) 前16位数 后16位数 -
剩余的为相关数据 00590000008261100000 由于数据类型为 B3 0010B—流量(水量) 按照文档6.2.26解析各种类型的数据
传输规约是5个字节代表一个数据,00 59 00 00 00 为流量数据,82 61 10 00 00 为水量数据
再按照每个位置代表的 数字位数解析后
流量为 00 00 00 59 00 实际数据为5.9 m3/s 水量 00 00 10 61 82 实际为106182 m3/h
java代码
package com.southsmart.smartwater.lotdevice.parser;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.southsmart.smartwater.lotdevice.constant.DataInfoConstant;
import com.southsmart.smartwater.lotdevice.enums.Szy206TypeEnum;
import com.southsmart.smartwater.lotdevice.enums.Szy206WaterQualityEnum;
import com.southsmart.smartwater.lotdevice.mapper.LotDeviceMapper;
import com.southsmart.smartwater.lotdevice.model.dto.Szy206InfoDTO;
import com.southsmart.smartwater.lotdevice.model.dto.UrlDTO;
import com.southsmart.smartwater.lotdevice.model.po.LotDevicePO;
import com.southsmart.smartwater.lotdevice.parser.service.ParserService;
import com.southsmart.smartwater.lotdevice.utils.MathUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@Slf4j
@Service
public class Szy206Parser extends BaseParser {
@Autowired
private LotDeviceMapper lotDeviceMapper;
@Autowired
private ParserService parserService;
@Override
public UrlDTO getUrlInfo(String interfaceId, String deviceId) {
return null;
}
@Override
public Map<String, Object> dataParser(String msg, String deviceId) {
Szy206InfoDTO szy206InfoDTO=new Szy206InfoDTO();
Integer index=0;
String startStr=msg.substring(index,index+6);
szy206InfoDTO.setStartStr(startStr);
index+=6;
String dataType=msg.substring(index,index+2);
szy206InfoDTO.setDataType(dataType);
index+=2;
String stationAddr=msg.substring(index,index+10);
szy206InfoDTO.setStationAddr(stationAddr);
szy206InfoDTO.setDeviceId(stationAddr);
index+=10;
String functionCode=msg.substring(index,index+2);
szy206InfoDTO.setFunctionCode(functionCode);
index+=2;
String content=msg.substring(index,msg.length()-4);
szy206InfoDTO.setContent(content);
index=msg.length()-4;
String crcCode=msg.substring(index,index+2);
szy206InfoDTO.setCrcCode(crcCode);
index+=2;
String endStr=msg.substring(index,index+2);
szy206InfoDTO.setEndStr(endStr);
parseContent(content,szy206InfoDTO);
Map<String,Object> map= (Map<String, Object>) JSONUtil.parse(szy206InfoDTO);
return map;
}
private void parseContent(String content, Szy206InfoDTO szy206InfoDTO) {
Map<String,Object> mainBody=new HashMap<>();
Map<String,Object> mainHead=new HashMap<>();
int index=content.length();
if(index>18){
String time=content.substring(index-10,index);
Integer year= DateTime.now().year();
Integer month=DateTime.now().monthBaseOne();
Integer day=Integer.parseInt(time.substring(6,8));
Integer hour=Integer.parseInt(time.substring(4,6));
Integer minutes=Integer.parseInt(time.substring(2,4));
Integer seconds=Integer.parseInt(time.substring(0,2));
String dateTimeStr=year+"/"+month+"/"+day+" "+hour+":"+minutes+":"+seconds;
DateTime dateTime= DateUtil.parseDateTime(dateTimeStr);
String timeStr= dateTime.toString();
szy206InfoDTO.setDataTime(timeStr);
mainBody.put(DataInfoConstant.DATA_TIME,timeStr);
mainHead.put(DataInfoConstant.DATA_TIME,DataInfoConstant.DATA_TIME_MEAN);
index-=10;
String warningStatus=content.substring(index-8,index);
index-=8;
String dataContent=content.substring(0,index);
if(Szy206TypeEnum.WATER_LEVEL.getKey().equals(szy206InfoDTO.getDataType())){
int oneDataLength=8;
int decimalPoint=5;
parentDataInfo(szy206InfoDTO,dataContent,oneDataLength,decimalPoint,true,mainBody,mainHead);
}else if(Szy206TypeEnum.TRAFFIC.getKey().equals(szy206InfoDTO.getDataType())){
int oneDataLength=10;
int decimalPoint=7;
int dataLength=dataContent.length();
if(dataLength%oneDataLength==0) {
int cycleNum = 0;
int flag=2;
while (dataLength > 0) {
try {
String data = dataContent.substring(cycleNum * oneDataLength, (cycleNum + 1) * oneDataLength);
cycleNum++;
dataLength -= oneDataLength;
char[] dataChar = data.toCharArray();
String result;
if(flag%2==0){
result = char2String(dataChar, decimalPoint,true);
Double resultData=Double.parseDouble(result);
mainBody.put("flow",resultData);
mainHead.put("flow","流量");
log.info("遥测地址:"+szy206InfoDTO.getStationAddr()+" 类型:流量"+" 结果:"+resultData);
}else{
result = char2String(dataChar, 0,true);
Double resultData=Double.parseDouble(result);
mainBody.put("countFlow",resultData);
mainHead.put("countFlow","累计流量");
log.info("遥测地址:"+szy206InfoDTO.getStationAddr()+" 类型:累计流量"+" 结果:"+resultData);
}
flag++;
} catch (Exception e) {
System.out.println(e.toString());
}
}
}
}else if(Szy206TypeEnum.VELOCITY.getKey().equals(szy206InfoDTO.getDataType())){
int oneDataLength=6;
int decimalPoint=3;
parentDataInfo(szy206InfoDTO,dataContent,oneDataLength,decimalPoint,true,mainBody,mainHead);
}else if(Szy206TypeEnum.GATES.getKey().equals(szy206InfoDTO.getDataType())){
int oneDataLength=6;
int decimalPoint=4;
parentDataInfo(szy206InfoDTO,dataContent,oneDataLength,decimalPoint,false,mainBody,mainHead);
}else if(Szy206TypeEnum.POWER.getKey().equals(szy206InfoDTO.getDataType())){
int oneDataLength=6;
int decimalPoint=0;
parentDataInfo(szy206InfoDTO,dataContent,oneDataLength,decimalPoint,false,mainBody,mainHead);
}else if(Szy206TypeEnum.AIR_PRESSURE.getKey().equals(szy206InfoDTO.getDataType())){
int oneDataLength=6;
int decimalPoint=0;
parentDataInfo(szy206InfoDTO,dataContent,oneDataLength,decimalPoint,false,mainBody,mainHead);
}else if(Szy206TypeEnum.WIND_SPEED.getKey().equals(szy206InfoDTO.getDataType())){
int oneDataLength=6;
int decimalPoint=4;
parentDataInfo(szy206InfoDTO,dataContent,oneDataLength,decimalPoint,false,mainBody,mainHead);
}else if(Szy206TypeEnum.WATER_TEMPERATURE.getKey().equals(szy206InfoDTO.getDataType())){
int oneDataLength=4;
int decimalPoint=3;
parentDataInfo(szy206InfoDTO,dataContent,oneDataLength,decimalPoint,false,mainBody,mainHead);
}else if(Szy206TypeEnum.MOISTURE_CONTENT.getKey().equals(szy206InfoDTO.getDataType())){
int oneDataLength=4;
int decimalPoint=4;
parentDataInfo(szy206InfoDTO,dataContent,oneDataLength,decimalPoint,false,mainBody,mainHead);
}else if(Szy206TypeEnum.WATER_PRESSURE.getKey().equals(szy206InfoDTO.getDataType())){
int oneDataLength=8;
int decimalPoint=7;
parentDataInfo(szy206InfoDTO,dataContent,oneDataLength,decimalPoint,false,mainBody,mainHead);
}else if(Szy206TypeEnum.WATER_QUALITY.getKey().equals(szy206InfoDTO.getDataType())){
int oneDataLength=8;
String typeStr=dataContent.substring(0,10);
char[] typeChar=typeStr.toCharArray();
String binStr="";
for(char ch:typeChar){
binStr+=MathUtil.hexString2binaryString(new StringBuilder(ch).toString());
}
char[] binaryTypeChar=binStr.toCharArray();
if(new StringBuilder(binaryTypeChar[24]).toString().equals("1")){
oneDataLength=10;
}
List<Integer> indexList=new ArrayList<>();
for(int i=0;i<binaryTypeChar.length;i++){
if(new StringBuilder(binaryTypeChar[i]).toString().equals("1")){
indexList.add(i);
}
}
int dataLength=dataContent.length();
List<String> dataList=new ArrayList<>();
if(dataLength%oneDataLength==0) {
int cycleNum=0;
while (dataLength > 0) {
String data = dataContent.substring(cycleNum * oneDataLength, (cycleNum + 1) * oneDataLength);
dataList.add(data);
}
}
if(indexList.size()==dataList.size()){
for(int i=0;i<indexList.size();i++){
Szy206WaterQualityEnum szy206WaterQualityEnum =getQualityEnumByKey("D"+indexList.get(i));
if(ObjectUtil.isNotEmpty(szy206WaterQualityEnum)){
Integer decimalPoint=oneDataLength-Integer.parseInt(szy206WaterQualityEnum.getPrecision().split(",")[1].replace(")",""));
Double value=Double.parseDouble(char2String(dataList.get(i).toCharArray(),decimalPoint,false));
String key=szy206WaterQualityEnum.getKey();
log.info("遥测地址:"+szy206InfoDTO.getStationAddr()+"类型:"+szy206WaterQualityEnum.getName()+"结果:"+value);
mainBody.put(key,value);
mainHead.put(key,szy206WaterQualityEnum.getName()+"("+szy206WaterQualityEnum.getUnit()+")");
}
}
}
}
}
szy206InfoDTO.setMainBody(mainBody);
szy206InfoDTO.setMainHead(mainHead);
}
public Szy206WaterQualityEnum getQualityEnumByKey(String key){
for(Szy206WaterQualityEnum e:Szy206WaterQualityEnum.values()){
if(e.getKey().equals(key)){
return e;
}
}
return null;
}
public void parentDataInfo( Szy206InfoDTO szy206InfoDTO,String dataContent,Integer oneDataLength, int decimalPoint,Boolean isNegative,Map<String,Object> mainBody,Map<String,Object> mainHead){
int dataLength=dataContent.length();
if(dataLength%oneDataLength==0){
int cycleNum=0;
while (dataLength>0){
try{
String data=dataContent.substring(cycleNum*oneDataLength,(cycleNum+1)*oneDataLength);
cycleNum++;
dataLength-=oneDataLength;
char[] dataChar=data.toCharArray();
String result=char2String(dataChar,decimalPoint,isNegative);
Szy206TypeEnum szy206TypeEnum=getTypeEnum(szy206InfoDTO.getDataType());
Double resultData=Double.parseDouble(result);
mainBody.put(szy206TypeEnum.getKey(),resultData);
mainHead.put(szy206TypeEnum.getKey(),szy206TypeEnum.getDescription());
log.info("遥测地址:"+szy206InfoDTO.getStationAddr()+" 类型:"+szy206TypeEnum.getDescription()+" 结果:"+result);
}catch (Exception e){
System.out.println(e.toString());
}
}
}
}
public Szy206TypeEnum getTypeEnum(String typeKey){
for(Szy206TypeEnum szy206TypeEnum:Szy206TypeEnum.values()){
if(szy206TypeEnum.getKey().equals(typeKey)){
return szy206TypeEnum;
}
}
return null;
}
public String char2String(char[] ch,Integer decimalPoint,Boolean isNegative){
int length=ch.length/2;
String[] dataArray=new String[length];
for(int i=0;i<ch.length;i+=2){
String c=ch[i]+""+ch[i+1];
dataArray[length-1]=c;
length--;
}
StringBuilder stringBuilder=new StringBuilder();
for(int j=0;j<dataArray.length;j++){
if(j==0){
if(isNegative){
if(Integer.parseInt(dataArray[j].substring(0,1))!=0){
stringBuilder.append("-");
}else{
stringBuilder.append("+");
}
stringBuilder.append(dataArray[j].substring(1,2));
}
}else{
stringBuilder.append(dataArray[j]);
}
}
String resultDataStr=stringBuilder.toString();
if(decimalPoint!=0){
resultDataStr=stringBuilder.toString().substring(0,decimalPoint)+"."+stringBuilder.toString().substring(decimalPoint,stringBuilder.length());
}
return resultDataStr;
}
}
|