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; /** * @author chenjiantian * @date 2021/12/6 18:20 * A5-81-40 * 灯读心跳包 上报 */ @Data @ToString(callSuper = true) public class A5LightHeartbeatReportInnerFrame extends BaseResponseInnerFrame { // 目标地址 2 private String destinationAddress; // 心跳包数据 58 private HeartBeatDataPackage heartBeatDataPackage; private String originFrame; @Override public A5LightHeartbeatReportInnerFrame 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, 108); HeartBeatDataPackage heartBeatDataPackage = new HeartBeatDataPackage(); heartBeatDataPackage.transformFrame(heartBeatData); setHeartBeatDataPackage(heartBeatDataPackage); setCrc32(hex.substring(108, 116)); // 校验CRC32 String frame = hex.substring(2, hex.length() - 8); this.setValidate(CRC32Utils.validateFrame(frame, getCrc32())); return this; } @Data public static class HeartBeatDataPackage implements IResponseInnerFrame { // 年RTC 1 private Integer year; // 月RTC 1 private Integer month; // 日RTC 1 private Integer day; // 时RTC 1 private Integer hour; // 分RTC 1 private Integer min; // 秒RTC 1 private Integer sec; // 设备温度 2 1字节整数1字节小数 private Double deviceTemperature; // 灯1亮度百分比 1 private Integer lightPercent; // 电网电压 2 1字节整数1字节小数 private Double voltage; // 电网电流 2 1字节整数1字节小数 private Double electricCurrent; // 赫兹 2 1字节整数1字节小数 private Double hertz; // 功率因素 2 1字节整数1字节小数 private Double powerFactor; // 有功功率 2 1字节整数1字节小数 private Double activePower; // 无功功率 2 1字节整数1字节小数 private Double reactivePower; // 最近一次亮灯时间 4 秒 private Long recentlyLightSec; // 累计亮灯时间 4 private Long totalLightSec; // 最近一次用电电量 4 private Double recentlyUsingPower; // 累计用电电量 4 private Double totalUsingPower; // 灯2亮度百分比 1 private Integer light2Percent; // 保留 11 private String retain; // 原帧 private String originFrame; @Override public HeartBeatDataPackage transformFrame(String hex) { this.originFrame = hex; this.year = HexUtil.hexToInt(hex.substring(0, 2)); this.month = HexUtil.hexToInt(hex.substring(2, 4)); this.day = HexUtil.hexToInt(hex.substring(4, 6)); this.hour = HexUtil.hexToInt(hex.substring(6, 8)); this.min = HexUtil.hexToInt(hex.substring(8, 10)); this.sec = HexUtil.hexToInt(hex.substring(10, 12)); // //需要把十六进制转二进制 // this.deviceTemperature = NumberUtil.round(HexUtil.hexToInt(hex.substring(12, 16)) * 0.01, 2).doubleValue(); this.deviceTemperature = NumberUtil.round(temperatureTransition(hex.substring(12, 16)), 2).doubleValue(); this.lightPercent = HexUtil.hexToInt(hex.substring(16, 18)); this.voltage = NumberUtil.round(HexUtil.hexToInt(hex.substring(18, 22)) * 0.1, 1).doubleValue(); this.electricCurrent = NumberUtil.round(HexUtil.hexToInt(hex.substring(22, 26)) * 0.001, 3).doubleValue(); this.hertz = NumberUtil.round(HexUtil.hexToInt(hex.substring(26, 30)) * 0.01, 2).doubleValue(); this.powerFactor = NumberUtil.round(HexUtil.hexToInt(hex.substring(30, 34)) * 0.001, 3).doubleValue(); this.activePower = NumberUtil.round(HexUtil.hexToInt(hex.substring(34, 38)) * 0.01, 2).doubleValue(); this.reactivePower = NumberUtil.round(HexUtil.hexToInt(hex.substring(38, 42)) * 0.01, 2).doubleValue(); this.recentlyLightSec = HexUtil.hexToLong(hex.substring(42, 50)); this.totalLightSec = HexUtil.hexToLong(hex.substring(50, 58)); this.recentlyUsingPower = NumberUtil.round(HexUtil.hexToInt(hex.substring(58, 66)) * (double) 0.001, 3).doubleValue(); this.totalUsingPower = NumberUtil.round(HexUtil.hexToInt(hex.substring(66, 74)) * (double) 0.001, 3).doubleValue(); this.light2Percent = HexUtil.hexToInt(hex.substring(74, 76)); this.retain = hex.substring(76, 96); return this; } /** * 将16进制转成2进制,进行补码(反码基础上+1),得到正确数值 * 传入16进制的温度,类型为String * 如F500 */ public static 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 static 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; } } }