2021与蓝度共同重构项目,服务端
zhanzhiqin
2022-10-14 ea8e8e7dd5f10cff4054f5fde8fd3961aaac1834
大气设备农耕
已修改8个文件
已添加2个文件
656 ■■■■■ 文件已修改
dao/src/main/java/com/sandu/ximon/dao/domain/AirDataNongGeng.java 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ximon-admin/src/main/java/com/sandu/ximon/admin/controller/AirEquipmentNongGengController.java 58 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ximon-admin/src/main/java/com/sandu/ximon/admin/manager/iot/amqp/processor/AirDataProcessor.java 11 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ximon-admin/src/main/java/com/sandu/ximon/admin/manager/iot/frame/inner/report/A5AtmosphereNewHeartbeatReportInnerFrame.java 135 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ximon-admin/src/main/java/com/sandu/ximon/admin/manager/iot/rrpc/util/CRCUtils.java 24 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ximon-admin/src/main/java/com/sandu/ximon/admin/manager/iot/rrpc/util/CRCValidate.java 210 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ximon-admin/src/main/java/com/sandu/ximon/admin/manager/iot/rrpc/util/SupplementUtils.java 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ximon-admin/src/main/java/com/sandu/ximon/admin/service/AirDataNongGengService.java 53 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ximon-admin/src/main/java/com/sandu/ximon/admin/service/AirEquipmentNongGengService.java 146 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ximon-admin/src/main/resources/application-local.yml 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
dao/src/main/java/com/sandu/ximon/dao/domain/AirDataNongGeng.java
@@ -5,6 +5,7 @@
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import java.io.Serializable;
import java.time.LocalDateTime;
import java.util.Date;
import lombok.Data;
@@ -129,7 +130,7 @@
    /**
     * åˆ›å»ºæ—¶é—´
     */
    private Date createTime;
    private LocalDateTime createTime;
    @TableField(exist = false)
    private static final long serialVersionUID = 1L;
ximon-admin/src/main/java/com/sandu/ximon/admin/controller/AirEquipmentNongGengController.java
@@ -53,4 +53,62 @@
    public ResponseVO<Object> getAirEquipment(@PathVariable String mac) {
        return ResponseUtil.success(airEquipmentNongGengService.getAirEquipment(mac));
    }
    /**
     * è®¾ç½®å¿ƒè·³åŒ…间隔时间
     *
     * @param mac
     * @param time
     * @return
     */
    @GetMapping("/setHeartBeatTime")
    public ResponseVO<Object> setHeartBeatTime(@RequestParam(value = "mac", required = false) String mac,
                                               @RequestParam(value = "time", required = false) Integer time) {
        if (!permissionConfig.check(MenuEnum.AIR_HEARTBEATTIME.getCode())) {
            return ResponseUtil.fail("缺少对应用户权限");
        }
        return ResponseUtil.success(airEquipmentNongGengService.setHeartBeatTime(mac, time));
    }
    /**
     * æŸ¥è¯¢å¤§æ°”设备心跳包时间
     *
     * @return
     */
    @GetMapping("/QueryHeartBeatTime")
    public ResponseVO<Object> QueryHeartBeatTime(@RequestParam(value = "mac", required = false) String mac) {
        if (!permissionConfig.check(MenuEnum.AIR_HEARTBEATTIME.getCode())) {
            return ResponseUtil.fail("缺少对应用户权限");
        }
        return ResponseUtil.success(airEquipmentNongGengService.QueryHeartBeatTime(mac));
    }
    /**
     * æŸ¥è¯¢è½¯ç¡¬ä»¶ç‰ˆæœ¬
     *
     * @param mac
     * @return
     */
    @GetMapping("/QueryVersion")
    public ResponseVO<Object> QueryVersion(@RequestParam(value = "mac", required = false) String mac) {
        if (!permissionConfig.check(MenuEnum.AIR_QUERYVERSION.getCode())) {
            return ResponseUtil.fail("缺少对应用户权限");
        }
        return ResponseUtil.success(airEquipmentNongGengService.QueryVersion(mac));
    }
    /**
     * è½¯é‡å¯
     *
     * @param mac
     * @return
     */
    @GetMapping("/Reboot")
    public ResponseVO<Object> Reboot(@RequestParam(value = "mac", required = false) String mac) {
        if (!permissionConfig.check(MenuEnum.AIR_REBOOT.getCode())) {
            return ResponseUtil.fail("缺少对应用户权限");
        }
        return ResponseUtil.success(airEquipmentNongGengService.Reboot(mac));
    }
}
ximon-admin/src/main/java/com/sandu/ximon/admin/manager/iot/amqp/processor/AirDataProcessor.java
@@ -31,21 +31,26 @@
    @Override
    public void process(String productKey, String deviceName, CommonFrame frame) {
        /**
         * connectType用于判断主动上报的数据是属于旧大气设备还是农耕大气设备
         * å†œè€•心跳包主动上报系统地址(MQTT请求方式):01   åŠŸèƒ½ç ï¼š03
         */
        String connectType = frame.getPayload().substring(0, 2);
        String functionCode = frame.getPayload().substring(2, 4);
        if (A5AtmosphereReportEnum.HeartBeat_Data.getCode().equals(functionCode)) {
            log.info("心跳相应——大气数据");
            A5AtmosphereHeartbeatReportInnerFrame heartbeatReportInnerFrame = new A5AtmosphereHeartbeatReportInnerFrame().transformFrame(frame.getPayload());
            if(heartbeatReportInnerFrame != null){
            if (heartbeatReportInnerFrame != null) {
                log.info(heartbeatReportInnerFrame.toString());
                SpringContextHolder.getBean(AirDataService.class).saveReportData(deviceName, heartbeatReportInnerFrame.getHeartBeatDataPackage());
            }
        } else if (A5AtmosphereReportEnum.HeartBeat_Data_Nong_Geng.getCode().equals(functionCode)) {
        } else if (A5AtmosphereReportEnum.HeartBeat_Data_Nong_Geng.getCode().equals(functionCode) && "01".equals(connectType)) {
            log.info("心跳相应——大气数据(农耕)");
            A5AtmosphereNewHeartbeatReportInnerFrame heartbeatReportInnerFrame = new A5AtmosphereNewHeartbeatReportInnerFrame().transformFrame(frame.getPayload());
            if (heartbeatReportInnerFrame != null && heartbeatReportInnerFrame.isValidate()) {
                log.info(heartbeatReportInnerFrame.toString());
                SpringContextHolder.getBean(AirDataNongGengService.class).saveReportData(deviceName, heartbeatReportInnerFrame.getHeartBeatDataPackage());
            }else{
            } else {
                System.out.println("数据校验异常!");
            }
ximon-admin/src/main/java/com/sandu/ximon/admin/manager/iot/frame/inner/report/A5AtmosphereNewHeartbeatReportInnerFrame.java
@@ -5,6 +5,7 @@
import com.sandu.ximon.admin.manager.iot.frame.inner.IResponseInnerFrame;
import com.sandu.ximon.admin.manager.iot.rrpc.util.CRC16Utils;
import com.sandu.ximon.admin.manager.iot.rrpc.util.CRC32Utils;
import com.sandu.ximon.admin.manager.iot.rrpc.util.CRCUtils;
import lombok.Data;
import java.math.BigDecimal;
@@ -15,7 +16,7 @@
 */
@Data
public class A5AtmosphereNewHeartbeatReportInnerFrame extends BaseResponseInnerFrame<A5AtmosphereNewHeartbeatReportInnerFrame> {
    //ff03200241000000000000000000000009000a198a186327b8000c000000000000000b8c35c1cad6bf
    //010326FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF1B341022277F000D05B5000000015DDD0000FFFF000070C9    ä¸»åŠ¨ä¸ŠæŠ¥å¿ƒè·³åŒ…
    private HeartBeatDataPackage heartBeatDataPackage;
    @Override
@@ -26,7 +27,7 @@
        }
        //校验
        hex = hex.replaceAll(" ", "");
        if (hex.length() < 74) {
        if (hex.length() != 86) {
            return null;
        }
@@ -44,9 +45,9 @@
        setHeartBeatDataPackage(heartBeatDataPackage);
        setCrc16(hex.substring(hex.length() - 4));
        //  æ ¡éªŒCRC32
        //  æ ¡éªŒCRC16
        String frame = hex.substring(0, hex.length() - 4);
        this.setValidate(getCrc16().equals(CRC16Utils.getCRC16(frame)));
        this.setValidate(getCrc16().equals(CRCUtils.getCRC16(frame)));
        return this;
    }
@@ -84,47 +85,137 @@
        private BigDecimal radiation;
        //("光照")
        private BigDecimal illumination;
        //紫外指数
        private BigDecimal ultraviolet;
        //CO2
        private BigDecimal co2;
        //负氧离子
        private BigDecimal o2;
        @Override
        public HeartBeatDataPackage transformFrame(String hex) {
            //ff   03  20   0241000000000000000000000009000a198a186327b8000c000000000000000b8c35c1ca(参考值)
            // 0241 0000  0000 0000 0000 0000 0009  000a  198a  1863  27b8  000c  0000  0000  0000  000b  8c35  c1ca
//            010326FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF1B341022277F000D05B5000000015DDD0000FFFF000070C9    ä¸»åŠ¨ä¸ŠæŠ¥å¿ƒè·³åŒ…
//            01:系统地址
//            03:功能码
//            26:数据段字 èŠ‚æ•°é‡
//            FFFF:噪声-------》
//            FFFF:硫化氢-------》
//            FFFF:SO2 æµ“度-------》
//            FFFF:NO2 æµ“度-------》
//            FFFF:CO æµ“度-------》
//            FFFF:O3 æµ“度-------》
//            FFFF:PM2.5 æµ“度-------》
//            FFFF:PM10 æµ“度-------》
//            1B34:空气温度-------》29.64℃
//            1022:空气湿度-------》41.30%
//            277F:大气压强-------》101.11hPa
//            000D:风速-------》0.13m/s
//            05B5:风向-------》146.1°
//            0000:连续雨量-------》0mm
//            0001:辐射-------》1W/㎡
//            5DDD:光照-------》240.29Klux
//            0000:紫外指数-------》
//            FFFF:CO2-------》
//            0000:负氧离子-------》
//            70C9:CRC16 æ ¡éªŒä½
            //噪声
            this.noise = BigDecimal.valueOf(parseVal(hex, 6, 10) / 10.0);
            if (isValidData(hex, 6, 10)) {
                this.noise = new BigDecimal(parseVal(hex, 6, 10)).divide(new BigDecimal(10), 1, BigDecimal.ROUND_HALF_UP);
            }
            //硫化氢
            this.hydrogenSulfide = BigDecimal.valueOf(parseVal(hex, 10, 14) / 1.0);
            if (isValidData(hex, 10, 14)) {
                this.hydrogenSulfide = new BigDecimal(parseVal(hex, 10, 14));
            }
            //SO2 æµ“度
            this.so2 = BigDecimal.valueOf(parseVal(hex, 14, 18) / 1.0);
            if (isValidData(hex, 14, 18)) {
                this.so2 = new BigDecimal(parseVal(hex, 14, 18));
            }
            //NO2 æµ“度
            this.no2 = BigDecimal.valueOf(parseVal(hex, 18, 22) / 1.0);
            if (isValidData(hex, 18, 22)) {
                this.no2 = new BigDecimal(parseVal(hex, 18, 22));
            }
            //CO æµ“度
            this.co = BigDecimal.valueOf(parseVal(hex, 22, 26) / 1.0);
            if (isValidData(hex, 22, 26)) {
                this.co = new BigDecimal(parseVal(hex, 22, 26));
            }
            //O3 æµ“度
            this.o3 = BigDecimal.valueOf(parseVal(hex, 26, 30) / 1.0);
            if (isValidData(hex, 26, 30)) {
                this.o3 = new BigDecimal(parseVal(hex, 26, 30));
            }
            //PM2.5 æµ“度
            this.pm2point5 = BigDecimal.valueOf(parseVal(hex, 30, 34) / 1.0);
            if (isValidData(hex, 30, 34)) {
                this.pm2point5 = new BigDecimal(parseVal(hex, 30, 34));
            }
            //PM10 æµ“度
            this.pm10 = BigDecimal.valueOf(parseVal(hex, 34, 38) / 1.0);
            if (isValidData(hex, 34, 38)) {
                this.pm10 = new BigDecimal(parseVal(hex, 34, 38));
            }
            //空气温度
            this.airTemperature = BigDecimal.valueOf(parseVal(hex, 38, 42) / 100.0 - 40);
            if (isValidData(hex, 38, 42)) {
                this.airTemperature = new BigDecimal(parseVal(hex, 38, 42)).divide(new BigDecimal(100), 2, BigDecimal.ROUND_HALF_UP).subtract(new BigDecimal(40));
            }
            //空气湿度
            this.airHumidity = BigDecimal.valueOf(parseVal(hex, 42, 46) / 100.0);
            if (isValidData(hex, 42, 46)) {
                this.airHumidity = new BigDecimal(parseVal(hex, 42, 46)).divide(new BigDecimal(100), 2, BigDecimal.ROUND_HALF_UP);
            }
            //大气压强
            this.airPressure = BigDecimal.valueOf(parseVal(hex, 46, 50) / 10.0);
            if (isValidData(hex, 46, 50)) {
                this.airPressure = new BigDecimal(parseVal(hex, 46, 50)).divide(new BigDecimal(10), 1, BigDecimal.ROUND_HALF_UP);
            }
            //风速
            this.windSpeed = BigDecimal.valueOf(parseVal(hex, 50, 54) / 100.0);
            if (isValidData(hex, 50, 54)) {
                this.windSpeed = new BigDecimal(parseVal(hex, 50, 54)).divide(new BigDecimal(100), 2, BigDecimal.ROUND_HALF_UP);
            }
            //风向
            this.windDirection = BigDecimal.valueOf(parseVal(hex, 54, 58) / 10.0);
            if (isValidData(hex, 54, 58)) {
                this.windDirection = new BigDecimal(parseVal(hex, 54, 58)).divide(new BigDecimal(10), 1, BigDecimal.ROUND_HALF_UP);
            }
            //10 åˆ†é’Ÿé›¨é‡
            this.tenRainfallMin = BigDecimal.valueOf(parseVal(hex, 58, 62) / 10.0);
            if (isValidData(hex, 58, 62)) {
                this.tenRainfallMin = new BigDecimal(parseVal(hex, 58, 62)).divide(new BigDecimal(10), 1, BigDecimal.ROUND_HALF_UP);
            }
            //辐射
            this.radiation = BigDecimal.valueOf(parseVal(hex, 62, 66) / 1.0);
            if (isValidData(hex, 62, 66)) {
                this.radiation = new BigDecimal(parseVal(hex, 62, 66));
            }
            //光照
            this.illumination = BigDecimal.valueOf(parseVal(hex, 66, 70) / 100.0);
            if (isValidData(hex, 66, 70)) {
                this.illumination = new BigDecimal(parseVal(hex, 66, 70)).divide(new BigDecimal(100), 2, BigDecimal.ROUND_HALF_UP);
            }
            //紫外指数
            if (isValidData(hex, 70, 74)) {
                this.ultraviolet = new BigDecimal(parseVal(hex, 70, 74)).divide(new BigDecimal(1), 2, BigDecimal.ROUND_HALF_UP);
            }
            //CO2
            if (isValidData(hex, 74, 78)) {
                this.co2 = new BigDecimal(parseVal(hex, 74, 78));
            }
            //负氧离子
            if (isValidData(hex, 78, 82)) {
                this.o2 = BigDecimal.valueOf(parseVal(hex, 78, 82) * 10.0);
                this.o2 = new BigDecimal(parseVal(hex, 78, 82)).multiply(new BigDecimal(1));
            }
            return this;
        }
        /**
         * åˆ¤æ–­è¯¥å¤§æ°”设备是否有对应的感应器
         *
         * @param value
         * @param startIndex
         * @param endIndex
         * @return
         */
        private boolean isValidData(String value, int startIndex, int endIndex) {
            //FFFF是代表这个设备不支持这个数据项。0000是表示支持但是数据为零
            if ("FFFF".equals(value.substring(startIndex, endIndex))) {
                return false;
            } else {
                return true;
            }
        }
        private Integer parseVal(String frame, int start, int end) {
            return Integer.parseInt(frame.substring(start, end), 16);
        }
ximon-admin/src/main/java/com/sandu/ximon/admin/manager/iot/rrpc/util/CRCUtils.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,24 @@
package com.sandu.ximon.admin.manager.iot.rrpc.util;
public class CRCUtils {
    /**
     * è®¡ç®—CRC16/Modbus校验码  é«˜ä½åœ¨å‰,低位在后
     *
     * @param hex åå…­è¿›åˆ¶å­—符串
     * @return CRC16校验码
     */
    public static String getCRC16 (String hex) {
        byte[] tx_buff = SupplementUtils.hexStringToBytes(hex);
        int[] result = CRCValidate.calculateCRC(tx_buff, 0, tx_buff.length);
        String hex1 = Integer.toHexString(result[1]);
        String hex2 = Integer.toHexString(result[0]);
        if (hex1.length()<2) {
            hex1 = "0" + hex1;
        }
        if (hex2.length()<2) {
            hex2 = "0" + hex2;
        }
        return ( hex2 + hex1 ).toUpperCase();
    }
}
ximon-admin/src/main/java/com/sandu/ximon/admin/manager/iot/rrpc/util/CRCValidate.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,210 @@
package com.sandu.ximon.admin.manager.iot.rrpc.util;
/**
 * Created by 11833 on 2018/1/5.
 */
public class CRCValidate {
    private static final String TAG="CRCValidate";
    /**
     *  è®¡ç®—CRC
     * */
    public static final int[] calculateCRC(byte[] data, int offset, int len) {
        int[] crc = { 0xFF, 0xFF };
        int nextByte = 0;
        int uIndex;
        for (int i = offset; i < len && i < data.length; i++) {
            nextByte = 0xFF & ((int) data[i]);
            uIndex = crc[0] ^ nextByte;
            crc[0] = crc[1] ^ auchCRCHi[uIndex];
            crc[1] = auchCRCLo[uIndex];
        }
        return crc;
    }// calculateCRC
    /**
     * é”Ÿæ–¤æ‹·é”Ÿæ–¤æ‹·ä¸€ä½CRC??锟斤拷锟斤拷位锟斤拷锟?
     * é”Ÿæ–¤æ‹·ä¸€é”Ÿæ–¤æ‹·é”Ÿæ–¤æ‹·é”Ÿæ–¤æ‹·é”Ÿæ–¤æ‹·è¦é”Ÿæ–¤æ‹·é”Ÿæ–¤æ‹·é”Ÿçµ™uff
     * é”Ÿæ–¤æ‹·ä¸€é”Ÿæ–¤æ‹·é”Ÿæ–¤æ‹·é”Ÿæ–¤æ‹·é”Ÿæ–¤æ‹·é”Ÿæ–¤æ‹·å§‹ä½é”Ÿæ–¤æ‹·
     * é”Ÿæ–¤æ‹·é”Ÿæ–¤æ‹·é”Ÿæ–¤æ‹·é”Ÿæ–¤æ‹·é”Ÿæ–¤æ‹·é”Ÿæ–¤æ‹·é”Ÿæ–¤æ‹·é”Ÿå§é•¿é”Ÿæ–¤æ‹·
     *
     * */
    public static final int calculateSingleCRC(byte[] data, int offset, int len) {
        int crc = data[offset];
        /* pass through message buffer */
        for (int i = offset+1; i < (offset+len) && i < data.length; i++) {
            crc = crc ^ ((int) data[i]); // *puchMsg++; /* calculate the CRC */
        }
        return crc;
    }
    /**
     * /锟斤拷锟斤拷CRC?? é”Ÿæ–¤æ‹·ä¸€é”Ÿæ–¤æ‹·é”Ÿæ–¤æ‹·é”Ÿæ–¤æ‹·é”Ÿæ–¤æ‹·è¦é”Ÿæ–¤æ‹·é”Ÿæ–¤æ‹·é”ŸçµšalcStr
     * // "01 10 00 5e 00 02 04 11 12 13 14"锟矫碉拷crc="df 19"
     */
    public static final String calculateStringCRC(String calcStr) {
        String crcStr = null;
        if (SupplementUtils.isHex(calcStr)) {
            byte[] data = SupplementUtils.hexStringToBytes(calcStr);
            int[] crcIntArr = CRCValidate.calculateCRC(data, 0, data.length);
            byte[] crcByteArr1 = { 0, (byte) crcIntArr[0] };
            byte[] crcByteArr2 = { 0, (byte) crcIntArr[1] };
//            String crcStr1 = HexStrConvertUtil.bytesToHexString(crcByteArr1).substring(2);
//            String crcStr2 = HexStrConvertUtil.bytesToHexString(crcByteArr2).substring(2);
//            crcStr = crcStr1 + " " + crcStr2;
        }
        return crcStr.toLowerCase();
    }
    /* Table of CRC values for high-order byte */
    private final static short[] auchCRCHi = {
            0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
            0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
            0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
            0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
            0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
            0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
            0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
            0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
            0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
            0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,
            0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
            0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
            0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
            0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,
            0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
            0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
            0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
            0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
            0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
            0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
            0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
            0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,
            0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
            0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
            0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
            0x80, 0x41, 0x00, 0xC1, 0x81, 0x40
    };
    /* Table of CRC values for low-order byte */
    private final static short[] auchCRCLo = {
            0x00, 0xC0, 0xC1, 0x01, 0xC3, 0x03, 0x02, 0xC2, 0xC6, 0x06,
            0x07, 0xC7, 0x05, 0xC5, 0xC4, 0x04, 0xCC, 0x0C, 0x0D, 0xCD,
            0x0F, 0xCF, 0xCE, 0x0E, 0x0A, 0xCA, 0xCB, 0x0B, 0xC9, 0x09,
            0x08, 0xC8, 0xD8, 0x18, 0x19, 0xD9, 0x1B, 0xDB, 0xDA, 0x1A,
            0x1E, 0xDE, 0xDF, 0x1F, 0xDD, 0x1D, 0x1C, 0xDC, 0x14, 0xD4,
            0xD5, 0x15, 0xD7, 0x17, 0x16, 0xD6, 0xD2, 0x12, 0x13, 0xD3,
            0x11, 0xD1, 0xD0, 0x10, 0xF0, 0x30, 0x31, 0xF1, 0x33, 0xF3,
            0xF2, 0x32, 0x36, 0xF6, 0xF7, 0x37, 0xF5, 0x35, 0x34, 0xF4,
            0x3C, 0xFC, 0xFD, 0x3D, 0xFF, 0x3F, 0x3E, 0xFE, 0xFA, 0x3A,
            0x3B, 0xFB, 0x39, 0xF9, 0xF8, 0x38, 0x28, 0xE8, 0xE9, 0x29,
            0xEB, 0x2B, 0x2A, 0xEA, 0xEE, 0x2E, 0x2F, 0xEF, 0x2D, 0xED,
            0xEC, 0x2C, 0xE4, 0x24, 0x25, 0xE5, 0x27, 0xE7, 0xE6, 0x26,
            0x22, 0xE2, 0xE3, 0x23, 0xE1, 0x21, 0x20, 0xE0, 0xA0, 0x60,
            0x61, 0xA1, 0x63, 0xA3, 0xA2, 0x62, 0x66, 0xA6, 0xA7, 0x67,
            0xA5, 0x65, 0x64, 0xA4, 0x6C, 0xAC, 0xAD, 0x6D, 0xAF, 0x6F,
            0x6E, 0xAE, 0xAA, 0x6A, 0x6B, 0xAB, 0x69, 0xA9, 0xA8, 0x68,
            0x78, 0xB8, 0xB9, 0x79, 0xBB, 0x7B, 0x7A, 0xBA, 0xBE, 0x7E,
            0x7F, 0xBF, 0x7D, 0xBD, 0xBC, 0x7C, 0xB4, 0x74, 0x75, 0xB5,
            0x77, 0xB7, 0xB6, 0x76, 0x72, 0xB2, 0xB3, 0x73, 0xB1, 0x71,
            0x70, 0xB0, 0x50, 0x90, 0x91, 0x51, 0x93, 0x53, 0x52, 0x92,
            0x96, 0x56, 0x57, 0x97, 0x55, 0x95, 0x94, 0x54, 0x9C, 0x5C,
            0x5D, 0x9D, 0x5F, 0x9F, 0x9E, 0x5E, 0x5A, 0x9A, 0x9B, 0x5B,
            0x99, 0x59, 0x58, 0x98, 0x88, 0x48, 0x49, 0x89, 0x4B, 0x8B,
            0x8A, 0x4A, 0x4E, 0x8E, 0x8F, 0x4F, 0x8D, 0x4D, 0x4C, 0x8C,
            0x44, 0x84, 0x85, 0x45, 0x87, 0x47, 0x46, 0x86, 0x82, 0x42,
            0x43, 0x83, 0x41, 0x81, 0x80, 0x40
    };
    /*
     * é”Ÿå«è®¹æ‹·CRC值锟角凤拷锟斤拷确--CRC校锟斤拷
     */
    public static Boolean isCRCConfig(byte[] buff) {
        int offset = 0;
        int len = buff.length - 2;
        // é”Ÿæ–¤æ‹·é”Ÿæ–¤æ‹·å‰é”Ÿæ–¤æ‹·æ¨¡é”Ÿæ–¤æ‹·é”Ÿè¡—凤拷锟街革拷睢拷锟斤拷荩锟斤拷锟斤拷锟叫o拷锟斤拷耄╋拷锟?
        // é”Ÿæ–¤æ‹·é”Ÿæ–¤æ‹·CRC值,(锟斤拷一锟斤拷锟斤拷锟斤拷锟斤拷要锟斤拷锟斤拷锟絙uff é”Ÿæ–¤æ‹·ä¸€é”Ÿæ–¤æ‹·é”Ÿæ–¤æ‹·é”Ÿæ–¤æ‹·é”Ÿæ–¤æ‹·é”Ÿæ–¤æ‹·å§‹ä½ é”Ÿæ–¤æ‹·é”Ÿæ–¤æ‹·é”Ÿæ–¤æ‹·é”Ÿæ–¤æ‹·é”Ÿæ–¤æ‹·é”Ÿæ–¤æ‹·é”Ÿæ–¤æ‹·é”Ÿå§é•¿é”Ÿæ–¤æ‹·)
        int[] crc = CRCValidate.calculateCRC(buff, offset, len);
        // é”Ÿé¥ºæ–¤æ‹·buff锟斤拷锟斤拷锟斤拷锟轿籆RC锟斤拷锟角凤拷锟斤拷诩锟斤拷锟斤拷锟斤拷锟斤拷CRC锟斤拷
        return (byte) crc[0] == buff[buff.length - 2] & (byte) crc[1] == buff[buff.length - 1];
    }
}
ximon-admin/src/main/java/com/sandu/ximon/admin/manager/iot/rrpc/util/SupplementUtils.java
@@ -76,4 +76,18 @@
    }
    public static boolean isHex(String str) {
        boolean isHexFlg = true;
        int i = 0;
        char c;
        for (i = 0; i < str.length(); i++) {
            c = str.charAt(i);
            if (!(((c >= '0') && (c <= '9')) || ((c >= 'A') && (c <= 'F')) || ((c >= 'a') && (c <= 'f')) || (c == ' '))) {
                isHexFlg = false;
                break;
            }
        }
        return isHexFlg;
    }
}
ximon-admin/src/main/java/com/sandu/ximon/admin/service/AirDataNongGengService.java
@@ -1,26 +1,15 @@
package com.sandu.ximon.admin.service;
import cn.hutool.core.collection.CollUtil;
import com.github.pagehelper.PageHelper;
import com.sandu.common.object.BaseConditionVO;
import com.sandu.common.service.impl.BaseServiceImpl;
import com.sandu.ximon.admin.manager.iot.frame.inner.report.A5AtmosphereHeartbeatReportInnerFrame;
import com.sandu.ximon.admin.manager.iot.frame.inner.report.A5AtmosphereNewHeartbeatReportInnerFrame;
import com.sandu.ximon.admin.manager.iot.rrpc.enums.AtmoFunctionCode;
import com.sandu.ximon.admin.security.SecurityUtils;
import com.sandu.ximon.admin.utils.RedisUtils;
import com.sandu.ximon.dao.bo.AirDataBo;
import com.sandu.ximon.dao.bo.AirDataNongGengBo;
import com.sandu.ximon.dao.domain.AirData;
import com.sandu.ximon.dao.domain.AirDataNongGeng;
import com.sandu.ximon.dao.domain.AirEquipment;
import com.sandu.ximon.dao.domain.AirEquipmentNongGeng;
import com.sandu.ximon.dao.mapper.AirDataNongGengMapper;
import lombok.AllArgsConstructor;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import java.util.List;
/**
 * å¤§æ°”数据,农耕硬件
@@ -41,7 +30,45 @@
    public boolean saveReportData(String deviceName, A5AtmosphereNewHeartbeatReportInnerFrame.HeartBeatDataPackage heartBeatDataPackage) {
        AirDataNongGeng airDataNongGeng = new AirDataNongGeng();
        BeanUtils.copyProperties(heartBeatDataPackage, airDataNongGeng);
        //("噪声")
        airDataNongGeng.setNoise(heartBeatDataPackage.getNoise() == null ? null : heartBeatDataPackage.getNoise() + "dB");
        //("硫化氢")
        airDataNongGeng.setHydrogenSulfide(heartBeatDataPackage.getHydrogenSulfide() == null ? null : heartBeatDataPackage.getHydrogenSulfide() + "");
        //("SO2 æµ“度")
        airDataNongGeng.setSo2(heartBeatDataPackage.getSo2() == null ? null : heartBeatDataPackage.getSo2() + "ppb");
        //("NO2 æµ“度")
        airDataNongGeng.setNo2(heartBeatDataPackage.getNo2() == null ? null : heartBeatDataPackage.getNo2() + "ppb");
        //("CO æµ“度")
        airDataNongGeng.setCo(heartBeatDataPackage.getCo() == null ? null : heartBeatDataPackage.getCo() + "ppb");
        //("O3 æµ“度")
        airDataNongGeng.setO3(heartBeatDataPackage.getO3() == null ? null : heartBeatDataPackage.getO3() + "ppb");
        //("PM2.5 æµ“度")
        airDataNongGeng.setPm2point5(heartBeatDataPackage.getPm2point5() == null ? null : heartBeatDataPackage.getPm2point5() + "ug/m³");
        //("PM10 æµ“度")
        airDataNongGeng.setPm10(heartBeatDataPackage.getPm10() == null ? null : heartBeatDataPackage.getPm10() + "ug/m³");
        //("空气温度")
        airDataNongGeng.setAirTemperature(heartBeatDataPackage.getAirTemperature() == null ? null : heartBeatDataPackage.getAirTemperature() + "℃");
        //("空气湿度")
        airDataNongGeng.setAirHumidity(heartBeatDataPackage.getAirHumidity() == null ? null : heartBeatDataPackage.getAirHumidity() + "%");
        //("大气压强")
        airDataNongGeng.setAirPressure(heartBeatDataPackage.getAirPressure() == null ? null : heartBeatDataPackage.getAirPressure() + "hPa");
        //("风速")
        airDataNongGeng.setWindSpeed(heartBeatDataPackage.getWindSpeed() == null ? null : heartBeatDataPackage.getWindSpeed() + "m/s");
        //("风向")
        airDataNongGeng.setWindDirection(heartBeatDataPackage.getWindDirection() == null ? null : heartBeatDataPackage.getWindDirection() + "°");
        //("10 åˆ†é’Ÿé›¨é‡")
        airDataNongGeng.setTenRainfallMin(heartBeatDataPackage.getTenRainfallMin() == null ? null : heartBeatDataPackage.getTenRainfallMin() + "mm");
        //("辐射")
        airDataNongGeng.setRadiation(heartBeatDataPackage.getRadiation() == null ? null : heartBeatDataPackage.getRadiation() + "0W/㎡");
        //("光照")
        airDataNongGeng.setIllumination(heartBeatDataPackage.getIllumination() == null ? null : heartBeatDataPackage.getIllumination() + "Klux");
        //紫外指数
        airDataNongGeng.setUltraviolet(heartBeatDataPackage.getUltraviolet() == null ? null : heartBeatDataPackage.getUltraviolet() + "");
        //CO2
        airDataNongGeng.setCo2(heartBeatDataPackage.getCo2() == null ? null : heartBeatDataPackage.getCo2() + "0ppm");
        //负氧离子
        airDataNongGeng.setO2(heartBeatDataPackage.getO2() == null ? null : heartBeatDataPackage.getO2() + "个");
        airDataNongGeng.setMac(deviceName);
        //将设备信息添加到大气设备表
@@ -57,6 +84,8 @@
        return save(airDataNongGeng);
    }
//
//    /**
//     * æŸ¥è¯¢å¤§æ°”数据(模糊查询)
ximon-admin/src/main/java/com/sandu/ximon/admin/service/AirEquipmentNongGengService.java
@@ -5,11 +5,25 @@
import com.sandu.common.execption.BusinessException;
import com.sandu.common.object.BaseConditionVO;
import com.sandu.common.service.impl.BaseServiceImpl;
import com.sandu.common.util.SpringContextHolder;
import com.sandu.ximon.admin.manager.iot.frame.A5Frame;
import com.sandu.ximon.admin.manager.iot.frame.inner.report.A5AtmosphereHeartBeatTimeReportInnerFrame;
import com.sandu.ximon.admin.manager.iot.frame.inner.report.A5AtmosphereOperationReportInnerFrame;
import com.sandu.ximon.admin.manager.iot.frame.inner.report.A5AtmosphereQueryVersionReportInnerFrame;
import com.sandu.ximon.admin.manager.iot.frame.inner.request.AtmosphereQueryHeartBeatTimeReqInnerFrame;
import com.sandu.ximon.admin.manager.iot.frame.inner.request.AtmosphereQueryVersionReqInnerFrame;
import com.sandu.ximon.admin.manager.iot.frame.inner.request.AtmosphereRebootReqInnerFrame;
import com.sandu.ximon.admin.manager.iot.frame.inner.request.AtmosphereSetHeartBeatTimeReqInnerFrame;
import com.sandu.ximon.admin.manager.iot.rrpc.dto.CommonFrame;
import com.sandu.ximon.admin.manager.iot.rrpc.enums.A5OrderEnum;
import com.sandu.ximon.admin.manager.iot.rrpc.enums.AtmoFunctionCode;
import com.sandu.ximon.admin.manager.iot.rrpc.mainboard.MainBoardInvokeSyncService;
import com.sandu.ximon.admin.security.SecurityUtils;
import com.sandu.ximon.admin.utils.RedisUtils;
import com.sandu.ximon.admin.utils.StoreOperationRecordsUtils;
import com.sandu.ximon.admin.utils.StringUtil;
import com.sandu.ximon.dao.bo.AirEquipmentNongGengBo;
import com.sandu.ximon.dao.domain.AirEquipment;
import com.sandu.ximon.dao.domain.AirEquipmentNongGeng;
import com.sandu.ximon.dao.mapper.AirEquipmentNongGengMapper;
import lombok.AllArgsConstructor;
@@ -131,4 +145,136 @@
        }
        return one;
    }
    /**
     * è®¾ç½®å¤§æ°”设备心跳包间隔时间
     *
     * @param mac
     * @param time
     */
    public String setHeartBeatTime(String mac, Integer time) {
        if (StringUtil.strIsNullOrEmpty(mac)) {
            throw new BusinessException("灯杆mac参数错误!");
        }
        if (time == null) {
            throw new BusinessException("心跳包间隔时间不能为空!");
        }
        if (time < 30) {
            throw new BusinessException("心跳包间隔时间不能少于30s!");
        }
        AirEquipmentNongGeng airEquipmentNongGeng = SpringContextHolder.getBean(AirEquipmentNongGengService.class).
                getOne(Wrappers.lambdaQuery(AirEquipmentNongGeng.class).eq(AirEquipmentNongGeng::getMac, mac).last("limit 1"));
        if (airEquipmentNongGeng == null) {
            throw new BusinessException("大气设备不存在!");
        }
        AtmosphereSetHeartBeatTimeReqInnerFrame atmosphereSetHeartBeatTimeReqInnerFrame = new AtmosphereSetHeartBeatTimeReqInnerFrame(time);
        A5Frame a5Frame = new A5Frame(A5OrderEnum.REQUEST_ATMOSPHERE_DATA.getCode(), atmosphereSetHeartBeatTimeReqInnerFrame);
        System.out.println(a5Frame + "          --------a5Frame");
        CommonFrame commonFrame = MainBoardInvokeSyncService.getInstance().sendRRPC(mac, a5Frame);
        System.out.println(commonFrame + "         -----------commonFrame");
        A5AtmosphereOperationReportInnerFrame a5AtmosphereOperationReportInnerFrame
                = new A5AtmosphereOperationReportInnerFrame().transformFrame(commonFrame.getPayload());
        if (a5AtmosphereOperationReportInnerFrame != null && a5AtmosphereOperationReportInnerFrame.isValidate()) {
            return a5AtmosphereOperationReportInnerFrame.getState();
        } else {
            throw new BusinessException("数据校验异常!");
        }
    }
    /**
     * æŸ¥è¯¢å¤§æ°”设备心跳包时间
     */
    public String QueryHeartBeatTime(String mac) {
        if (StringUtil.strIsNullOrEmpty(mac)) {
            throw new BusinessException("灯杆mac参数错误!");
        }
        AirEquipmentNongGeng airEquipmentNongGeng = SpringContextHolder.getBean(AirEquipmentNongGengService.class).
                getOne(Wrappers.lambdaQuery(AirEquipmentNongGeng.class).eq(AirEquipmentNongGeng::getMac, mac).last("limit 1"));
        if (airEquipmentNongGeng == null) {
            throw new BusinessException("大气设备不存在!");
        }
        AtmosphereQueryHeartBeatTimeReqInnerFrame atmosphereQueryHeartBeatTimeReqInnerFrame = new AtmosphereQueryHeartBeatTimeReqInnerFrame();
        A5Frame a5Frame = new A5Frame(A5OrderEnum.REQUEST_ATMOSPHERE_DATA.getCode(), atmosphereQueryHeartBeatTimeReqInnerFrame);
        System.out.println(a5Frame + "          --------a5Frame");
        CommonFrame commonFrame = MainBoardInvokeSyncService.getInstance().sendRRPC(mac, a5Frame);
        System.out.println(commonFrame + "         -----------commonFrame");
        A5AtmosphereHeartBeatTimeReportInnerFrame a5AtmosphereHeartBeatTimeReportInnerFrame
                = new A5AtmosphereHeartBeatTimeReportInnerFrame().transformFrame(commonFrame.getPayload());
        if (a5AtmosphereHeartBeatTimeReportInnerFrame != null && a5AtmosphereHeartBeatTimeReportInnerFrame.isValidate()) {
            return "该大气设备心跳包间隔时间为:" + a5AtmosphereHeartBeatTimeReportInnerFrame.getIntervalTime() + "s";
        } else {
            throw new BusinessException("数据校验异常!");
        }
    }
    /**
     * æŸ¥è¯¢è½¯ç¡¬ä»¶ç‰ˆæœ¬
     *
     * @param mac
     * @return
     */
    public String QueryVersion(String mac) {
        if (StringUtil.strIsNullOrEmpty(mac)) {
            throw new BusinessException("灯杆mac参数错误!");
        }
        AirEquipmentNongGeng airEquipmentNongGeng = SpringContextHolder.getBean(AirEquipmentNongGengService.class).
                getOne(Wrappers.lambdaQuery(AirEquipmentNongGeng.class).eq(AirEquipmentNongGeng::getMac, mac).last("limit 1"));
        if (airEquipmentNongGeng == null) {
            throw new BusinessException("大气设备不存在!");
        }
        AtmosphereQueryVersionReqInnerFrame atmosphereQueryVersionReqInnerFrame = new AtmosphereQueryVersionReqInnerFrame();
        A5Frame a5Frame = new A5Frame(A5OrderEnum.REQUEST_ATMOSPHERE_DATA.getCode(), atmosphereQueryVersionReqInnerFrame);
        System.out.println(a5Frame + "          --------a5Frame");
        CommonFrame commonFrame = MainBoardInvokeSyncService.getInstance().sendRRPC(mac, a5Frame);
        System.out.println(commonFrame + "         -----------commonFrame");
        A5AtmosphereQueryVersionReportInnerFrame a5AtmosphereQueryVersionReportInnerFrame =
                new A5AtmosphereQueryVersionReportInnerFrame().transformFrame(commonFrame.getPayload());
        if (a5AtmosphereQueryVersionReportInnerFrame != null && a5AtmosphereQueryVersionReportInnerFrame.isValidate()) {
            return a5AtmosphereQueryVersionReportInnerFrame.getVersion();
        } else {
            throw new BusinessException("数据校验异常!");
        }
    }
    /**
     * è½¯é‡å¯
     *
     * @param mac
     * @return
     */
    public String Reboot(String mac) {
        if (StringUtil.strIsNullOrEmpty(mac)) {
            throw new BusinessException("灯杆mac参数错误!");
        }
        AirEquipmentNongGeng airEquipmentNongGeng = SpringContextHolder.getBean(AirEquipmentNongGengService.class).
                getOne(Wrappers.lambdaQuery(AirEquipmentNongGeng.class).eq(AirEquipmentNongGeng::getMac, mac).last("limit 1"));
        if (airEquipmentNongGeng == null) {
            throw new BusinessException("大气设备不存在!");
        }
        AtmosphereRebootReqInnerFrame atmosphereRebootReqInnerFrame = new AtmosphereRebootReqInnerFrame();
        A5Frame a5Frame = new A5Frame(A5OrderEnum.REQUEST_ATMOSPHERE_DATA.getCode(), atmosphereRebootReqInnerFrame);
        System.out.println(a5Frame + "          --------a5Frame");
        CommonFrame commonFrame = MainBoardInvokeSyncService.getInstance().sendRRPC(mac, a5Frame);
        System.out.println(commonFrame + "         -----------commonFrame");
        A5AtmosphereOperationReportInnerFrame a5AtmosphereOperationReportInnerFrame =
                new A5AtmosphereOperationReportInnerFrame().transformFrame(commonFrame.getPayload());
        if (a5AtmosphereOperationReportInnerFrame != null && a5AtmosphereOperationReportInnerFrame.isValidate()) {
            return a5AtmosphereOperationReportInnerFrame.getState();
        } else {
            throw new BusinessException("数据校验异常!");
        }
    }
}
ximon-admin/src/main/resources/application-local.yml
@@ -39,7 +39,7 @@
    enable: true
listenter:
  isOpen: false
  isOpen: true
minio:
  endpoint: 47.106.172.9