package com.sandu.ximon.admin.manager.iot.frame.inner.report; import cn.hutool.core.util.HexUtil; import cn.hutool.core.util.NumberUtil; 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; /** * 灯杆倾斜心跳包上报 */ @Data @ToString(callSuper = true) public class A5LightPoleHeelingHeartbeatReportInnerFrame extends BaseResponseInnerFrame { // 目标地址 4 private String destinationAddress; // 心跳包数据 private HeartBeatDataPackage heartBeatDataPackage; @Override public A5LightPoleHeelingHeartbeatReportInnerFrame transformFrame(String hex) { // 长度不一致时,返回null if (StrUtil.isBlank(hex)) { 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 = 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 { //设备型号 private String equipmentModel; //X轴 private double theXAxis; //Y轴 private double theYAxis; //Z轴 private double theZAxis; //预留 private String reservedA; private String reservedB; private String reservedC; private String reservedD; @Override public HeartBeatDataPackage transformFrame(String hex) { if (StrUtil.isBlank(hex)) { return null; } this.equipmentModel = "V" + (parseVal(hex, 0, 2)) + "." + String.format("%02d", parseVal(hex, 2, 4)); this.theXAxis = NumberUtil.round(temperatureTransition(hex.substring(4, 8)) * 0.1, 1).doubleValue(); this.theYAxis = NumberUtil.round(temperatureTransition(hex.substring(8, 12)) * 0.1, 1).doubleValue(); this.theZAxis = NumberUtil.round(temperatureTransition(hex.substring(12, 16)) * 0.1, 1).doubleValue(); this.reservedA = hex.substring(16, 20); this.reservedB = hex.substring(20, 24); this.reservedC = hex.substring(24, 28); this.reservedD = hex.substring(28, 32); //72-80保留,暂未使用 return this; } private Integer parseVal(String frame, int start, int end) { return Integer.parseInt(frame.substring(start, end), 16); } private String parseVal(String hex) { return Integer.parseInt(hex, 16) + ""; } /** * 将16进制转成2进制,进行补码(反码基础上+1),得到正确数值 * 传入16进制的温度,类型为String * 如F500 */ public Double temperatureTransition(String temperature) { //将传进来的16进制的转为2进制 String twoBinStr = hexStr2BinStr(temperature); if ("1".equals(twoBinStr.substring(0, 1))) { //最高位是1,为负数,将16进制的进行补码,返回 int max = 0b1111111111111111; double result = (max - HexUtil.hexToInt(temperature)) * (-0.01); return result; } else if ("0".equals(twoBinStr.substring(0, 1))) { //最高位是0,正数,直接返回 double result = (HexUtil.hexToInt(temperature)) * (0.01); return result; } // return 0.00; } /** * 16进制字符串转为二进制 */ public String hexStr2BinStr(String hexStr) { if (hexStr == null || hexStr.length() % 2 != 0) { return null; } String bString = "", tmp; for (int i = 0; i < hexStr.length(); i++) { tmp = "0000" + Integer.toBinaryString(Integer.parseInt(hexStr.substring(i, i + 1), 16)); bString += tmp.substring(tmp.length() - 4); } return bString; } } }