package com.dy.rtuMw.server.upgrade; 
 | 
  
 | 
import com.dy.common.softUpgrade.state.UpgradeInfo; 
 | 
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.springUtil.SpringContextUtil; 
 | 
import com.dy.common.util.Callback; 
 | 
import com.dy.common.util.DateTime; 
 | 
import com.dy.common.util.TimerTaskJob; 
 | 
import com.dy.rtuMw.web.webRequest.WebRequestDeal; 
 | 
import org.apache.logging.log4j.LogManager; 
 | 
import org.apache.logging.log4j.Logger; 
 | 
import java.util.List; 
 | 
  
 | 
/** 
 | 
 *  升级管理类 
 | 
 * @Author liurunyu 
 | 
 * @Date 2024/11/4 16:03 
 | 
 * @Description 
 | 
 */ 
 | 
public class UpgradeManager extends TimerTaskJob implements Callback { 
 | 
  
 | 
    private static final Logger log = LogManager.getLogger(UpgradeManager.class.getName()); 
 | 
  
 | 
    private static final UpgradeManager INSTANCE = new UpgradeManager(); 
 | 
  
 | 
    private Boolean openNoUpgrade ;//阀开(泵开)不执行升级 
 | 
    private Integer lastOpenMaxGoOn ;//阀开(泵开)状态设置以来持续最长时间(秒钟),超过这个时间认为状态无效(这个时长取决于工作报间隔) 
 | 
    private Integer failTryTimes ;//升级失败后,重新偿试升级次数,0表示不重新偿试升级 
 | 
    private Integer ugMaxRtuSameTime ;//同时升级RTU最大个数 
 | 
    private Integer notifyTimesAfterOver; //升级结束后,再向web服务系统通知状态的次数 
 | 
    private int nowNotifyTimesAfterOver; //升级结束后,再向web服务系统通知状态的次数 
 | 
  
 | 
    private UpgradeTask task ;//升级任务 
 | 
    private boolean monitorFirst ;//是否是第一次监视 
 | 
  
 | 
    private UpgradeManager(){ 
 | 
        monitorFirst = true ; 
 | 
    } 
 | 
  
 | 
    public static UpgradeManager getInstance() { 
 | 
        return UpgradeManager.INSTANCE; 
 | 
    } 
 | 
  
 | 
    /** 
 | 
     *  初始化配置信息 
 | 
     */ 
 | 
    public void initOption(UpgradeUnitConfigVo configVo) { 
 | 
        this.openNoUpgrade = configVo.openNoUpgrade; 
 | 
        this.lastOpenMaxGoOn = configVo.lastOpenMaxGoOn; 
 | 
        this.failTryTimes = configVo.failTryTimes; 
 | 
        this.ugMaxRtuSameTime = configVo.ugMaxRtuAtOnce; 
 | 
        this.notifyTimesAfterOver = configVo.notifyTimesAfterOver; 
 | 
    } 
 | 
  
 | 
    /** 
 | 
     * 设置升级任务 
 | 
     * @param vo UpgradeTaskVo 升级任务对象 
 | 
     * @throws Exception 异常 
 | 
     */ 
 | 
    public void setUpgradeTask(UpgradeTaskVo vo) throws Exception { 
 | 
        if(this.task != null && !this.task.taskIsOver){ 
 | 
            throw new Exception("当前存在升级任务,请等待当前任务执行完或强制结束当前任务"); 
 | 
        }else { 
 | 
            Exception ex = null ; 
 | 
            try{ 
 | 
                if(this.task != null){ 
 | 
                    this.task.forceOver(); 
 | 
                } 
 | 
                this.task = new UpgradeTask(); 
 | 
                this.task.initOption(this.openNoUpgrade, this.lastOpenMaxGoOn, this.failTryTimes, this.ugMaxRtuSameTime); 
 | 
                this.task.setTask(vo); 
 | 
                this.nowNotifyTimesAfterOver = 0 ; 
 | 
                this.monitorFirst = true ; 
 | 
                log.info("======================================================") ; 
 | 
                log.info("=                                                    =") ; 
 | 
                log.info("=设置了升级任务,涉及RTU" + vo.rtuAddrList.size() + "台                            =") ; 
 | 
                log.info("=                                                    =") ; 
 | 
                log.info("======================================================") ; 
 | 
            }catch (Exception e){ 
 | 
                ex = e ; 
 | 
            }finally { 
 | 
                if(ex != null){ 
 | 
                    this.task = null ; 
 | 
                    throw ex ; 
 | 
                }else{ 
 | 
                    this.start(1000L, (long) UpgradeUnit.confVo.notifyStateInterval, this); 
 | 
                } 
 | 
            } 
 | 
        } 
 | 
    } 
 | 
  
 | 
    /** 
 | 
     * 强制结束当前升级任务, 
 | 
     * 此功能可能不会开放出去, 
 | 
     * 因为强制结束升级任务,对一个未升级完成的RTU就会卡死, 
 | 
     * 所以当强制结束升级任务,代码逻辑并没有强制结果RTU升级过程,如果升级过程也强制停止,那么RTU真会卡死 
 | 
     */ 
 | 
    public String forceOverUpgradeTask() { 
 | 
        if(this.task != null){ 
 | 
            this.task.countRunningRtuCount(); 
 | 
            if(this.task.curUgRunningRtuTotal > 0){ 
 | 
                return "当前存在升级中的设备,不能结束升级任务" ; 
 | 
            }else{ 
 | 
                this.stop(); 
 | 
                this.task.forceOver(); 
 | 
                return null ; 
 | 
            } 
 | 
        }else{ 
 | 
            return "当前没有升级任务" ; 
 | 
        } 
 | 
    } 
 | 
  
 | 
    /** 
 | 
     * RTU有上行数据了,触发下发升级数据 
 | 
     * @param rtuAddr 控制器RTU地址 
 | 
     * @param code 上行数据功能码 
 | 
     * @param protocolName 上行数据对应的协议名称 
 | 
     * @param protocolVersion 上行数据对应的协议版本号 
 | 
     * @param callbackCom 回调函数,处理下行命令 
 | 
     */ 
 | 
    public void trigger(String rtuAddr, String code, String protocolName, Short protocolVersion, Callback callbackCom){ 
 | 
        if(task != null && !task.taskIsOver){ 
 | 
            this.task.trigger(rtuAddr, code, protocolName, protocolVersion, callbackCom); 
 | 
        } 
 | 
    } 
 | 
  
 | 
    //////////////////////////////////////////////////// 
 | 
    // 
 | 
    // 查询升级状态信息 
 | 
    // 
 | 
    //////////////////////////////////////////////////// 
 | 
    /** 
 | 
     * 当前升级状态 
 | 
     * @return 当前升级状态 
 | 
     */ 
 | 
    public UpgradeState currentUpgradeState() { 
 | 
        if(task != null){ 
 | 
            return task.currentUpgradeState() ; 
 | 
        }else{ 
 | 
            return null ; 
 | 
        } 
 | 
    } 
 | 
  
 | 
    /** 
 | 
     * Rtu升级信息 
 | 
     * @param rtuAddr 控制器RTU地址 
 | 
     * @return 控制器RTU升级状态 
 | 
     */ 
 | 
    @SuppressWarnings("unused") 
 | 
    public UpgradeRtu upgradeRtuInfo(String rtuAddr){ 
 | 
        if(task != null){ 
 | 
            return task.upgradeInfos(rtuAddr) ; 
 | 
        }else{ 
 | 
            return null ; 
 | 
        } 
 | 
    } 
 | 
  
 | 
    /** 
 | 
     * Rtu升级信息 
 | 
     * @param rtuAddrList 控制器地址列表 
 | 
     * @return 指定列表中的控制器RTU升级状态 
 | 
     */ 
 | 
    @SuppressWarnings("unused") 
 | 
    public List<UpgradeRtu> upgradeRtuInfos(List<String> rtuAddrList){ 
 | 
        if(task != null){ 
 | 
            return task.upgradeInfos(rtuAddrList) ; 
 | 
        }else{ 
 | 
            return null ; 
 | 
        } 
 | 
    } 
 | 
  
 | 
  
 | 
    /** 
 | 
     * 所有Rtu升级信息 
 | 
     * @return 所有Rtu升级信息 
 | 
     */ 
 | 
    public List<UpgradeRtu> upgradeRtuInfoAll(){ 
 | 
        if(task != null){ 
 | 
            return task.upgradeInfoAll() ; 
 | 
        }else{ 
 | 
            return null ; 
 | 
        } 
 | 
    } 
 | 
  
 | 
  
 | 
    //////////////////////////////////////////////////// 
 | 
    // 
 | 
    // 升级服务工作线程执行的方法 
 | 
    // 统计状态 + 状态通知 
 | 
    // 
 | 
    //////////////////////////////////////////////////// 
 | 
    public Object execute() { 
 | 
        if(this.task == null 
 | 
                || this.task.taskVo == null 
 | 
                || this.task.taskVo.rtuAddrList == null 
 | 
                || this.task.taskVo.rtuAddrList.size() == 0){ 
 | 
            //任务为空 
 | 
            this.stop() ; 
 | 
        }else{ 
 | 
            if(!this.task.taskIsOver){ 
 | 
                if(this.openNoUpgrade != null 
 | 
                        && this.openNoUpgrade.booleanValue() 
 | 
                        && this.monitorFirst){ 
 | 
                    //第一次进入,进行阀开不升级处理 
 | 
                    this.task.openNoUpgrade() ; 
 | 
                } 
 | 
                this.nowNotifyTimesAfterOver = 0 ; 
 | 
                //升级任务未完成 
 | 
                //工作1:判断是否无任何一个RTU进行过升级,并且达到时限,则认为当前升级任务完成 
 | 
                //-1:无一RTU升级且超时,0:无RTU升级但未超时等待,1有RTU升级正常执行 
 | 
                //int temp = 1 ; 
 | 
                int temp = this.task.countNoOneRtuUpgradeInDuration() ; 
 | 
                if(temp == -1){ 
 | 
                    //当前没有RTU进行过升级,而且超时了,认为任务已经完成 
 | 
                    this.task.taskIsOver = true ; 
 | 
                    this.stop(); 
 | 
                    log.info("===========================================================") ; 
 | 
                    log.info("=                                                         =") ; 
 | 
                    log.info("=无RTU升级超时,因无一台RTU进行升级,并且等待超时,强制设置升级完成  =") ; 
 | 
                    log.info("=                                                         =") ; 
 | 
                    log.info("===========================================================") ; 
 | 
                }else if(temp == 1){ 
 | 
                    //当前有RTU进行过升级 
 | 
                    //工作2:统计当前正在升级的RTU数量,为同时升级数量限制做准备 
 | 
                    temp = this.task.countRunningRtuCount() ; 
 | 
                    if(temp > 0){ 
 | 
                        //说前当前还有升级中的RTU 
 | 
                    } 
 | 
  
 | 
                    //工作3:统计需要升级但当前离线RTU的情况,超过时限的设置为升级完成 
 | 
                    int tmp = this.task.countOffRtuAndSetIfOver() ; 
 | 
                    if(tmp >= 1){ 
 | 
                        //超时,强制设置一些RTU升级失败并且升级完成 
 | 
                        log.info("======================================================") ; 
 | 
                        log.info("=                                                    =") ; 
 | 
                        log.info("=因离线超时,强制设置" + tmp + "台RTU升级失败并且升级完成            =") ; 
 | 
                        log.info("=                                                    =") ; 
 | 
                        log.info("======================================================") ; 
 | 
                    }else if(tmp == 0){ 
 | 
                        /* 
 | 
                        log.info("======================================================") ; 
 | 
                        log.info("=                                                    =") ; 
 | 
                        log.info("=离线超时,但无一台RTU因离线而被设置成升级失败并且升级完成     =") ; 
 | 
                        log.info("=                                                    =") ; 
 | 
                        log.info("======================================================") ; 
 | 
                         */ 
 | 
                    }else{//tmp = -1 
 | 
                        //无任务逻辑 
 | 
                    } 
 | 
  
 | 
                    //工作4:统计进行升级过程而后又停止升级,发呆一定时长的设备 
 | 
                    tmp = this.task.countRunningIdleRtuAndSetIfOver() ; 
 | 
                    if(tmp >= 1){ 
 | 
                        //升级发呆超时,强制设置一些RTU升级失败并且升级完成 
 | 
                        log.info("======================================================") ; 
 | 
                        log.info("=                                                    =") ; 
 | 
                        log.info("=因升级发呆超时,强制设置" + tmp + "台RTU升级失败并且升级完成          =") ; 
 | 
                        log.info("=                                                    =") ; 
 | 
                        log.info("======================================================") ; 
 | 
                    } 
 | 
  
 | 
                    //工作5:统计是否全部升级完成 
 | 
                    this.task.taskIsOver = this.task.countIsAllOver() ; 
 | 
                    if(this.task.taskIsOver){ 
 | 
                        log.info("==================================================") ; 
 | 
                        log.info("=                                                =") ; 
 | 
                        log.info("= 升级全部结束,设置升级任务完成,涉及RTU" + this.task.taskVo.rtuAddrList.size() + "台          =") ; 
 | 
                        log.info("=                                                =") ; 
 | 
                        log.info("==================================================") ; 
 | 
                    } 
 | 
                }else if(temp == 0){ 
 | 
                    //当前没有一个RTU进行过升级,也没有超时,不作为 
 | 
                } 
 | 
                if(this.task.taskIsOver){ 
 | 
                    if(!this.task.taskOverType.equals(UpgradeTask.TaskOverType_Force)){ 
 | 
                        //任务不是强制结束的 
 | 
                        this.task.taskOverType = UpgradeTask.TaskOverType_Natural ;//任务完成方式(自然,强制) 
 | 
                        this.task.taskOverDt = DateTime.yyyy_MM_dd_HH_mm_ss() ;//任务完成时间(yyyy-mm-dd HH:MM:SS) 
 | 
                    } 
 | 
                    //任务完成,执行最后一次升级状态通知 
 | 
                    //工作6:升级状态通知 
 | 
                    //if(!first){ 
 | 
                    //    this.notifyUpgradeStatus() ; 
 | 
                    //} 
 | 
                }else{ 
 | 
                    //任务未完成,继续执行升级状态通知 
 | 
                    //工作6: 升级状态通知 
 | 
                    //if(!first){ 
 | 
                    //    this.notifyUpgradeStatus() ; 
 | 
                    //} 
 | 
                } 
 | 
                //工作6:升级状态通知 
 | 
                if(!this.monitorFirst){ 
 | 
                    this.notifyUpgradeStatus() ; 
 | 
                } 
 | 
            }else{ 
 | 
                //任务已经完成 
 | 
                //工作6:任务结束后,最后发升级状态通知 
 | 
                if(this.nowNotifyTimesAfterOver == 0){ 
 | 
                    this.nowNotifyTimesAfterOver++ ; 
 | 
                    this.notifyUpgradeStatus() ;//必须通知一次 
 | 
                }else{ 
 | 
                    //然后重复通知 
 | 
                    if(this.nowNotifyTimesAfterOver <= this.notifyTimesAfterOver){ 
 | 
                        //保证上面必须通知一次,那此处上面if中就得用<= 
 | 
                        this.nowNotifyTimesAfterOver++ ; 
 | 
                        this.notifyUpgradeStatus() ; 
 | 
                    }else{ 
 | 
                        this.stop(); 
 | 
                    } 
 | 
                } 
 | 
  
 | 
            } 
 | 
        } 
 | 
        if(this.monitorFirst){ 
 | 
            this.monitorFirst = false ; 
 | 
        } 
 | 
        return true ; 
 | 
    } 
 | 
  
 | 
  
 | 
    /** 
 | 
     * 升级状态通知 
 | 
     */ 
 | 
    private void notifyUpgradeStatus(){ 
 | 
        if(this.task.taskVo.callbackWebUrl != null && this.task.taskVo.callbackWebUrl.length() > 0){ 
 | 
            UpgradeInfo info = new UpgradeInfo() ; 
 | 
            info.ugTaskId = this.task.taskVo.id ;//任务ID 
 | 
            info.ugOverallState = this.currentUpgradeState() ; 
 | 
            info.ugRtuStateList = this.upgradeRtuInfoAll() ; 
 | 
            WebRequestDeal deal = SpringContextUtil.getBean(WebRequestDeal.class) ; 
 | 
            deal.deal(this.task.taskVo.callbackWebUrl, info); 
 | 
        } 
 | 
    } 
 | 
  
 | 
    //////////////////////////////////////////////////// 
 | 
    // 
 | 
    // 升级状态通知工作线程执行完成后回调的方法, 
 | 
    // 也就是上面execute方法执行完成返回或抛出异常后,执行下面三个方法 
 | 
    // 
 | 
    //////////////////////////////////////////////////// 
 | 
    @Override 
 | 
    public void call(Object obj) { 
 | 
        //线程工作执行完了,obj = Boolean(true) 
 | 
    } 
 | 
    @Override 
 | 
    public void call(Object... objs) { 
 | 
    } 
 | 
    @Override 
 | 
    public void exception(Exception e) { 
 | 
        log.error("远程升级伺服线程发生异常", e); 
 | 
    } 
 | 
  
 | 
} 
 |