2021与蓝度共同重构项目,服务端
liuhaonan
2022-05-07 cf1b764eedd475949b02b9c0a7881eccb09b958a
Merge remote-tracking branch 'origin/master'
已添加26个文件
已修改2个文件
1537 ■■■■■ 文件已修改
dao/src/main/java/com/sandu/ximon/dao/domain/RemoteUpdateFile.java 62 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
dao/src/main/java/com/sandu/ximon/dao/mapper/RemoteUpdateFileMapper.java 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
dao/src/main/resources/mapper/RemoteUpdateFileMapper.xml 23 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ximon-admin/src/main/java/com/sandu/ximon/admin/controller/RemoteUpdateController.java 190 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ximon-admin/src/main/java/com/sandu/ximon/admin/dto/RemoteFileDto.java 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ximon-admin/src/main/java/com/sandu/ximon/admin/dto/RemoteUpdateTypeDto.java 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ximon-admin/src/main/java/com/sandu/ximon/admin/manager/iot/frame/inner/report/RemoteFinishUpdateReportInnerFrame.java 46 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ximon-admin/src/main/java/com/sandu/ximon/admin/manager/iot/frame/inner/report/RemoteSearchLoseDataReportInnerFrame.java 94 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ximon-admin/src/main/java/com/sandu/ximon/admin/manager/iot/frame/inner/report/RemoteSearchUpdateResultReportInnerFrame.java 47 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ximon-admin/src/main/java/com/sandu/ximon/admin/manager/iot/frame/inner/report/RemoteStartUpdateReportInnerFrame.java 63 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ximon-admin/src/main/java/com/sandu/ximon/admin/manager/iot/frame/inner/report/RemoteStopUpdateReportInnerFrame.java 40 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ximon-admin/src/main/java/com/sandu/ximon/admin/manager/iot/frame/inner/report/RemoteUpdateFileInfoReportInnerFrame.java 46 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ximon-admin/src/main/java/com/sandu/ximon/admin/manager/iot/frame/inner/request/A5LightBrightnessReqInnerFrame.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
ximon-admin/src/main/java/com/sandu/ximon/admin/manager/iot/frame/inner/request/C3QrCodeReqInnerFrame.java 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ximon-admin/src/main/java/com/sandu/ximon/admin/manager/iot/frame/inner/request/RemoteFinishUpdateReqInnerFrame.java 24 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ximon-admin/src/main/java/com/sandu/ximon/admin/manager/iot/frame/inner/request/RemoteSearchLoseDataReqInnerFrame.java 24 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ximon-admin/src/main/java/com/sandu/ximon/admin/manager/iot/frame/inner/request/RemoteSearchUpdateResultReqInnerFrame.java 25 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ximon-admin/src/main/java/com/sandu/ximon/admin/manager/iot/frame/inner/request/RemoteSendFileReqInnerFrame.java 38 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ximon-admin/src/main/java/com/sandu/ximon/admin/manager/iot/frame/inner/request/RemoteStartUpdateReqInnerFrame.java 51 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ximon-admin/src/main/java/com/sandu/ximon/admin/manager/iot/frame/inner/request/RemoteStopUpdateReqInnerFrame.java 24 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ximon-admin/src/main/java/com/sandu/ximon/admin/manager/iot/frame/inner/request/RemoteUpdateDataReqInnerFrame.java 35 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ximon-admin/src/main/java/com/sandu/ximon/admin/manager/iot/rrpc/enums/RemoteUpdateEnum.java 34 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ximon-admin/src/main/java/com/sandu/ximon/admin/manager/iot/rrpc/enums/RemoteUpdateTypeEnum.java 55 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ximon-admin/src/main/java/com/sandu/ximon/admin/manager/iot/rrpc/util/FileProcessingUtils.java 61 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ximon-admin/src/main/java/com/sandu/ximon/admin/param/RemotePrarm.java 54 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ximon-admin/src/main/java/com/sandu/ximon/admin/param/RemoteUpdateParam.java 50 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ximon-admin/src/main/java/com/sandu/ximon/admin/service/RemoteUpdateService.java 236 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ximon-admin/src/main/java/com/sandu/ximon/admin/utils/HexUtils.java 161 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
dao/src/main/java/com/sandu/ximon/dao/domain/RemoteUpdateFile.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,62 @@
package com.sandu.ximon.dao.domain;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import java.io.Serializable;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import lombok.Data;
/**
 *
 * @TableName remote_update_file
 */
@TableName(value ="remote_update_file")
@Data
public class RemoteUpdateFile implements Serializable {
    /**
     *
     */
    @TableId(type = IdType.AUTO)
    private Integer id;
    /**
     * å‡çº§æ–‡ä»¶å
     */
    private String filename;
    /**
     * è½¯ä»¶ç‰ˆæœ¬
     */
    private BigDecimal softwareVersion;
    /**
     * ç¡¬ä»¶ç‰ˆæœ¬
     */
    private BigDecimal hardwareVersion;
    /**
     * é˜¿é‡Œæ–‡ä»¶å­˜å‚¨åœ°å€
     */
    private String aliAddress;
    /**
     * æ–‡ä»¶ç±»åž‹
     */
    private String fileType;
    /**
     *
     */
    private LocalDateTime createTime;
    /**
     * æ–‡ä»¶é•¿åº¦
     */
    private String fileLength;
    @TableField(exist = false)
    private static final long serialVersionUID = 1L;
}
dao/src/main/java/com/sandu/ximon/dao/mapper/RemoteUpdateFileMapper.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,17 @@
package com.sandu.ximon.dao.mapper;
import com.sandu.ximon.dao.domain.RemoteUpdateFile;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
/**
 * @Entity com.sandu.ximon.dao.domain.RemoteUpdateFile
 */
@Mapper
public interface RemoteUpdateFileMapper extends BaseMapper<RemoteUpdateFile> {
}
dao/src/main/resources/mapper/RemoteUpdateFileMapper.xml
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.sandu.ximon.dao.mapper.RemoteUpdateFileMapper">
    <resultMap id="BaseResultMap" type="com.sandu.ximon.dao.domain.RemoteUpdateFile">
            <id property="id" column="id" jdbcType="INTEGER"/>
            <result property="filename" column="filename" jdbcType="VARCHAR"/>
            <result property="softwareVersion" column="software_version" jdbcType="DECIMAL"/>
            <result property="hardwareVersion" column="hardware_version" jdbcType="DECIMAL"/>
            <result property="aliAddress" column="ali_address" jdbcType="VARCHAR"/>
            <result property="fileType" column="file_type" jdbcType="VARCHAR"/>
            <result property="createTime" column="create_time" jdbcType="TIMESTAMP"/>
            <result property="fileLength" column="file_length" jdbcType="VARCHAR"/>
    </resultMap>
    <sql id="Base_Column_List">
        id,filename,software_version,
        hardware_version,ali_address,file_type,
        create_time,file_length
    </sql>
</mapper>
ximon-admin/src/main/java/com/sandu/ximon/admin/controller/RemoteUpdateController.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,190 @@
package com.sandu.ximon.admin.controller;
import com.sandu.common.domain.ResponseVO;
import com.sandu.common.execption.BusinessException;
import com.sandu.common.security.annotation.AnonymousAccess;
import com.sandu.common.util.ResponseUtil;
import com.sandu.ximon.admin.dto.RemoteFileDto;
import com.sandu.ximon.admin.manager.iot.rrpc.enums.A5OrderEnum;
import com.sandu.ximon.admin.param.RemotePrarm;
import com.sandu.ximon.admin.param.RemoteUpdateParam;
import com.sandu.ximon.admin.service.RemoteUpdateService;
import com.sandu.ximon.admin.utils.HexUtils;
import com.sandu.ximon.admin.utils.StringUtil;
import lombok.AllArgsConstructor;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.util.Arrays;
import java.util.List;
/**
 * å›ºä»¶å‡çº§Controller
 *
 * @author ZZQ
 * @date 2022/4/11 17:06
 */
@AllArgsConstructor
@RestController
@RequestMapping("/v1/remoteupdate")
public class RemoteUpdateController {
    private RemoteUpdateService remoteUpdateService;
    @AnonymousAccess
    @PostMapping("/add")
    public ResponseVO<Object> addRemoteUpdateFile(@RequestBody @Validated RemoteUpdateParam param) {
        boolean flag = remoteUpdateService.addRemoteUpdateFile(param.getFilename(), param.getFileType()
                , param.getSoftwareVersion(), param.getHardwareVersion(), param.getAliAddress(), param.getFileLength());
        return ResponseUtil.success(flag);
    }
    @AnonymousAccess
    @GetMapping("/getRemoteFileList")
    public ResponseVO<Object> getRemoteFileList() {
        return ResponseUtil.success(remoteUpdateService.getRemoteFileList());
    }
    @GetMapping("/getRemoteUpdateTypeList")
    public ResponseVO<Object> getRemoteUpdateTypeList() {
        return ResponseUtil.success(remoteUpdateService.getRemoteUpdateTypeList());
    }
    /**
     * å¯åŠ¨è¿œç¨‹å‡çº§å‘½ä»¤
     *
     * @return
     */
    //TODO
    @AnonymousAccess
    @PostMapping("/StartRemoteUpdate")
    public ResponseVO<Object> startRemoteUpdate(@RequestBody @Validated RemotePrarm remotePrarm) {
        String orderType;
        boolean UpdateFlag = false;
        switch (remotePrarm.getDeviceType()) {
            case "MQTT串口":
            case "CAT1":
                orderType = A5OrderEnum.REQUEST_LIGHT_DATA.getCode();
                break;
            case "大气":
                orderType = A5OrderEnum.REQUEST_ATMOSPHERE_DATA.getCode();
                break;
            case "C3充电桩":
                orderType = A5OrderEnum.REQUEST_C3_DATA.getCode();
                break;
            case "杆体倾斜":
                orderType = A5OrderEnum.REQUEST_POLE_MONITOR_DATA.getCode();
                break;
            default:
                throw new BusinessException("升级硬件设备类型指令有误,请确认!");
        }
        //启动远程升级命令
        boolean startRemoteUpdateFlag = remoteUpdateService.StartRemoteUpdate(orderType, remotePrarm.getMac(), remotePrarm.getHardwareVersion()
                , remotePrarm.getSoftwareVersion(), remotePrarm.getUpdateFlag());
        if (startRemoteUpdateFlag) {
            //服务器下发升级文件信息
            //"C:\\Users\\Administrator\\Desktop\\test\\MQTT-过滤大气版本1-09-20220310.bin"
            RemoteFileDto remoteFileDto = remoteUpdateService.UpdateFileInfo(orderType, remotePrarm.getMac(), remotePrarm.getAliAddress());
            if (remoteFileDto != null) {
                System.out.println(remoteFileDto.getList().size());
                for (int i = 0; i < remoteFileDto.getList().size(); i++) {
                    //升级包数据
                    remoteUpdateService.UpdateData(orderType, remotePrarm.getMac(), i, remoteFileDto.getList().get(i));
                }
                //服务器下发查询漏包帧
                boolean searchLoseDataFlag = remoteUpdateService.SearchLoseData(orderType, remotePrarm.getMac(), remoteFileDto, 0);
                if (searchLoseDataFlag) {
                    //服务器下发结束升级帧
                    boolean finishUpdateFlag = remoteUpdateService.FinishUpdate(orderType, remotePrarm.getMac());
                    UpdateFlag = finishUpdateFlag;
                }
            }
        }
        if (UpdateFlag) {
            return ResponseUtil.success("升级成功!");
        } else {
            return ResponseUtil.fail("升级失败!");
        }
    }
    /**
     * æŸ¥è¯¢å›ºä»¶ç‰ˆæœ¬å·
     *
     * @param remotePrarm
     * @return
     */
    @AnonymousAccess
    @PostMapping("/searchUpdateResult")
    public ResponseVO<Object> searchUpdateResult(@RequestBody RemotePrarm remotePrarm) {
        if (remotePrarm.getMac() == null || remotePrarm.getDeviceType() == null) {
            throw new BusinessException("缺少相关参数!");
        }
        String orderType;
        switch (remotePrarm.getDeviceType()) {
            case "MQTT串口":
            case "CAT1":
                orderType = A5OrderEnum.REQUEST_LIGHT_DATA.getCode();
                break;
            case "大气":
                orderType = A5OrderEnum.REQUEST_ATMOSPHERE_DATA.getCode();
                break;
            case "C3充电桩":
                orderType = A5OrderEnum.REQUEST_C3_DATA.getCode();
                break;
            case "杆体倾斜":
                orderType = A5OrderEnum.REQUEST_POLE_MONITOR_DATA.getCode();
                break;
            default:
                throw new BusinessException("升级硬件设备类型指令有误,请确认!");
        }
        //服务器下发升级结果查询
        String result = remoteUpdateService.SearchUpdateResult(orderType, remotePrarm.getMac());
        return ResponseUtil.success(result);
    }
    /**
     * ç´§æ€¥ä¸­æ–­å‡çº§æŽ§åˆ¶å¸§
     *
     * @param remotePrarm
     * @return
     */
    @AnonymousAccess
    @PostMapping("/stopUpdate")
    public ResponseVO<Object> stopUpdate(@RequestBody RemotePrarm remotePrarm) {
        if (remotePrarm.getMac() == null || remotePrarm.getDeviceType() == null) {
            throw new BusinessException("缺少相关参数!");
        }
        String orderType;
        switch (remotePrarm.getDeviceType()) {
            case "MQTT串口":
            case "CAT1":
                orderType = A5OrderEnum.REQUEST_LIGHT_DATA.getCode();
                break;
            case "大气":
                orderType = A5OrderEnum.REQUEST_ATMOSPHERE_DATA.getCode();
                break;
            case "C3充电桩":
                orderType = A5OrderEnum.REQUEST_C3_DATA.getCode();
                break;
            case "杆体倾斜":
                orderType = A5OrderEnum.REQUEST_POLE_MONITOR_DATA.getCode();
                break;
            default:
                throw new BusinessException("升级硬件设备类型指令有误,请确认!");
        }
        //服务器下发升级结果查询
        boolean flag = remoteUpdateService.stopUpdate(orderType, remotePrarm.getMac());
        if (flag) {
            return ResponseUtil.success("紧急结束升级成功");
        } else {
            return ResponseUtil.success("紧急结束升级失败");
        }
    }
}
ximon-admin/src/main/java/com/sandu/ximon/admin/dto/RemoteFileDto.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,16 @@
package com.sandu.ximon.admin.dto;
import lombok.Data;
import java.util.List;
/**
 * @author ZZQ
 * @date 2022/5/5 14:40
 */
@Data
public class RemoteFileDto {
    private List<String> list;
    private int listSize = 0;
    private String fileHexStr;
}
ximon-admin/src/main/java/com/sandu/ximon/admin/dto/RemoteUpdateTypeDto.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,16 @@
package com.sandu.ximon.admin.dto;
import lombok.Data;
/**
 * @author ZZQ
 * @date 2022/4/12 11:38
 */
@Data
public class RemoteUpdateTypeDto {
    private String fileTypeName;
    private String val;
}
ximon-admin/src/main/java/com/sandu/ximon/admin/manager/iot/frame/inner/report/RemoteFinishUpdateReportInnerFrame.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,46 @@
package com.sandu.ximon.admin.manager.iot.frame.inner.report;
import com.sandu.common.execption.BusinessException;
import com.sandu.ximon.admin.manager.iot.frame.inner.BaseResponseInnerFrame;
import com.sandu.ximon.admin.manager.iot.rrpc.util.CRC32Utils;
import lombok.Data;
/**
 * æœåŠ¡å™¨ä¸‹å‘ç»“æŸå‡çº§å¸§
 *
 * @author ZZQ
 * @date 2022/5/7 13:47
 */
@Data
public class RemoteFinishUpdateReportInnerFrame extends BaseResponseInnerFrame<RemoteFinishUpdateReportInnerFrame> {
    //校验状态
    private boolean responseState;
    @Override
    public RemoteFinishUpdateReportInnerFrame transformFrame(String hex) {
        //FE B4 0001 01 DD480706
        if (hex.length() != 18) {
            throw new BusinessException("响应帧出错,请重新发送指令!");
        }
        // MQTT通信方式(1)
        setConnectType(hex.substring(0, 2));
        //  åŠŸèƒ½ç (1)
        setFunctionCode(hex.substring(2, 4));
        //  è´Ÿè·é•¿åº¦(2)
        setPayloadLength(hex.substring(4, 8));
        //校验状态
        if ("01".equals(hex.substring(8, 10))) {
            setResponseState(true);
        } else {
            setResponseState(false);
        }
        setCrc32(hex.substring(hex.length() - 8));
        //  æ ¡éªŒCRC32
        String frame = hex.substring(2, hex.length() - 8);
        this.setValidate(CRC32Utils.validateFrame(frame, getCrc32()));
        return this;
    }
}
ximon-admin/src/main/java/com/sandu/ximon/admin/manager/iot/frame/inner/report/RemoteSearchLoseDataReportInnerFrame.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,94 @@
package com.sandu.ximon.admin.manager.iot.frame.inner.report;
import com.sandu.common.execption.BusinessException;
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 java.util.ArrayList;
import java.util.List;
/**
 * æœåŠ¡å™¨ä¸‹å‘æŸ¥è¯¢æ¼åŒ…å¸§
 *
 * @author ZZQ
 * @date 2022/5/7 10:38
 */
@Data
public class RemoteSearchLoseDataReportInnerFrame extends BaseResponseInnerFrame<RemoteSearchLoseDataReportInnerFrame> {
    //FE
    //B3
    //003F
    //001E
    //00
    //0035    0036    0037    0038    0039    003A    003B
    //003C    003D    003E    003F    0040    0041    0042
    //0043    0044    0045    0046    0047    0048    0049
    //004A    004B    004C    004D    004E    004F    0050
    //0051    0052
    //36E57602
    //漏包总帧数
    private int loseCount;
    //校验状态
    private boolean checkState;
    private List<Integer> list;
    @Override
    public RemoteSearchLoseDataReportInnerFrame transformFrame(String hex) {
        if (hex.length() < 16) {
            throw new BusinessException("响应帧出错,请重新发送指令!");
        }
        // MQTT通信方式(1)
        setConnectType(hex.substring(0, 2));
        //  åŠŸèƒ½ç (1)
        setFunctionCode(hex.substring(2, 4));
        //  è´Ÿè·é•¿åº¦(2)
        setPayloadLength(hex.substring(4, 8));
        //漏包总帧数
        setLoseCount(parseVal(hex, 8, 12));
        //校验状态
        if ("01".equals(hex.substring(12, 14))) {
            setCheckState(true);
        } else {
            setCheckState(false);
        }
        //丢帧卷序号
        LoseFrameData loseFrameData = new LoseFrameData();
        loseFrameData.transformFrame(hex.substring(14, hex.length() - 8));
        //保存丢帧数据卷号
        setList(loseFrameData.getList());
        setCrc32(hex.substring(hex.length() - 8));
        //  æ ¡éªŒCRC32
        String frame = hex.substring(2, hex.length() - 8);
        this.setValidate(CRC32Utils.validateFrame(frame, getCrc32()));
        return this;
    }
    private Integer parseVal(String frame, int start, int end) {
        return Integer.parseInt(frame.substring(start, end), 16);
    }
    @Data
    public static class LoseFrameData implements IResponseInnerFrame<LoseFrameData> {
        private List<Integer> list = new ArrayList<>();
        @Override
        public LoseFrameData transformFrame(String hex) {
            for (int i = 0; i < hex.length() / 4; i++) {
                list.add(parseVal(hex, i * 4, i * 4 + 4));
            }
            return this;
        }
        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/frame/inner/report/RemoteSearchUpdateResultReportInnerFrame.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,47 @@
package com.sandu.ximon.admin.manager.iot.frame.inner.report;
import com.sandu.common.execption.BusinessException;
import com.sandu.ximon.admin.manager.iot.frame.inner.BaseResponseInnerFrame;
import com.sandu.ximon.admin.manager.iot.rrpc.util.CRC32Utils;
import lombok.Data;
/**
 * @author ZZQ
 * @date 2022/5/7 14:43
 */
@Data
public class RemoteSearchUpdateResultReportInnerFrame extends BaseResponseInnerFrame<RemoteSearchUpdateResultReportInnerFrame> {
    //硬件版本
    private String hardwareVersion;
    //软件版本
    private String softwareVersion;
    @Override
    public RemoteSearchUpdateResultReportInnerFrame transformFrame(String hex) {
        if (hex.length() < 16) {
            throw new BusinessException("响应帧出错,请重新发送指令!");
        }
        // MQTT通信方式(1)
        setConnectType(hex.substring(0, 2));
        //  åŠŸèƒ½ç (1)
        setFunctionCode(hex.substring(2, 4));
        //  è´Ÿè·é•¿åº¦(2)
        setPayloadLength(hex.substring(4, 8));
        //硬件版本
        setHardwareVersion(parseVal(hex, 8, 10) + "." + parseVal(hex, 10, 12));
        //软件版本
        setSoftwareVersion(parseVal(hex, 12, 14) + "." + parseVal(hex, 14, 16));
        setCrc32(hex.substring(hex.length() - 8));
        //  æ ¡éªŒCRC32
        String frame = hex.substring(2, hex.length() - 8);
        this.setValidate(CRC32Utils.validateFrame(frame, getCrc32()));
        return this;
    }
    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/frame/inner/report/RemoteStartUpdateReportInnerFrame.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,63 @@
package com.sandu.ximon.admin.manager.iot.frame.inner.report;
import com.sandu.common.execption.BusinessException;
import com.sandu.ximon.admin.manager.iot.frame.inner.BaseResponseInnerFrame;
import com.sandu.ximon.admin.manager.iot.rrpc.util.CRC32Utils;
import lombok.Data;
import lombok.ToString;
/**
 * å¯åŠ¨è¿œç¨‹å‡çº§å‘½ä»¤å“åº”å†…å¸§
 *
 * @author ZZQ
 * @date 2022/5/6 14:13
 */
@Data
@ToString(callSuper = true)
public class RemoteStartUpdateReportInnerFrame extends BaseResponseInnerFrame<RemoteStartUpdateReportInnerFrame> {
    //硬件版本
    private String hardwareVersion;
    //软件版本
    private String softwareVersion;
    //厂家标志
    private String factoryFlag;
    //指令标志
    private String orderFlag;
    //升级标志
    private String updateFlag;
    //FE  B0  0007  0108  0109  786D  01  90431921
    @Override
    public RemoteStartUpdateReportInnerFrame transformFrame(String hex) {
        if (hex.length() != 30) {
            throw new BusinessException("响应帧出错,请重新发送指令!");
        }
        // MQTT通信方式(1)
        setConnectType(hex.substring(0, 2));
        //  åŠŸèƒ½ç (1)
        setFunctionCode(hex.substring(2, 4));
        //  è´Ÿè·é•¿åº¦(2)
        setPayloadLength(hex.substring(4, 8));
        //硬件版本
        setHardwareVersion(parseVal(hex, 8, 10) + "." + parseVal(hex, 10, 12));
        //软件版本
        setSoftwareVersion(parseVal(hex, 12, 14) + "." + parseVal(hex, 14, 16));
        //厂家标志
        setFactoryFlag(hex.substring(16, 20));
        //指令标志
        setOrderFlag(hex.substring(20, 21));
        //升级标志
        setUpdateFlag(hex.substring(21, 22));
        setCrc32(hex.substring(hex.length() - 8));
        //  æ ¡éªŒCRC32
        String frame = hex.substring(2, hex.length() - 8);
        this.setValidate(CRC32Utils.validateFrame(frame, getCrc32()));
        return this;
    }
    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/frame/inner/report/RemoteStopUpdateReportInnerFrame.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,40 @@
package com.sandu.ximon.admin.manager.iot.frame.inner.report;
import com.sandu.common.execption.BusinessException;
import com.sandu.ximon.admin.manager.iot.frame.inner.BaseResponseInnerFrame;
import com.sandu.ximon.admin.manager.iot.rrpc.util.CRC32Utils;
import lombok.Data;
/**
 * @author ZZQ
 * @date 2022/5/7 15:16
 */
@Data
public class RemoteStopUpdateReportInnerFrame extends BaseResponseInnerFrame<RemoteStopUpdateReportInnerFrame> {
    private boolean responseState;
    @Override
    public RemoteStopUpdateReportInnerFrame transformFrame(String hex) {
        if (hex.length() != 18) {
            throw new BusinessException("响应帧出错,请重新发送指令!");
        }
        // MQTT通信方式(1)
        setConnectType(hex.substring(0, 2));
        //  åŠŸèƒ½ç (1)
        setFunctionCode(hex.substring(2, 4));
        //  è´Ÿè·é•¿åº¦(2)
        setPayloadLength(hex.substring(4, 8));
        //校验状态
        if ("01".equals(hex.substring(8, 10))) {
            setResponseState(true);
        } else {
            setResponseState(false);
        }
        setCrc32(hex.substring(hex.length() - 8));
        //  æ ¡éªŒCRC32
        String frame = hex.substring(2, hex.length() - 8);
        this.setValidate(CRC32Utils.validateFrame(frame, getCrc32()));
        return this;
    }
}
ximon-admin/src/main/java/com/sandu/ximon/admin/manager/iot/frame/inner/report/RemoteUpdateFileInfoReportInnerFrame.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,46 @@
package com.sandu.ximon.admin.manager.iot.frame.inner.report;
import com.sandu.common.execption.BusinessException;
import com.sandu.ximon.admin.manager.iot.frame.inner.BaseResponseInnerFrame;
import com.sandu.ximon.admin.manager.iot.rrpc.util.CRC32Utils;
import lombok.Data;
import lombok.ToString;
/**
 * æœåŠ¡å™¨ä¸‹å‘å‡çº§æ–‡ä»¶ä¿¡æ¯
 *
 * @author ZZQ
 * @date 2022/5/6 15:08
 */
@Data
@ToString(callSuper = true)
public class RemoteUpdateFileInfoReportInnerFrame extends BaseResponseInnerFrame<RemoteUpdateFileInfoReportInnerFrame> {
    //确认标识  0x00:确实失败  0x01:确认ok
    private boolean flag;
    @Override
    public RemoteUpdateFileInfoReportInnerFrame transformFrame(String hex) {
        if (hex.length() != 18) {
            throw new BusinessException("响应帧出错,请重新发送指令!");
        }
        //FE  B1  0001  01  EA96F734
        // MQTT通信方式(1)
        setConnectType(hex.substring(0, 2));
        //  åŠŸèƒ½ç (1)
        setFunctionCode(hex.substring(2, 4));
        //  è´Ÿè·é•¿åº¦(2)
        setPayloadLength(hex.substring(4, 8));
        //确认标识
        if ("01".equals(hex.substring(8, 10))) {
            setFlag(true);
        } else {
            setFlag(false);
        }
        setCrc32(hex.substring(hex.length() - 8));
        //  æ ¡éªŒCRC32
        String frame = hex.substring(2, hex.length() - 8);
        this.setValidate(CRC32Utils.validateFrame(frame, getCrc32()));
        return this;
    }
}
ximon-admin/src/main/java/com/sandu/ximon/admin/manager/iot/frame/inner/request/A5LightBrightnessReqInnerFrame.java
@@ -34,7 +34,7 @@
        } else if (lightLevel > 100) {
            lightLevel = 100;
        }
        payload = destinationAddress + SupplementUtils.suppleZero(Integer.toHexString(lightLevel), 2);
        payload = destinationAddress + SupplementUtils.suppleZero(Integer.toHexString(lightLevel).toUpperCase(), 2);
    }
    @Override
ximon-admin/src/main/java/com/sandu/ximon/admin/manager/iot/frame/inner/request/C3QrCodeReqInnerFrame.java
@@ -4,6 +4,7 @@
import com.sandu.ximon.admin.manager.iot.rrpc.enums.C3ChargingEnum;
import com.sandu.ximon.admin.manager.iot.rrpc.enums.MQTTConnectTypeEnum;
import com.sandu.ximon.admin.manager.iot.rrpc.util.CRC32Utils;
import com.sandu.ximon.admin.manager.iot.rrpc.util.SupplementUtils;
/**
 * @author ZZQ
@@ -21,7 +22,7 @@
    public String getEncodeFrame() {
        String functionCode = C3ChargingEnum.QR_CODE_REQUEST.getCode();
        //长度可变,不定长
        String payloadLength = payload.length() + "";
        String payloadLength = SupplementUtils.suppleZero(Integer.toHexString((payload.length() / 2)).toUpperCase(), 4);
        String frame = functionCode + payloadLength + payload;
        return MQTTConnectTypeEnum.SYNCHRONIZATION.getCode() + frame.toUpperCase() + CRC32Utils.getCRC32(frame.toUpperCase());
    }
ximon-admin/src/main/java/com/sandu/ximon/admin/manager/iot/frame/inner/request/RemoteFinishUpdateReqInnerFrame.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,24 @@
package com.sandu.ximon.admin.manager.iot.frame.inner.request;
import com.sandu.ximon.admin.manager.iot.frame.inner.IRequestInnerFrame;
import com.sandu.ximon.admin.manager.iot.rrpc.enums.MQTTConnectTypeEnum;
import com.sandu.ximon.admin.manager.iot.rrpc.enums.RemoteUpdateEnum;
import com.sandu.ximon.admin.manager.iot.rrpc.util.CRC32Utils;
/**
 * æœåŠ¡å™¨ä¸‹å‘ç»“æŸå‡çº§å¸§
 *
 * @author ZZQ
 * @date 2022/5/5 14:03
 */
public class RemoteFinishUpdateReqInnerFrame implements IRequestInnerFrame {
    @Override
    public String getEncodeFrame() {
        String functionCode = RemoteUpdateEnum.FinishUpdate.getCode();
        String payloadLength = "0000";
        String frame = functionCode + payloadLength;
        return MQTTConnectTypeEnum.SYNCHRONIZATION.getCode() + frame.toUpperCase() + CRC32Utils.getCRC32(frame.toUpperCase());
    }
}
ximon-admin/src/main/java/com/sandu/ximon/admin/manager/iot/frame/inner/request/RemoteSearchLoseDataReqInnerFrame.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,24 @@
package com.sandu.ximon.admin.manager.iot.frame.inner.request;
import com.sandu.ximon.admin.manager.iot.frame.inner.IRequestInnerFrame;
import com.sandu.ximon.admin.manager.iot.rrpc.enums.MQTTConnectTypeEnum;
import com.sandu.ximon.admin.manager.iot.rrpc.enums.RemoteUpdateEnum;
import com.sandu.ximon.admin.manager.iot.rrpc.util.CRC32Utils;
/**
 * æœåŠ¡å™¨ä¸‹å‘æŸ¥è¯¢æ¼åŒ…å¸§
 *
 * @author ZZQ
 * @date 2022/5/5 14:03
 */
public class RemoteSearchLoseDataReqInnerFrame implements IRequestInnerFrame {
    @Override
    public String getEncodeFrame() {
        String functionCode = RemoteUpdateEnum.SearchLoseData.getCode();
        String payloadLength = "0000";
        String frame = functionCode + payloadLength;
        return MQTTConnectTypeEnum.SYNCHRONIZATION.getCode() + frame.toUpperCase() + CRC32Utils.getCRC32(frame.toUpperCase());
    }
}
ximon-admin/src/main/java/com/sandu/ximon/admin/manager/iot/frame/inner/request/RemoteSearchUpdateResultReqInnerFrame.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,25 @@
package com.sandu.ximon.admin.manager.iot.frame.inner.request;
import com.sandu.ximon.admin.manager.iot.frame.inner.IRequestInnerFrame;
import com.sandu.ximon.admin.manager.iot.rrpc.enums.MQTTConnectTypeEnum;
import com.sandu.ximon.admin.manager.iot.rrpc.enums.RemoteUpdateEnum;
import com.sandu.ximon.admin.manager.iot.rrpc.util.CRC32Utils;
/**
 * æœåŠ¡å™¨ä¸‹å‘å‡çº§ç»“æžœæŸ¥è¯¢
 *
 * @author ZZQ
 * @date 2022/5/5 14:03
 */
public class RemoteSearchUpdateResultReqInnerFrame implements IRequestInnerFrame {
    @Override
    public String getEncodeFrame() {
        String functionCode = RemoteUpdateEnum.SearchUpdateResult.getCode();
        String payloadLength = "0004";
        String payload = "00000000";
        String frame = functionCode + payloadLength + payload;
        return MQTTConnectTypeEnum.SYNCHRONIZATION.getCode() + frame.toUpperCase() + CRC32Utils.getCRC32(frame.toUpperCase());
    }
}
ximon-admin/src/main/java/com/sandu/ximon/admin/manager/iot/frame/inner/request/RemoteSendFileReqInnerFrame.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,38 @@
package com.sandu.ximon.admin.manager.iot.frame.inner.request;
import com.sandu.ximon.admin.manager.iot.frame.inner.IRequestInnerFrame;
import com.sandu.ximon.admin.manager.iot.rrpc.enums.MQTTConnectTypeEnum;
import com.sandu.ximon.admin.manager.iot.rrpc.enums.RemoteUpdateEnum;
import com.sandu.ximon.admin.manager.iot.rrpc.util.CRC32Utils;
import com.sandu.ximon.admin.manager.iot.rrpc.util.SupplementUtils;
/**
 * @author ZZQ
 * @date 2022/5/5 11:28
 */
public class RemoteSendFileReqInnerFrame implements IRequestInnerFrame {
    private String payload;
    /**
     * @param fileTotalSize  å‡çº§æ–‡ä»¶æ€»å¤§å°
     * @param frameTotalSize æ€»å¸§æ•°
     * @param frameSize      å•帧数据
     */
    public RemoteSendFileReqInnerFrame(int fileTotalSize, int frameTotalSize, int frameSize, String fileHexStr) {
        payload = SupplementUtils.suppleZero(Integer.toHexString(fileTotalSize).toUpperCase(), 8)
                + SupplementUtils.suppleZero(Integer.toHexString(frameTotalSize).toUpperCase(), 4)
                + SupplementUtils.suppleZero(Integer.toHexString(frameSize).toUpperCase(), 4) +
                CRC32Utils.getCRC32(fileHexStr.toUpperCase());
    }
    @Override
    public String getEncodeFrame() {
        String functionCode = RemoteUpdateEnum.UpdateFileInfo.getCode();
        String payloadLength = SupplementUtils.suppleZero(Integer.toHexString((payload.length() / 2)).toUpperCase(), 4);
        String frame = functionCode + payloadLength + payload;
        return MQTTConnectTypeEnum.SYNCHRONIZATION.getCode() + frame.toUpperCase() + CRC32Utils.getCRC32(frame.toUpperCase());
    }
}
ximon-admin/src/main/java/com/sandu/ximon/admin/manager/iot/frame/inner/request/RemoteStartUpdateReqInnerFrame.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,51 @@
package com.sandu.ximon.admin.manager.iot.frame.inner.request;
import com.sandu.ximon.admin.manager.iot.frame.inner.IRequestInnerFrame;
import com.sandu.ximon.admin.manager.iot.rrpc.enums.MQTTConnectTypeEnum;
import com.sandu.ximon.admin.manager.iot.rrpc.enums.RemoteUpdateEnum;
import com.sandu.ximon.admin.manager.iot.rrpc.util.CRC32Utils;
import com.sandu.ximon.admin.manager.iot.rrpc.util.SupplementUtils;
import java.math.BigDecimal;
/**
 * å¯åŠ¨è¿œç¨‹å‡çº§
 *
 * @author ZZQ
 * @date 2022/5/5 10:55
 */
public class RemoteStartUpdateReqInnerFrame implements IRequestInnerFrame {
    //厂家标志(待定)
    private String factoryFlag = "0001";
    private String payload;
    /**
     * @param hardwareVersion ç¡¬ä»¶æœ¬ç‰ˆ
     * @param softwareVersion è½¯ä»¶ç‰ˆæœ¬
     * @param updateFlag      å‡çº§æ ‡å¿—
     */
    public RemoteStartUpdateReqInnerFrame(String hardwareVersion, String softwareVersion, String updateFlag) {
        String[] split = new BigDecimal(hardwareVersion).setScale(2, BigDecimal.ROUND_DOWN).toString().split("\\.");
        hardwareVersion = SupplementUtils.suppleZero(Integer.toHexString(Integer.valueOf(split[0])).toUpperCase(), 2)
                + SupplementUtils.suppleZero(Integer.toHexString(Integer.valueOf(split[1])).toUpperCase(), 2);
        String[] split1 = new BigDecimal(softwareVersion).setScale(2, BigDecimal.ROUND_DOWN).toString().split("\\.");
        softwareVersion = SupplementUtils.suppleZero(Integer.toHexString(Integer.valueOf(split1[0])).toUpperCase(), 2)
                + SupplementUtils.suppleZero(Integer.toHexString(Integer.valueOf(split1[1])).toUpperCase(), 2);
        payload = hardwareVersion + softwareVersion + factoryFlag + updateFlag;
    }
    @Override
    public String getEncodeFrame() {
        String functionCode = RemoteUpdateEnum.StartRemoteUpdate.getCode();
        //计算长度
        String payloadLength = SupplementUtils.suppleZero(Integer.toHexString((payload.length() / 2)).toUpperCase(), 4);
        String frame = functionCode + payloadLength + payload;
        return MQTTConnectTypeEnum.SYNCHRONIZATION.getCode() + frame.toUpperCase() + CRC32Utils.getCRC32(frame.toUpperCase());
    }
}
ximon-admin/src/main/java/com/sandu/ximon/admin/manager/iot/frame/inner/request/RemoteStopUpdateReqInnerFrame.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,24 @@
package com.sandu.ximon.admin.manager.iot.frame.inner.request;
import com.sandu.ximon.admin.manager.iot.frame.inner.IRequestInnerFrame;
import com.sandu.ximon.admin.manager.iot.rrpc.enums.MQTTConnectTypeEnum;
import com.sandu.ximon.admin.manager.iot.rrpc.enums.RemoteUpdateEnum;
import com.sandu.ximon.admin.manager.iot.rrpc.util.CRC32Utils;
/**
 * æœåŠ¡å™¨ä¸‹å‘ç´§æ€¥ä¸­æ–­å‡çº§æŽ§åˆ¶å¸§
 *
 * @author ZZQ
 * @date 2022/5/5 14:03
 */
public class RemoteStopUpdateReqInnerFrame implements IRequestInnerFrame {
    @Override
    public String getEncodeFrame() {
        String functionCode = RemoteUpdateEnum.StopUpdate.getCode();
        String payloadLength = "0000";
        String frame = functionCode + payloadLength;
        return MQTTConnectTypeEnum.SYNCHRONIZATION.getCode() + frame.toUpperCase() + CRC32Utils.getCRC32(frame.toUpperCase());
    }
}
ximon-admin/src/main/java/com/sandu/ximon/admin/manager/iot/frame/inner/request/RemoteUpdateDataReqInnerFrame.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,35 @@
package com.sandu.ximon.admin.manager.iot.frame.inner.request;
import com.sandu.ximon.admin.manager.iot.frame.inner.IRequestInnerFrame;
import com.sandu.ximon.admin.manager.iot.rrpc.enums.MQTTConnectTypeEnum;
import com.sandu.ximon.admin.manager.iot.rrpc.enums.RemoteUpdateEnum;
import com.sandu.ximon.admin.manager.iot.rrpc.util.CRC32Utils;
import com.sandu.ximon.admin.manager.iot.rrpc.util.SupplementUtils;
/**
 * å‡çº§åŒ…数据
 *
 * @author ZZQ
 * @date 2022/5/5 13:58
 */
public class RemoteUpdateDataReqInnerFrame implements IRequestInnerFrame {
    private String payload;
    /**
     * @param volumeOrder å·åº
     * @param datas       å‡çº§åŒ…分卷数据
     */
    public RemoteUpdateDataReqInnerFrame(int volumeOrder, String datas) {
        payload = SupplementUtils.suppleZero(Integer.toHexString(volumeOrder).toUpperCase(), 4) + datas;
    }
    @Override
    public String getEncodeFrame() {
        String functionCode = RemoteUpdateEnum.UpdateData.getCode();
        String payloadLength = SupplementUtils.suppleZero(Integer.toHexString((payload.length() / 2)).toUpperCase(), 4);
        String frame = functionCode + payloadLength + payload;
        return MQTTConnectTypeEnum.SYNCHRONIZATION.getCode() + frame.toUpperCase() + CRC32Utils.getCRC32(frame.toUpperCase());
    }
}
ximon-admin/src/main/java/com/sandu/ximon/admin/manager/iot/rrpc/enums/RemoteUpdateEnum.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,34 @@
package com.sandu.ximon.admin.manager.iot.rrpc.enums;
/**
 * è¿œç¨‹å‡çº§å¸§-功能码
 *
 * @author ZZQ
 * @date 2022/4/11 14:48
 */
public enum RemoteUpdateEnum {
    //  å¯åŠ¨è¿œç¨‹å‡çº§å‘½ä»¤
    StartRemoteUpdate("B0"),
    //  æœåŠ¡å™¨ä¸‹å‘å‡çº§æ–‡ä»¶ä¿¡æ¯
    UpdateFileInfo("B1"),
    //  å‡çº§åŒ…数据
    UpdateData("B2"),
    //  æŸ¥è¯¢æ¼åŒ…帧
    SearchLoseData("B3"),
    //  ç»“束升级帧
    FinishUpdate("B4"),
    //  å‡çº§ç»“果查询
    SearchUpdateResult("B5"),
    //  ä¸­æ–­å‡çº§æŽ§åˆ¶å¸§
    StopUpdate("B6");
    private String code;
    RemoteUpdateEnum(String code) {
        this.code = code;
    }
    public String getCode() {
        return code;
    }
}
ximon-admin/src/main/java/com/sandu/ximon/admin/manager/iot/rrpc/enums/RemoteUpdateTypeEnum.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,55 @@
package com.sandu.ximon.admin.manager.iot.rrpc.enums;
import com.sandu.ximon.admin.dto.RemoteUpdateTypeDto;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
/**
 * @author ZZQ
 * @date 2022/4/12 11:39
 */
public enum RemoteUpdateTypeEnum {
    //  MQTT主板
    MQTT_MAIN("0"),
    //  MQTT核心板
    MQTT_CORE("1"),
    //  å•灯模块
    LIGHT("2"),
    //  C3充电桩模块
    C3_CHARGING("3");
    private String code;
    public String getCode() {
        return code;
    }
    RemoteUpdateTypeEnum(String code) {
        this.code = code;
    }
    public static List<RemoteUpdateTypeDto> getAllType() {
        List<RemoteUpdateTypeDto> list = new ArrayList<>();
        for (RemoteUpdateTypeEnum r : RemoteUpdateTypeEnum.values()) {
            RemoteUpdateTypeDto remoteUpdateTypeEntity = new RemoteUpdateTypeDto();
            remoteUpdateTypeEntity.setVal(r.getCode());
            remoteUpdateTypeEntity.setFileTypeName(map.get(r.getCode()));
            list.add(remoteUpdateTypeEntity);
        }
        return list;
    }
    private static ConcurrentHashMap<String, String> map = new ConcurrentHashMap<String, String>() {
        {
            put("0", "MQTT核心板");
            put("1", "Cat.1主板");
            put("2", "C3充电桩模块");
            put("3", "大气设备模块");
            put("4", "杆体倾斜模块");
        }
    };
}
ximon-admin/src/main/java/com/sandu/ximon/admin/manager/iot/rrpc/util/FileProcessingUtils.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,61 @@
package com.sandu.ximon.admin.manager.iot.rrpc.util;
import com.sandu.ximon.admin.dto.RemoteFileDto;
import com.sandu.ximon.admin.utils.HexUtils;
import org.apache.catalina.LifecycleState;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
 * @author ZZQ
 * @date 2022/5/5 14:26
 */
public class FileProcessingUtils {
//    public static void main(String[] args) {
//        try {
//            RemoteFileDto remoteFileDto = read("C:\\Users\\Administrator\\Desktop\\test\\H01_v3.0.12.min.dhcp.bin");
//            System.out.println(remoteFileDto.getListSize());
//            System.out.println(remoteFileDto.getList().size());
//            System.out.println(Arrays.toString(remoteFileDto.getList().get(0)));
//        } catch (IOException e) {
//            e.printStackTrace();
//        }
//    }
    public static RemoteFileDto read(String filePath) throws IOException {
        List<String> data = new ArrayList<>();
        int dataSize = 0;
        StringBuffer fileHexStr=new StringBuffer();
        File file = new File(filePath);
        InputStream in = new FileInputStream(file);
        // ä¸€æ¬¡æ€§å–多少个字节
        byte[] bytes = new byte[512];
        // è¯»å–到的字节数组长度,为-1时表示没有数据
        int length = 0;
        // å¾ªçŽ¯å–æ•°æ®
        while ((length = in.read(bytes)) != -1) {
            String temp=HexUtils.encodeHexStr(Arrays.copyOf(bytes, length));
            data.add(temp);
            fileHexStr.append(temp);
            dataSize += length;
        }
        in.close();
        RemoteFileDto remoteFileDto = new RemoteFileDto();
        remoteFileDto.setList(data);
        remoteFileDto.setListSize(dataSize);
        remoteFileDto.setFileHexStr(fileHexStr.toString());
        return remoteFileDto;
    }
}
ximon-admin/src/main/java/com/sandu/ximon/admin/param/RemotePrarm.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,54 @@
package com.sandu.ximon.admin.param;
import lombok.Data;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import java.math.BigDecimal;
/**
 * å›ºä»¶å‡çº§
 *
 * @author ZZQ
 * @date 2022/5/7 9:40
 */
@Data
public class RemotePrarm {
    /**
     * è®¾å¤‡MAC地址
     */
    @NotEmpty
    private String mac;
    /**
     * è®¾å¤‡ç±»åž‹ï¼Œå•灯/大气/C3充电桩/杆体倾斜
     */
    @NotEmpty
    private String deviceType;
    /**
     * ç¡¬ä»¶ç‰ˆæœ¬
     */
    @NotEmpty
    private String hardwareVersion;
    /**
     * è½¯ä»¶ç‰ˆæœ¬
     */
    @NotEmpty
    private String softwareVersion;
    /**
     * å‡çº§æ ‡å¿—
     */
    @NotEmpty
    private String updateFlag;
    /**
     * æ–‡ä»¶åœ°å€
     */
    @NotEmpty
    private String aliAddress;
}
ximon-admin/src/main/java/com/sandu/ximon/admin/param/RemoteUpdateParam.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,50 @@
package com.sandu.ximon.admin.param;
import lombok.Data;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import java.math.BigDecimal;
/**
 * @author ZZQ
 * @date 2022/4/12 11:07
 */
@Data
public class RemoteUpdateParam {
    /**
     * å‡çº§æ–‡ä»¶å
     */
    @NotEmpty
    private String filename;
    /**
     * è½¯ä»¶ç‰ˆæœ¬
     */
    @NotEmpty
    private String softwareVersion;
    /**
     * ç¡¬ä»¶ç‰ˆæœ¬
     */
    @NotEmpty
    private String hardwareVersion;
    /**
     * é˜¿é‡Œæ–‡ä»¶å­˜å‚¨åœ°å€
     */
    @NotEmpty
    private String aliAddress;
    /**
     * æ–‡ä»¶ç±»åž‹
     */
    @NotEmpty
    private String fileType;
    /**
     * æ–‡ä»¶é•¿åº¦
     */
    private String fileLength;
}
ximon-admin/src/main/java/com/sandu/ximon/admin/service/RemoteUpdateService.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,236 @@
package com.sandu.ximon.admin.service;
import com.sandu.common.execption.BusinessException;
import com.sandu.common.service.impl.BaseServiceImpl;
import com.sandu.ximon.admin.dto.RemoteFileDto;
import com.sandu.ximon.admin.dto.RemoteUpdateTypeDto;
import com.sandu.ximon.admin.manager.iot.frame.A5Frame;
import com.sandu.ximon.admin.manager.iot.frame.inner.report.*;
import com.sandu.ximon.admin.manager.iot.frame.inner.request.*;
import com.sandu.ximon.admin.manager.iot.rrpc.dto.CommonFrame;
import com.sandu.ximon.admin.manager.iot.rrpc.enums.RemoteUpdateTypeEnum;
import com.sandu.ximon.admin.manager.iot.rrpc.mainboard.MainBoardInvokeSyncService;
import com.sandu.ximon.admin.manager.iot.rrpc.util.FileProcessingUtils;
import com.sandu.ximon.dao.domain.RemoteUpdateFile;
import com.sandu.ximon.dao.mapper.RemoteUpdateFileMapper;
import org.springframework.stereotype.Service;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.List;
/**
 * @author ZZQ
 * @date 2022/4/12 11:09
 */
@Service
public class RemoteUpdateService extends BaseServiceImpl<RemoteUpdateFileMapper, RemoteUpdateFile> {
    /**
     * æ·»åŠ æ–‡ä»¶æ›´æ–°å†…å®¹
     *
     * @param filename
     * @param fileType
     * @param softwareVersion
     * @param hardwareVersion
     * @param aliAddress
     */
    public boolean addRemoteUpdateFile(String filename, String fileType, String softwareVersion
            , String hardwareVersion, String aliAddress, String fileLength) {
        RemoteUpdateFile remoteUpdateFile = new RemoteUpdateFile();
        remoteUpdateFile.setAliAddress(aliAddress);
        remoteUpdateFile.setFileType(fileType);
        remoteUpdateFile.setSoftwareVersion(new BigDecimal(softwareVersion).setScale(2, BigDecimal.ROUND_DOWN));
        remoteUpdateFile.setHardwareVersion(new BigDecimal(hardwareVersion).setScale(2, BigDecimal.ROUND_DOWN));
        remoteUpdateFile.setFilename(filename);
        remoteUpdateFile.setFileLength(fileLength);
        return save(remoteUpdateFile);
    }
    /**
     * å›ºä»¶å‡çº§æ–‡ä»¶
     *
     * @return
     */
    public List<RemoteUpdateFile> getRemoteFileList() {
        return list();
    }
    /**
     * è¿œç¨‹å‡çº§ç±»åž‹
     */
    public List<RemoteUpdateTypeDto> getRemoteUpdateTypeList() {
        return RemoteUpdateTypeEnum.getAllType();
    }
    /**
     * å¯åŠ¨è¿œç¨‹å‡çº§å‘½ä»¤
     *
     * @param mac             è®¾å¤‡MAC地址
     * @param hardwareVersion ç¡¬ä»¶ç‰ˆæœ¬
     * @param softwareVersion è½¯ä»¶ç‰ˆæœ¬
     * @param updateFlag      å‡çº§æ ‡å¿—
     */
    public boolean StartRemoteUpdate(String orderType, String mac, String hardwareVersion, String softwareVersion, String updateFlag) {
        RemoteStartUpdateReqInnerFrame remoteStartUpdateReqInnerFrame = new RemoteStartUpdateReqInnerFrame(hardwareVersion, softwareVersion, updateFlag);
        A5Frame a5Frame = new A5Frame(orderType, remoteStartUpdateReqInnerFrame);
        System.out.println(a5Frame + "      a5Frame");
        CommonFrame commonFrame = MainBoardInvokeSyncService.getInstance().sendRRPC(mac, a5Frame);
        System.out.println(commonFrame + "            -----commonFrame");
        RemoteStartUpdateReportInnerFrame remoteStartUpdateReportInnerFrame
                = new RemoteStartUpdateReportInnerFrame().transformFrame(commonFrame.getPayload());
        boolean flag;
        if (remoteStartUpdateReportInnerFrame.isValidate()) {
            switch (remoteStartUpdateReportInnerFrame.getOrderFlag()) {
                case "0":
                    if ("1".equals(remoteStartUpdateReportInnerFrame.getUpdateFlag())) {
                        System.out.println("开始升级相关步骤");
                        //服务器下发升级文件信息
                        flag = true;
                    } else {
                        System.out.println("不进行升级");
                        flag = false;
                    }
                    break;
                case "1":
                    System.out.println("终端不在空闲状态");
                    flag = false;
                    break;
                case "8":
                    System.out.println("指令有误");
                    flag = false;
                    break;
                default:
                    flag = false;
            }
        } else {
            throw new BusinessException("数据校验错误,请重新请求");
        }
        return flag;
    }
    /**
     * æœåŠ¡å™¨ä¸‹å‘å‡çº§æ–‡ä»¶ä¿¡æ¯
     *
     * @param filePath æ–‡ä»¶è·¯å¾„地址
     */
    public RemoteFileDto UpdateFileInfo(String orderType, String mac, String filePath) {
        try {
            RemoteFileDto remoteFileDto = FileProcessingUtils.read(filePath);
            RemoteSendFileReqInnerFrame remoteSendFileReqInnerFrame
                    = new RemoteSendFileReqInnerFrame(remoteFileDto.getListSize(), remoteFileDto.getList().size(), 512, remoteFileDto.getFileHexStr());
            A5Frame a5Frame = new A5Frame(orderType, remoteSendFileReqInnerFrame);
            System.out.println(a5Frame + "      a5Frame");
            CommonFrame commonFrame = MainBoardInvokeSyncService.getInstance().sendRRPC(mac, a5Frame);
            System.out.println(commonFrame + "            -----commonFrame");
            RemoteUpdateFileInfoReportInnerFrame remoteUpdateFileInfoReportInnerFrame
                    = new RemoteUpdateFileInfoReportInnerFrame().transformFrame(commonFrame.getPayload());
            //确认OK
            if (remoteUpdateFileInfoReportInnerFrame != null && remoteUpdateFileInfoReportInnerFrame.isFlag()) {
                return remoteFileDto;
            } else {
                return null;
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }
    /**
     * å‡çº§åŒ…数据
     *
     * @param volumeOrder å·åº
     * @param datas       å‡çº§åŒ…分卷数据
     */
    public void UpdateData(String orderType, String mac, int volumeOrder, String datas) {
        RemoteUpdateDataReqInnerFrame remoteUpdateDataReqInnerFrame = new RemoteUpdateDataReqInnerFrame(volumeOrder, datas);
        A5Frame a5Frame = new A5Frame(orderType, remoteUpdateDataReqInnerFrame);
        System.out.println(a5Frame + "      a5Frame");
        CommonFrame commonFrame = null;
        try {
            commonFrame = MainBoardInvokeSyncService.getInstance().sendRRPC(mac, a5Frame);
            System.out.println(commonFrame + "            -----commonFrame");
        } catch (Exception e) {
            System.out.println("发送数据超时或失败");
        }
        //FE  B2  0004  0056  01  00  AE2C4474
    }
    /**
     * æœåŠ¡å™¨ä¸‹å‘æŸ¥è¯¢æ¼åŒ…å¸§
     */
    public boolean SearchLoseData(String orderType, String mac, RemoteFileDto remoteFileDto, int resendTime) {
        RemoteSearchLoseDataReqInnerFrame remoteSearchLoseDataReqInnerFrame = new RemoteSearchLoseDataReqInnerFrame();
        A5Frame a5Frame = new A5Frame(orderType, remoteSearchLoseDataReqInnerFrame);
        System.out.println(a5Frame + "      a5Frame");
        CommonFrame commonFrame = MainBoardInvokeSyncService.getInstance().sendRRPC(mac, a5Frame);
        System.out.println(commonFrame + "            -----commonFrame");
        RemoteSearchLoseDataReportInnerFrame remoteSearchLoseDataReportInnerFrame = new RemoteSearchLoseDataReportInnerFrame().transformFrame(commonFrame.getPayload());
        //校验不通过,有漏包
        if (!remoteSearchLoseDataReportInnerFrame.isCheckState()) {
            if (resendTime == 3) {
                throw new BusinessException("重发丢帧数据超次数,更新失败!");
            }
            for (Integer integer : remoteSearchLoseDataReportInnerFrame.getList()) {
                UpdateData(orderType, mac, integer, remoteFileDto.getList().get(integer));
            }
            SearchLoseData(orderType, mac, remoteFileDto, resendTime + 1);
        }
        return true;
    }
    /**
     * æœåŠ¡å™¨ä¸‹å‘ç»“æŸå‡çº§å¸§
     */
    public boolean FinishUpdate(String orderType, String mac) {
        RemoteFinishUpdateReqInnerFrame remoteFinishUpdateReqInnerFrame = new RemoteFinishUpdateReqInnerFrame();
        A5Frame a5Frame = new A5Frame(orderType, remoteFinishUpdateReqInnerFrame);
        System.out.println(a5Frame + "      a5Frame");
        CommonFrame commonFrame = MainBoardInvokeSyncService.getInstance().sendRRPC(mac, a5Frame);
        System.out.println(commonFrame + "            -----commonFrame");
        RemoteFinishUpdateReportInnerFrame remoteFinishUpdateReportInnerFrame = new RemoteFinishUpdateReportInnerFrame().transformFrame(commonFrame.getPayload());
        //返回升级结果
        return remoteFinishUpdateReportInnerFrame.isResponseState();
    }
    /**
     * æœåŠ¡å™¨ä¸‹å‘å‡çº§ç»“æžœæŸ¥è¯¢
     */
    public String SearchUpdateResult(String orderType, String mac) {
        RemoteSearchUpdateResultReqInnerFrame remoteSearchUpdateResultReqInnerFrame = new RemoteSearchUpdateResultReqInnerFrame();
        A5Frame a5Frame = new A5Frame(orderType, remoteSearchUpdateResultReqInnerFrame);
        System.out.println(a5Frame + "      a5Frame");
        CommonFrame commonFrame = MainBoardInvokeSyncService.getInstance().sendRRPC(mac, a5Frame);
        System.out.println(commonFrame + "            -----commonFrame");
        RemoteSearchUpdateResultReportInnerFrame innerFrame = new RemoteSearchUpdateResultReportInnerFrame().transformFrame(commonFrame.getPayload());
        String result = "硬件版本:" + innerFrame.getHardwareVersion() + "  è½¯ä»¶ä»¶ç‰ˆæœ¬ï¼š" + innerFrame.getSoftwareVersion();
        return result;
    }
    /**
     * æœåŠ¡å™¨ä¸‹å‘ç´§æ€¥ä¸­æ–­å‡çº§æŽ§åˆ¶å¸§
     */
    public boolean stopUpdate(String orderType, String mac) {
        RemoteStopUpdateReqInnerFrame remoteStopUpdateReqInnerFrame = new RemoteStopUpdateReqInnerFrame();
        A5Frame a5Frame = new A5Frame(orderType, remoteStopUpdateReqInnerFrame);
        System.out.println(a5Frame + "      a5Frame");
        CommonFrame commonFrame = MainBoardInvokeSyncService.getInstance().sendRRPC(mac, a5Frame);
        System.out.println(commonFrame + "            -----commonFrame");
        RemoteStopUpdateReportInnerFrame innerFrame = new RemoteStopUpdateReportInnerFrame().transformFrame(commonFrame.getPayload());
        return innerFrame.isResponseState();
    }
}
ximon-admin/src/main/java/com/sandu/ximon/admin/utils/HexUtils.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,161 @@
package com.sandu.ximon.admin.utils;
/**
 * @author ZZQ
 * @date 2022/5/6 18:18
 */
public class HexUtils {
    /**
     * ç”¨äºŽå»ºç«‹åå…­è¿›åˆ¶å­—符的输出的小写字符数组
     */
    private static final char[] DIGITS_LOWER = { '0', '1', '2', '3', '4', '5',
            '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
    /**
     * ç”¨äºŽå»ºç«‹åå…­è¿›åˆ¶å­—符的输出的大写字符数组
     */
    private static final char[] DIGITS_UPPER = { '0', '1', '2', '3', '4', '5',
            '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
    /**
     * å°†å­—节数组转换为十六进制字符数组
     *
     * @param data
     *            byte[]
     * @return åå…­è¿›åˆ¶char[]
     */
    public static char[] encodeHex(byte[] data) {
        return encodeHex(data, true);
    }
    /**
     * å°†å­—节数组转换为十六进制字符数组
     *
     * @param data
     *            byte[]
     * @param toLowerCase
     *            <code>true</code> ä¼ æ¢æˆå°å†™æ ¼å¼ ï¼Œ <code>false</code> ä¼ æ¢æˆå¤§å†™æ ¼å¼
     * @return åå…­è¿›åˆ¶char[]
     */
    public static char[] encodeHex(byte[] data, boolean toLowerCase) {
        return encodeHex(data, toLowerCase ? DIGITS_LOWER : DIGITS_UPPER);
    }
    /**
     * å°†å­—节数组转换为十六进制字符数组
     *
     * @param data
     *            byte[]
     * @param toDigits
     *            ç”¨äºŽæŽ§åˆ¶è¾“出的char[]
     * @return åå…­è¿›åˆ¶char[]
     */
    protected static char[] encodeHex(byte[] data, char[] toDigits) {
        int l = data.length;
        char[] out = new char[l << 1];
        // two characters form the hex value.
        for (int i = 0, j = 0; i < l; i++) {
            out[j++] = toDigits[(0xF0 & data[i]) >>> 4];
            out[j++] = toDigits[0x0F & data[i]];
        }
        return out;
    }
    /**
     * å°†å­—节数组转换为十六进制字符串
     *
     * @param data
     *            byte[]
     * @return åå…­è¿›åˆ¶String
     */
    public static String encodeHexStr(byte[] data) {
        return encodeHexStr(data, true);
    }
    /**
     * å°†å­—节数组转换为十六进制字符串
     *
     * @param data
     *            byte[]
     * @param toLowerCase
     *            <code>true</code> ä¼ æ¢æˆå°å†™æ ¼å¼ ï¼Œ <code>false</code> ä¼ æ¢æˆå¤§å†™æ ¼å¼
     * @return åå…­è¿›åˆ¶String
     */
    public static String encodeHexStr(byte[] data, boolean toLowerCase) {
        return encodeHexStr(data, toLowerCase ? DIGITS_LOWER : DIGITS_UPPER);
    }
    /**
     * å°†å­—节数组转换为十六进制字符串
     *
     * @param data
     *            byte[]
     * @param toDigits
     *            ç”¨äºŽæŽ§åˆ¶è¾“出的char[]
     * @return åå…­è¿›åˆ¶String
     */
    protected static String encodeHexStr(byte[] data, char[] toDigits) {
        return new String(encodeHex(data, toDigits));
    }
    /**
     * å°†åå…­è¿›åˆ¶å­—符数组转换为字节数组
     *
     * @param data
     *            åå…­è¿›åˆ¶char[]
     * @return byte[]
     * @throws RuntimeException
     *             å¦‚果源十六进制字符数组是一个奇怪的长度,将抛出运行时异常
     */
    public static byte[] decodeHex(char[] data) {
        int len = data.length;
        if ((len & 0x01) != 0) {
            throw new RuntimeException("Odd number of characters.");
        }
        byte[] out = new byte[len >> 1];
        // two characters form the hex value.
        for (int i = 0, j = 0; j < len; i++) {
            int f = toDigit(data[j], j) << 4;
            j++;
            f = f | toDigit(data[j], j);
            j++;
            out[i] = (byte) (f & 0xFF);
        }
        return out;
    }
    /**
     * å°†åå…­è¿›åˆ¶å­—符转换成一个整数
     *
     * @param ch
     *            åå…­è¿›åˆ¶char
     * @param index
     *            åå…­è¿›åˆ¶å­—符在字符数组中的位置
     * @return ä¸€ä¸ªæ•´æ•°
     * @throws RuntimeException
     *             å½“ch不是一个合法的十六进制字符时,抛出运行时异常
     */
    protected static int toDigit(char ch, int index) {
        int digit = Character.digit(ch, 16);
        if (digit == -1) {
            throw new RuntimeException("Illegal hexadecimal character " + ch
                    + " at index " + index);
        }
        return digit;
    }
    public static void main(String[] args) {
        String srcStr = "待转换字符串";
        String encodeStr = encodeHexStr(srcStr.getBytes());
        String decodeStr = new String(decodeHex(encodeStr.toCharArray()));
        System.out.println("转换前:" + srcStr);
        System.out.println("转换后:" + encodeStr);
        System.out.println("还原后:" + decodeStr);
    }
}