package com.sandu.ximon.admin.manager.iot.frame.inner.report; import cn.hutool.core.util.StrUtil; import com.sandu.ximon.admin.manager.iot.frame.inner.BaseResponseInnerFrame; import com.sandu.ximon.admin.manager.iot.frame.inner.IResponseInnerFrame; import com.sandu.ximon.admin.manager.iot.rrpc.util.CRC32Utils; import lombok.Data; import lombok.ToString; /** * @author chenjiantian * @date 2021/12/6 18:20 * A5-84-01 * 大气心跳包 应答 */ @Data @ToString(callSuper = true) public class A5AtmosphereHeartbeatReportInnerFrame extends BaseResponseInnerFrame { // 目标地址 2 private String destinationAddress; // 心跳包数据 58 private HeartBeatDataPackage heartBeatDataPackage; private String originFrame; @Override public A5AtmosphereHeartbeatReportInnerFrame transformFrame(String hex) { // 长度不一致时,返回null if (StrUtil.isBlank(hex) || hex.length() < 26 || hex.substring(18).length() % 8 != 0) { System.out.println("数据校验异常!"); return null; } // MQTT通信方式(1) setConnectType(hex.substring(0, 2)); // 功能码(1) setFunctionCode(hex.substring(2, 4)); // 负荷长度(2) setPayloadLength(hex.substring(4, 8)); setDestinationAddress(hex.substring(8, 12)); String heartBeatData = hex.substring(12, hex.length() - 8); HeartBeatDataPackage heartBeatDataPackage = new HeartBeatDataPackage(); heartBeatDataPackage.transformFrame(heartBeatData); setHeartBeatDataPackage(heartBeatDataPackage); setCrc32(hex.substring(hex.length() - 8)); // 校验CRC32 String frame = hex.substring(2, hex.length() - 8); this.setValidate(CRC32Utils.validateFrame(frame, getCrc32())); return this; } @Data public static class HeartBeatDataPackage implements IResponseInnerFrame { // 编号 数据 含义 单位 // D7:D6 D5:D4 D3:D2 D1:D0 // 0x01 空,用0x00填充 0x00~0xEC 0x00~0x09 温度 0.1℃ // 0x02 空,用0x00填充 0x00~0x64 0x00~0x09 湿度 0.1% // 0x03 空,用0x00填充 0x00 0x00 风速 0.1m/s // 0x04 空,用0x00填充 0xF8或0x00 0x00 风向 八方向/0.1℃ // 0x05 空,用0x00填充 空,用0x00填充 0x00~0x12 风力 级 // 0x06 0x00 0x00 0x00 大气压 0.01hPA(百帕斯卡) // 0x07 0x00 0x00 0x00 光强 Lux // 0x08 空,用0x00填充 0x00 0x00 噪音 0.1dB // 0x09 空,用0x00填充 0x00 0x00 PM2.5 ug/m3 // 0x0A 空,用0x00填充 0x00 0x00 PM10 ug/m3 // 0x0B 空,用0x00填充 0x00 0x00 TSP ug/m3 // 0x0C 空,用0x00填充 0x00 0x00 雨量 0.1mm // 0x0D 空,用0x00填充 0x00 0x00 甲醛 ppm // 0x0E 空,用0x00填充 0x00 0x00 TVOC ppm // 0x0F 空,用0x00填充 0x00 0x00 eCO2 ppm // 0x10 空,用0x00填充 0x00 0x00 SO2二氧化硫 ppm // 0x11 空,用0x00填充 0x00 0x00 NO2二氧化氮 ppm // 0x12 空,用0x00填充 0x00 0x00 CO一氧化碳 ppm // 0x13 空,用0x00填充 0x00 0x00 O3臭氧 ppm // 0x14 空,用0x00填充 0x00 0x00 F氟化物 ppm // 设备型号 2 private String deviceType; // 模块预热状态标志 1 private String moduleWarmUpStatusFlag; // 温度值 private String temperature; // 湿度值 private String humidity; // 风速 private String windSpeed; // 风向 private String windDirection; // 风力 private String windPower; // 大气压 private String pressure; // 光强 private String lightIntensity; // 噪音 private String noise; // PM2.5 private String pm25; // PM10 private String pm10; //总悬浮颗粒物TSP private String tsp; // 雨量 private String rain; // SO2二氧化硫相对值 private String so2; // 甲醛相对值 private String ech2o; // NO2二氧化氮 private String no2; // TVOC private String tvoc; // CO一氧化碳 private String co; // 二氧化碳 private String co2; // O3臭氧 private String o3; // F氟化物 private String fluoride; @Override public HeartBeatDataPackage transformFrame(String hex) { //判断数据长度是否正确 if (hex == null || hex.substring(6).length() % 8 != 0) { System.out.println("hex:---" + hex); System.out.println("心跳包数据异常!"); return null; } //设备型号 this.deviceType = hex.substring(0, 4); //模块预热状态标志 this.moduleWarmUpStatusFlag = hex.substring(4, 6); //心跳包设备数据 String data = hex.substring(6, hex.length() - 8); int lenght = data.length() / 8; //设备数据 String sub; for (int i = 0; i < lenght; i++) { sub = data.substring(i * 8, i * 8 + 8); switch (data.substring(i * 8, i * 8 + 2)) { //温度 case "01": //01001E01 this.temperature = Double.parseDouble( parseVal(sub, 4, 6) + "." + parseVal(sub, 6, 8) ) + "℃"; break; //湿度 case "02": //02003608 this.humidity = Double.parseDouble( parseVal(sub, 4, 6) + "." + parseVal(sub, 6, 8) ) + "%"; break; //风速 case "03": //03000000 this.windSpeed = parseVal(sub, 4, 8) * .1 + "m/s"; break; //风向 case "04": //0400F804 if ("F8".equals(sub.substring(4, 6))) { //八向款风向仪 switch (sub.substring(6, 8)) { case "00": this.windDirection = "北风"; break; case "01": this.windDirection = "东北风"; break; case "02": this.windDirection = "东风"; break; case "03": this.windDirection = "东南风"; break; case "04": this.windDirection = "南风"; break; case "05": this.windDirection = "西南风"; break; case "06": this.windDirection = "西风"; break; case "07": this.windDirection = "西北风"; break; default: this.windDirection = "未知风向"; } } else if ("00".equals(sub.substring(4, 6))) { //360度款风向仪 this.windDirection = parseVal(sub, 4, 8) * .1 + "度"; } break; //风力 case "05": this.windPower = sub.substring(6, 8) + "级"; break; //大气压 case "06": //06000000 this.pressure = parseVal(sub, 2, 8) * .01 + "hPA"; break; //光强 case "07": this.lightIntensity = parseVal(sub, 2, 8) + "Lux"; break; //噪音 case "08": this.noise = parseVal(sub, 4, 8) * .1 + "dB"; break; //PM2.5 case "09": this.pm25 = parseVal(sub, 4, 8) + "ug/m3"; break; //PM10 case "0A": this.pm10 = parseVal(sub, 4, 8) + "ug/m3"; break; //TSP case "0B": this.tsp = parseVal(sub, 4, 8) + "ug/m3"; break; //雨量 case "0C": this.rain = parseVal(sub, 4, 8) * .1 + "mm"; break; //甲醛 case "0D": this.ech2o = parseVal(sub, 4, 8) + "ppm"; break; //TVOC case "0E": this.tvoc = parseVal(sub, 4, 8) + "ppm"; break; //eCO2 case "0F": this.co2 = parseVal(sub, 4, 8) + "ppm"; break; //SO2二氧化硫 case "10": this.so2 = parseVal(sub, 4, 8) + "ppm"; break; //NO2二氧化氮 case "11": this.no2 = parseVal(sub, 4, 8) + "ppm"; break; //CO一氧化碳 case "12": this.co = parseVal(sub, 4, 8) + "ppm"; break; //O3臭氧 case "13": this.o3 = parseVal(sub, 4, 8) + "ppm"; break; //F氟化物 case "14": this.fluoride = parseVal(sub, 4, 8) + "ppm"; break; default: return null; } } return this; } private Integer parseVal(String frame, int start, int end) { return Integer.parseInt(frame.substring(start, end), 16); } } }