1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
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);
    }
 
}