zhubaomin
2024-11-13 9312cee2191aabf6043356e2927ca692a57921ec
pipIrr-platform/pipIrr-mw/pipIrr-mw-rtu/src/main/java/com/dy/rtuMw/server/upgrade/UpgradeTask.java
@@ -2,7 +2,9 @@
import com.alibaba.fastjson2.annotation.JSONField;
import com.dy.common.softUpgrade.parse.HexFileParse;
import com.dy.common.softUpgrade.parse.HexFileVo;
import com.dy.common.softUpgrade.state.UpgradeRtu;
import com.dy.common.softUpgrade.state.UpgradeState;
import com.dy.common.softUpgrade.state.UpgradeTaskVo;
import com.dy.common.util.Callback;
import com.dy.common.util.DateTime;
import lombok.Data;
@@ -17,30 +19,37 @@
@Data
public class UpgradeTask {
    protected static final String TaskOverType_Natural = "自然" ;
    protected static final String TaskOverType_Force = "强制" ;
    @JSONField(serialize = false)
    protected Integer failTryTimes ;//升级失败后,重新偿试升级次数,0表示不重新偿试升级
    @JSONField(serialize = false)
    protected Integer ugMaxRtuSameTime ;//同时升级RTU最大个数
    public String setupDt ;//设置时间(yyyy-mm-dd HH:MM:SS)
    @JSONField(serialize = false)
    private Long setupDtLong ;//设置时间
    public String softFileName ;//升级软件(hex)文件名称
    public String softStoreAddr ;//升级程序存放地址(4字节,8字符HEX字符串),升级程序在FLASH中存放地址
    public String softStartAddr ;//程序覆盖起始地址(4字节,8字符HEX字符串),被刷新程序的起始地址高字节在前 ,低字节在后
    public UpgradeTaskVo taskVo ;//升级任务值对象
    @JSONField(serialize = false)
    public byte[][] softData ;//升级程序数据(每包数据是512字节)
    @JSONField(serialize = false)
    public int softByteSrc16;//升级程序校验码 CRC16
    public int softBytesCalculate;//升级程序字节数(按公式计算)
    public List<String> rtuAddrList ;//需要升级的RTU地址集合
    protected byte[][] softFileDataGrp ;//以512字节为单位把升级程序数据分组
    @JSONField(serialize = false)
    public Map<String, UpgradeRtu> upgradeState ;//升级状态
    protected Map<String, UpgradeRtu> upgradeRtus;//升级状态
    public boolean taskIsOver = false ;//任务是否完成
    public String taskOverType = "" ;//任务完成方式(自然,强制)
    public String taskOverDt = "" ;//任务完成时间(yyyy-mm-dd HH:MM:SS)
    ///////////////////////////////////////////////////
    //以下内部控制用
    @JSONField(serialize = false)
    private int curUgRunningRtuTotal = 0 ;//当前正在升级的RTU个数
    public UpgradeTask() {
        this.curUgRunningRtuTotal = 0 ;
    }
    /**
     *  初始化配置信息
@@ -51,70 +60,112 @@
    }
    /**
     * 设置升级任务
     * @param softFileName 升级程序文件名
     * @param softStoreAddr 升级程序存放地址
     * @param softStartAddr 程序覆盖起始地址
     * @param softFileData 升级程序字节数组
     * @param softBytesCalculate 升级程序字节数(按公式计算)
     * @param rtuAddrList 升级RTU
     * @param taskVo UpgradeTaskVo 升级任务对象
     * @throws Exception
     */
    public void setTask(String softFileName,
                       String softStoreAddr,
                       String softStartAddr,
                       byte[] softFileData,
                       Integer softBytesCalculate,
                       List<String> rtuAddrList) throws Exception {
        if(softFileName == null || softFileName.trim().length() == 0){
    public void setTask(UpgradeTaskVo taskVo) throws Exception {
        if(taskVo.id == null || taskVo.id.trim().length() == 0){
            throw new Exception("升级任务id必须提供") ;
        }
       if(taskVo.softFileName == null || taskVo.softFileName.trim().length() == 0){
            throw new Exception("升级软件(hex)文件名称必须提供") ;
        }
        if(softStoreAddr == null || softStoreAddr.trim().length() != 8){
        if(taskVo.softStoreAddr == null || taskVo.softStoreAddr.trim().length() != 8){
            throw new Exception("升级程序存放地址不合法,必须是8字符(十六进制)的字符串") ;
        }
        if(softStartAddr == null || softStartAddr.trim().length() != 8){
        if(taskVo.softStartAddr == null || taskVo.softStartAddr.trim().length() != 8){
            throw new Exception("程序覆盖起始地址不合法,必须是8字符(十六进制)的字符串") ;
        }
        if(softFileData == null || softFileData.length <= 0){
        if(taskVo.softFileData == null || taskVo.softFileData.length <= 0){
            throw new Exception("升级程序内容必须提供") ;
        }
        if(rtuAddrList == null || rtuAddrList.size() <= 0){
        if(taskVo.softBytesCalculate == null){
            throw new Exception("公式计算升级程序有效序字节数必须提供") ;
        }
       if(taskVo.softByteSrc16 == null){
            throw new Exception("有效升级程序字节数CRC16校验值必须提供") ;
        }
        if(taskVo.rtuAddrList == null || taskVo.rtuAddrList.size() <= 0){
            throw new Exception("升级设备RTU地址必须提供") ;
        }
        if(taskVo.callbackWebUrl == null || taskVo.callbackWebUrl.trim().equals("")){
            throw new Exception("回调网址必须提供") ;
        }
        this.setupDt = DateTime.yyyy_MM_dd_HH_mm_ss() ;
        this.softFileName = softFileName;
        this.softStoreAddr = softStoreAddr;
        this.softStartAddr = softStartAddr;
        this.softBytesCalculate = softBytesCalculate;
        this.rtuAddrList = rtuAddrList;
        this.setupDtLong = System.currentTimeMillis() ;
        this.taskVo = taskVo ;
        this.upgradeState = new HashMap<>();
        if(softFileData != null && softFileData.length >0){
            HexFileVo vo = new HexFileParse().doParse(softFileData);
            this.softData = vo.listByte512.toArray(new byte[0][]);
            this.softByteSrc16 = vo.bytesCrc16 ;
        this.upgradeRtus = new HashMap<>();
        if(taskVo.softFileData != null && taskVo.softFileData.length >0){
            List<byte[]> listBytes = new HexFileParse().splitBytesByUnit512(taskVo.softFileData);
            this.softFileDataGrp = listBytes.toArray(new byte[0][]);
            for(String rtuAddr : this.taskVo.rtuAddrList){
                //此时状态设置成离线状态
                UpgradeRtuDev ugRtu = new UpgradeRtuDev(this, rtuAddr, this.softFileDataGrp.length, UpgradeRtuDev.STATE_OFFLINE) ;
                this.upgradeRtus.put(rtuAddr, ugRtu) ;
            }
        }
    }
    /**
     * RTU有上行数据了,触发下发升级数据
     * @param rtuAddr
     * @param code
     * @param callback
     * @param callbackCom
     */
    public void trigger(String rtuAddr, String code, String protocolName, Short protocolVersion, Callback callback){
        if(upgradeState != null && upgradeState.size() > 0
                && rtuAddrList != null && rtuAddrList.size() > 0){
            UpgradeRtu info = upgradeState.get(rtuAddr) ;
            if(info == null){
                if(rtuAddrList.contains(rtuAddr)){
                    info = new UpgradeRtu(this, rtuAddr, softData.length) ;
                    upgradeState.put(rtuAddr, info) ;
    public void trigger(String rtuAddr, String code, String protocolName, Short protocolVersion, Callback callbackCom){
        if(this.upgradeRtus != null && this.upgradeRtus.size() > 0
                && this.taskVo.rtuAddrList != null && this.taskVo.rtuAddrList.size() > 0){
            UpgradeRtu ugRtu = this.upgradeRtus.get(rtuAddr) ;
            if(ugRtu == null){
                //根据方法setTask的逻辑,只要RTU在升级之列,此处ugRtuState一定不为null
                //为保险,实现下面逻辑
                if(taskVo.rtuAddrList.contains(rtuAddr)){
                    ugRtu = new UpgradeRtuDev(this, rtuAddr, this.taskVo.softFileData.length) ;
                    upgradeRtus.put(rtuAddr, ugRtu) ;
                }else{
                    //rtu不在升级之列
                    return ;
                }
            }
            if(info != null){
                info.trigger(code, protocolName, protocolVersion, this.softData, callback) ;
            if(ugRtu != null){
                if(ugRtu.isOver){
                    //当前RTU已经升级完成,无需再升级
                    return;
                }else{
                    if(UpgradeUnit.confVo.ugMaxRtuAtOnce > 0){
                        //设置了同时升级的RTU最大数量的限制
                        if(ugRtu.state == UpgradeRtuDev.STATE_OFFLINE){
                            //初始态,说明升级任务设置以来,该RTU第一次上行数据
                            if(this.curUgRunningRtuTotal <= UpgradeUnit.confVo.ugMaxRtuAtOnce){
                                //当前正在升级的RTU数量还未受限
                                ugRtu.trigger(code, protocolName, protocolVersion, this.softFileDataGrp, callbackCom) ;
                            }else{
                                //同时升级的RTU数量受限,等待下次机会
                                //但先表明一下状态
                                ugRtu.state = UpgradeRtuDev.STATE_UNSTART ;
                                return ;
                            }
                        }else if(ugRtu.state == UpgradeRtuDev.STATE_UNSTART){
                            //根据上面逻辑, 说明必然在线了
                            if(this.curUgRunningRtuTotal <= UpgradeUnit.confVo.ugMaxRtuAtOnce){
                                //当前正在升级的RTU数量还未受限
                                ugRtu.trigger(code, protocolName, protocolVersion, this.softFileDataGrp, callbackCom) ;
                            }else{
                                //同时升级的RTU数量受限,等待下次机会
                                return ;
                            }
                        }else{
                            //RTU已经处于升级过程中
                            ugRtu.trigger(code, protocolName, protocolVersion, this.softFileDataGrp, callbackCom) ;
                        }
                    }else{
                        //没有设置同时升级的RTU最大数量的限制
                         ugRtu.trigger(code, protocolName, protocolVersion, this.softFileDataGrp, callbackCom) ;
                    }
                }
            }else{
                //rtu不在升级之列
                return ;
            }
        }
    }
@@ -123,29 +174,11 @@
     * 强制结束升级任务
     */
    public void forceOver(){
        this.rtuAddrList.clear();
        this.upgradeState.clear();
    }
    /**
     * 升级任务是否完成
     * @return
     */
    public boolean isOver() {
        boolean isOver = true ;
        if(upgradeState != null && upgradeState.size() > 0){
            Collection<UpgradeRtu> col = upgradeState.values() ;
            for(UpgradeRtu info : col){
                if(info.state == UpgradeRtu.STATE_UNSTART){
                    isOver = false ;
                    break ;
                }else if(info.state == UpgradeRtu.STATE_RUNNING){
                    isOver = false ;
                    break ;
                }
            }
        }
        return isOver ;
        this.taskIsOver = true ;//强制设置任务完成
        this.taskOverType = TaskOverType_Force ;//任务完成方式(自然,强制)
        this.taskOverDt = DateTime.yyyy_MM_dd_HH_mm_ss() ;//任务完成时间(yyyy-mm-dd HH:MM:SS)
        //this.taskVo.rtuAddrList.clear();
        //this.upgradeState.clear();
    }
    /**
@@ -154,24 +187,26 @@
     */
    public UpgradeState currentUpgradeState() {
        UpgradeState state = new UpgradeState() ;
        if(rtuAddrList != null && rtuAddrList.size() > 0){
            state.rtuTotal = rtuAddrList.size() ;
            if(upgradeState != null && upgradeState.size() > 0){
                Collection<UpgradeRtu> col = upgradeState.values() ;
        if(this.taskVo.rtuAddrList != null && this.taskVo.rtuAddrList.size() > 0){
            state.rtuTotal = this.taskVo.rtuAddrList.size() ;
            if(this.upgradeRtus != null && this.upgradeRtus.size() > 0){
                Collection<UpgradeRtu> col = this.upgradeRtus.values() ;
                for(UpgradeRtu info : col){
                    if(info.state == UpgradeRtu.STATE_UNSTART){
                    if(info.state == UpgradeRtu.STATE_OFFLINE){
                        state.offLineTotal ++ ;
                    }else if(info.state == UpgradeRtu.STATE_UNSTART){
                        state.unStartTotal ++ ;
                    }else if(info.state == UpgradeRtu.STATE_RUNNING){
                        state.runningTotal ++ ;
                    }else if(info.state == UpgradeRtu.STATE_SUCCESS) {
                        state.successTotal++;
                        state.overTotal++;
                    }else if(info.state == UpgradeRtu.STATE_FAILONE) {
                        state.failOneTotal++;
                        state.failTotal++;
                        state.overTotal++;
                    }else if(info.state == UpgradeRtu.STATE_FAIL) {
                        state.failTotal++;
                    }
                    if(info.isOver){
                        state.overTotal++;
                    }
                }
@@ -186,23 +221,84 @@
     * @return
    */
    public UpgradeRtu upgradeInfos(String rtuAddr){
        return upgradeState.get(rtuAddr) ;
        return this.upgradeRtus.get(rtuAddr) ;
    }
    /**
     * Rtu升级信息
     * 一些Rtu升级信息
     * @param rtuAddrList
     * @return
     */
    public List<UpgradeRtu> upgradeInfos(List<String> rtuAddrList){
        List<UpgradeRtu> list = new ArrayList<>() ;
        for(String rtuAddr : rtuAddrList){
            UpgradeRtu info = upgradeState.get(rtuAddr) ;
            UpgradeRtu info = this.upgradeRtus.get(rtuAddr) ;
            if(info != null){
                list.add(info) ;
            }
        }
        return list ;
    }
    /**
     * 全部Rtu升级信息
     * @return
     */
    public List<UpgradeRtu> upgradeInfoAll(){
        if(this.upgradeRtus != null && this.upgradeRtus.size() > 0){
            return this.upgradeRtus.values().stream().toList();
        }else{
            return null ;
        }
    }
    ///////////////////////////////////////////////////////////
    //以下方法为内部服务,不对外提供服务
    ///////////////////////////////////////////////////////////
    /**
     * 统计当前正在升级的RTU数量,为受限同时升级数量做准备
     */
    protected void statisticsRunningRtuCount(){
        int runningTotal = 0 ;
        Collection<UpgradeRtu> col = this.upgradeRtus.values() ;
        for(UpgradeRtu info : col){
            if(info.state == UpgradeRtu.STATE_RUNNING){
                runningTotal ++ ;
            }
        }
        this.curUgRunningRtuTotal = runningTotal ;
    }
    /**
     * 统计需要升级但当前离线RTU的情况
     */
    protected void statisticsOffRtuCountAndSet() {
        Long now = System.currentTimeMillis() ;
        if(now - this.setupDtLong > UpgradeUnit.confVo.rtuOffLineWaitDuration){
            //rtu离线,等待其升级的时长(毫秒),超过配置的最大时长,设置其升级失败,且设置升级任务完成
            if (this.taskVo.rtuAddrList != null && this.taskVo.rtuAddrList.size() > 0) {
                Collection<UpgradeRtu> col = this.upgradeRtus.values() ;
                for(UpgradeRtu info : col){
                    if(info.state == UpgradeRtu.STATE_OFFLINE){
                        info.isOver = true ;
                        info.state = UpgradeRtu.STATE_FAILOFFLINE ;
                    }
                }
            }
        }
    }
    /**
     * 统计是否升级全部结束
     */
    protected boolean statisticsIsAllOver() {
        if (this.taskVo.rtuAddrList != null && this.taskVo.rtuAddrList.size() > 0) {
            Collection<UpgradeRtu> col = this.upgradeRtus.values() ;
            for(UpgradeRtu info : col){
                if(info.isOver == false){
                    return false ;
                }
            }
        }
        return true ;
    }
}