| package com.dy.rtuMw.web.com; | 
|   | 
| import com.dy.common.softUpgrade.state.UpgradeTaskVo; | 
| import com.dy.common.webUtil.ResultCodeMsg; | 
| import com.dy.rtuMw.resource.ResourceUnit; | 
| import com.dy.rtuMw.server.ServerProperties; | 
| import com.dy.rtuMw.server.forTcp.TcpSessionCache; | 
| import com.dy.rtuMw.server.local.CommandInnerDeaLer; | 
| import com.dy.rtuMw.server.local.ReturnCommand; | 
| import com.dy.rtuMw.server.mqtt.MqttManager; | 
| import com.dy.rtuMw.server.msCenter.MsCenterUnit; | 
| import com.dy.rtuMw.server.tasks.WebDownCom4MqttTask; | 
| import com.dy.rtuMw.server.tasks.WebDownComTask; | 
| import com.dy.common.mw.core.CoreUnit; | 
| import com.dy.common.mw.protocol.Command; | 
| import com.dy.common.mw.protocol.CommandType; | 
| import com.dy.common.webUtil.BaseResponse; | 
| import com.dy.common.webUtil.BaseResponseUtils; | 
| import com.dy.rtuMw.server.tasks.WebDownTransparentComTask; | 
| import com.dy.rtuMw.server.upgrade.UpgradeUnit; | 
| import jakarta.servlet.ServletOutputStream; | 
| import jakarta.servlet.http.HttpServletRequest; | 
| import jakarta.servlet.http.HttpServletResponse; | 
| import lombok.extern.slf4j.Slf4j; | 
| import org.springframework.http.MediaType; | 
| import org.springframework.web.bind.annotation.*; | 
|   | 
| import java.io.*; | 
| import java.util.ArrayList; | 
| import java.util.Comparator; | 
| import java.util.List; | 
| import java.util.stream.Collectors; | 
| import java.util.stream.Stream; | 
|   | 
|   | 
| /** | 
|  * @Author liurunyu | 
|  * @Date 2023/12/21 13:58 | 
|  * @LastEditTime 2023/12/21 13:58 | 
|  * @Description 命令接收 | 
|  */ | 
| @Slf4j | 
| @RestController | 
| @RequestMapping(path="com") | 
| @SuppressWarnings("unchecked")//java版本越高,对泛型约束越严,所以配置SuppressWarnings("unchecked") | 
| public class CommandCtrl { | 
|   | 
|     @GetMapping(path = "test") | 
|     public BaseResponse<String> test(){ | 
|         return BaseResponseUtils.buildSuccess("ok"); | 
|     } | 
|   | 
|     /** | 
|      * 下载控制器(RTU)上下行数据的log日志文件 | 
|      * @param rtuAddr | 
|      * @param req | 
|      * @param rep | 
|      */ | 
|     @GetMapping("/rtuLogFile") | 
|     public void rtuLogFile(String rtuAddr, HttpServletRequest req, HttpServletResponse rep){ | 
|         logFile(rtuAddr, req, rep) ; | 
|     } | 
|   | 
|     /** | 
|      * 下载控制器(RTU)上下行数据的log日志文件 | 
|      * @param devId | 
|      * @param req | 
|      * @param rep | 
|      */ | 
|     @GetMapping("/mqttDevLogFile") | 
|     public void mqttDevLogFile(String devId, HttpServletRequest req, HttpServletResponse rep){ | 
|         logFile(devId, req, rep) ; | 
|     } | 
|     private void logFile(String fileName, HttpServletRequest req, HttpServletResponse rep){ | 
|         File logFile = ResourceUnit.getInstance().getLogFile(fileName + ".log") ; | 
|         if(logFile != null && logFile.exists()){ | 
|             //在Spring Boot中,application/octet-stream;charset=UTF-8通常表示响应的内容是字节流, | 
|             //并且字符集是UTF-8。对于这种类型的响应,Spring Boot默认使用ByteArrayHttpMessageConverter来处理, | 
|             //因为它可以处理所有application/octet-stream类型的响应。 | 
|             //然而,ByteArrayHttpMessageConverter并不直接处理字符集(charset)。 | 
|             //字符集通常用于文本内容,而application/octet-stream通常用于二进制内容,因此在这种情况下指定字符集可能是不合适的。 | 
|             //不过,如果你确实需要处理带有特定字符集的application/octet-stream响应,你可能需要自定义HttpMessageConverter。 | 
|             rep.addHeader("content-type", "application/octet-stream;charset=UTF-8"); | 
|             rep.addHeader("Content-Disposition", "attachment;fileName=" + (fileName + ".log")) ; | 
|             ServletOutputStream out = null; | 
|             FileInputStream in = null ; | 
|             try { | 
|                 out = rep.getOutputStream() ; | 
|             } catch (Exception ee) { | 
|                 out = null ; | 
|             }finally{ | 
|                 if(out != null){ | 
|                     byte[] bs = new byte[1024] ; | 
|                     int len = -1 ; | 
|                     try { | 
|                         in = new FileInputStream(logFile); | 
|                         len = in.read(bs) ; | 
|                         while(len != -1){ | 
|                             out.write(bs, 0, len); | 
|                             len = in.read(bs) ; | 
|                         } | 
|                     } catch (Exception eee) { | 
|                     } finally { | 
|                         if(out != null){ | 
|                             try{ | 
|                                 out.flush(); | 
|                                 out.close(); | 
|                             }catch(Exception e){ | 
|                             }finally{ | 
|                                 if(in != null){ | 
|                                     try{ | 
|                                         in.close(); | 
|                                     }catch(Exception e){ | 
|                                     } | 
|                                 } | 
|                             } | 
|                         } | 
|                     } | 
|                 } | 
|             } | 
|         } | 
|     } | 
|     /** | 
|      * 下载控制器(RTU)上下行数据的log日志文件 | 
|      * @param rtuAddr | 
|      */ | 
|     @GetMapping("/rtuLogText") | 
|     public BaseResponse<List<String>> rtuLogText(String rtuAddr){ | 
|         return logText(rtuAddr, true) ; | 
|     } | 
|     /** | 
|      * 下载控制器(RTU)上下行数据的log日志文件 | 
|      * @param devId | 
|      */ | 
|     @GetMapping("/mqttDevLogText") | 
|     public BaseResponse<List<String>> mqttDevLogText(String devId){ | 
|         return logText(devId, false) ; | 
|     } | 
|     /** | 
|      * 下载控制器(RTU)上下行数据的log日志文件 | 
|      * @param fileName | 
|      * @param reverseOrder | 
|      */ | 
|     private BaseResponse<List<String>> logText(String fileName, boolean reverseOrder){ | 
|         List<String> list ; | 
|         File logFile = ResourceUnit.getInstance().getLogFile(fileName + ".log") ; | 
|         if(logFile != null && logFile.exists()){ | 
|             BufferedReader reader = null ; | 
|             try { | 
|                 reader = new BufferedReader(new FileReader(logFile)) ; | 
|                 Stream<String> linesStream = reader.lines() ; | 
|                 if(reverseOrder){ | 
|                     list = linesStream.sorted(Comparator.reverseOrder()).collect(Collectors.toList()) ;//倒序 | 
|                 }else{ | 
|                     list = linesStream.toList() ; //按原来顺序 | 
|                 } | 
|                 return BaseResponseUtils.buildSuccess(list); | 
|             } catch (Exception e) { | 
|                 list = new ArrayList() ; | 
|                 list.add("读取控制器(" + fileName + ")的日志文件异常:" + (e.getMessage() == null?"":("," + e.getMessage()))) ; | 
|                 return BaseResponseUtils.buildSuccess(list); | 
|             }finally{ | 
|                 if(reader != null){ | 
|                     try{ | 
|                         reader.close(); | 
|                     }catch(Exception e){ | 
|                     } | 
|                 } | 
|             } | 
|         }else{ | 
|             list = new ArrayList() ; | 
|             list.add("未得到控制器(" + fileName + ")的日志文件") ; | 
|             return BaseResponseUtils.buildSuccess(list); | 
|         } | 
|     } | 
|   | 
|   | 
|     /** | 
|      * 注册消息接收者 | 
|      * @param msReceiverWebUrl 消息接收者web http post url | 
|      * @return | 
|      */ | 
|     @GetMapping("/registerMsReceiverWebUrl") | 
|     public BaseResponse<Boolean> registerMsReceiverWebUrl(String msReceiverWebUrl){ | 
|         try{ | 
|             MsCenterUnit.getInstance().registerMsReceiver(msReceiverWebUrl); | 
|         }catch (Exception e){ | 
|             log.error("注册消息接收者时发生异常", e); | 
|             return BaseResponseUtils.buildError("注册消息接收者时发生异常" + (e.getMessage() == null?"":(":" + e.getMessage()))); | 
|         } | 
|         return BaseResponseUtils.buildSuccess(true); | 
|     } | 
|   | 
|     /** | 
|      * 接收web系统发来升级任务 | 
|      * @param vo | 
|      * @return | 
|      */ | 
|     @PostMapping(path = "upgradeRtu", consumes = MediaType.APPLICATION_JSON_VALUE) | 
|     public BaseResponse<Boolean> upgradeRtu(@RequestBody UpgradeTaskVo vo) { | 
|         log.info("收到RTU升级任务:\n" + vo.toString()) ; | 
|         try{ | 
|             UpgradeUnit.getInstance().setUpgradeTask(vo); | 
|         }catch (Exception e){ | 
|             log.error("设置RTU升级任务时发生异常", e); | 
|             return BaseResponseUtils.buildError("设置RTU升级任务时发生异常" + (e.getMessage() == null?"":(":" + e.getMessage()))); | 
|         } | 
|         return BaseResponseUtils.buildSuccess(true); | 
|     } | 
|   | 
|     /** | 
|      * 接收web系统发来强制结束升级任务 | 
|      * @return | 
|      */ | 
|     @GetMapping(path = "ugForceOver") | 
|     public BaseResponse<String> ugForceOver() { | 
|         log.info("收到停止RTU升级任务命令") ; | 
|         try{ | 
|             String mes = UpgradeUnit.getInstance().forceOverUpgradeTask(); | 
|             if(mes == null){ | 
|                 mes = "停止升级任务成功" ; | 
|                 return BaseResponseUtils.buildResult(ResultCodeMsg.RsCode.SUCCESS_CODE, mes, mes); | 
|             }else{ | 
|                 return BaseResponseUtils.buildResult(ResultCodeMsg.RsCode.FAIL_CODE, mes, mes); | 
|             } | 
|         }catch (Exception e){ | 
|             log.error("停止RTU升级任务时发生异常", e); | 
|             return BaseResponseUtils.buildError("停止RTU升级任务时发生异常" + (e.getMessage() == null?"":(":" + e.getMessage()))); | 
|         } | 
|     } | 
|   | 
|     /** | 
|      * 接收web系统发来的命令 | 
|      * @param com | 
|      * @return | 
|      */ | 
|     @PostMapping(path = "send", consumes = MediaType.APPLICATION_JSON_VALUE) | 
|     public BaseResponse<Command> send(@RequestBody Command com) { | 
|         log.info("收到web系统发来的命令:\n" + com.toString()) ; | 
|   | 
|         String commandType = com.getType() ; | 
|         if(commandType == null){ | 
|             return BaseResponseUtils.buildError(ReturnCommand.errored("出错,收到命令的命令类型为空!", com.getId(), com.getCode())); | 
|         } | 
|         String commandId = com.getId() ; | 
|         if(commandId == null){ | 
|             return BaseResponseUtils.buildError(ReturnCommand.errored("出错,收到命令的命令ID为空!",null, com.getCode())); | 
|         } | 
|   | 
|         String code = com.getCode() ; | 
|         if(code == null){ | 
|             return BaseResponseUtils.buildError(ReturnCommand.errored("出错,收到命令的命令功能码为空!", com.getId(), null)); | 
|         } | 
|   | 
|         if(commandType.equals(CommandType.innerCommand)){ | 
|             //通信中间件内部命令,例如查询监控中间件时钟,查询RTU在线情况等 | 
|             try{ | 
|                 Command reCom = new CommandInnerDeaLer().deal(com) ; | 
|                 return BaseResponseUtils.buildSuccess(reCom); | 
|             }catch(Exception e){ | 
|                 return BaseResponseUtils.buildError(ReturnCommand.errored("处理内部命令出错" + (e.getMessage() == null?"":("," + e.getMessage())), com.getId(), com.getCode()) ); | 
|             } | 
|         }else if(commandType.equals(CommandType.outerCommand)){ | 
|             //发向RTU的外部命令 | 
|             try{ | 
|                 return this.dealOuterCommand(com) ; | 
|             }catch(Exception e){ | 
|                 return BaseResponseUtils.buildError(ReturnCommand.errored("处理发向RTU的外部命令出错" + (e.getMessage() == null?"":("," + e.getMessage())), com.getId(), com.getCode()) ); | 
|             } | 
|         }else if(commandType.equals(CommandType.outerTransCommand)){ | 
|             //发向RTU的外部透传命令 | 
|             try{ | 
|                 return this.dealOutTransparentCommand(com) ; | 
|             }catch(Exception e){ | 
|                 return BaseResponseUtils.buildError(ReturnCommand.errored("处理发向RTU的外部透传命令出错" + (e.getMessage() == null?"":("," + e.getMessage())), com.getId(), com.getCode()) ); | 
|             } | 
|         }else if(commandType.equals(CommandType.mqttCommand)){ | 
|             //发向MQTT的外部命令 | 
|             try{ | 
|                 return this.dealMqttCommand(com) ; | 
|             }catch(Exception e){ | 
|                 return BaseResponseUtils.buildError(ReturnCommand.errored("处理发向RTU的外部命令出错" + (e.getMessage() == null?"":("," + e.getMessage())), com.getId(), com.getCode()) ); | 
|             } | 
|         }else if(commandType.equals(CommandType.resultCommand)){ | 
|             return BaseResponseUtils.buildError(ReturnCommand.errored("出错,通信中间件不接结果类型的命令!", com.getId(), com.getCode())); | 
|         }else{ | 
|             return BaseResponseUtils.buildError(ReturnCommand.errored("出错,收到命令的命令功能码为空!", com.getId(), com.getCode())); | 
|         } | 
|     } | 
|   | 
|     /** | 
|      * 本地调用,例如任务树中某个任务下发的命令(如清空命令) | 
|      * @param com | 
|      * @return | 
|      */ | 
|     public BaseResponse<Command> sendOutComFromLocal(Command com) { | 
|         try{ | 
|             return this.dealOuterCommand(com) ; | 
|         }catch(Exception e){ | 
|             return BaseResponseUtils.buildError(ReturnCommand.errored("处理发向RTU的外部命令出错" + (e.getMessage() == null?"":("," + e.getMessage())), com.getId(), com.getCode()) ); | 
|         } | 
|     } | 
|   | 
|   | 
|     /** | 
|      * 处理发向RTU的外部命令 | 
|      * @return 结果 | 
|      */ | 
|     private BaseResponse<Command> dealOuterCommand(Command command){ | 
|         String rtuAddr = command.getRtuAddr() ; | 
|         if(rtuAddr == null || rtuAddr.trim().equals("")){ | 
|             return BaseResponseUtils.buildError(ReturnCommand.errored("出错,RTU地址为空!", command.getId(), command.getCode())) ; | 
|         } | 
|         rtuAddr = rtuAddr.trim() ; | 
|         Boolean onLine = TcpSessionCache.isConnect(rtuAddr); | 
|         if(onLine == null){ | 
|             return BaseResponseUtils.buildError(ReturnCommand.errored("出错,RTU(地址=" + rtuAddr + ")未上线!", command.getId(), command.getCode())) ; | 
|         }else if(!onLine.booleanValue()){ | 
|             if(!ServerProperties.isLowPower){ | 
|                 return BaseResponseUtils.buildError(ReturnCommand.errored("出错,RTU(地址=" + rtuAddr + ")离线!", command.getId(), command.getCode())) ; | 
|             } | 
|         } | 
|   | 
|         //生成异步任务 | 
|         WebDownComTask task = new WebDownComTask() ; | 
|         task.data = command ; | 
|         try{ | 
|             log.info("构造下发远程命令" + command.getCode() + "的核心任务,并放入任务队列中"); | 
|             CoreUnit.getInstance().pushCoreTask(task); | 
|         }catch(Exception e){ | 
|             log.error(e.getMessage(), e); | 
|             return BaseResponseUtils.buildError(ReturnCommand.successed("命令处理失败" + e.getMessage(), command.getId(), command.getCode())) ; | 
|         } | 
|   | 
|         return BaseResponseUtils.buildSuccess(ReturnCommand.successed("命令已接受,即将构造并下发命令。", command.getId(), command.getCode())); | 
|     } | 
|   | 
|   | 
|   | 
|     /** | 
|      * 处理发向RTU的外部命令 | 
|      * @return 结果 | 
|      */ | 
|     private BaseResponse<Command> dealOutTransparentCommand(Command command){ | 
|         String rtuAddr = command.getRtuAddr() ; | 
|         if(rtuAddr == null || rtuAddr.trim().equals("")){ | 
|             return BaseResponseUtils.buildError(ReturnCommand.errored("出错,RTU地址为空!", command.getId(), command.getCode())) ; | 
|         } | 
|         rtuAddr = rtuAddr.trim() ; | 
|         Boolean onLine = TcpSessionCache.isConnect(rtuAddr); | 
|         if(onLine == null){ | 
|             return BaseResponseUtils.buildError(ReturnCommand.errored("出错,RTU(地址=" + rtuAddr + ")未上线!", command.getId(), command.getCode())) ; | 
|         }else if(!onLine.booleanValue()){ | 
|             if(!ServerProperties.isLowPower){ | 
|                 return BaseResponseUtils.buildError(ReturnCommand.errored("出错,RTU(地址=" + rtuAddr + ")离线!", command.getId(), command.getCode())) ; | 
|             } | 
|         } | 
|   | 
|         //生成异步任务 | 
|         WebDownTransparentComTask task = new WebDownTransparentComTask() ; | 
|         task.data = command ; | 
|         try{ | 
|             log.info("构造下发远程透传命令" + command.getCode() + "的核心任务,并放入任务队列中"); | 
|             CoreUnit.getInstance().pushCoreTask(task); | 
|         }catch(Exception e){ | 
|             log.error(e.getMessage(), e); | 
|             return BaseResponseUtils.buildError(ReturnCommand.errored("透传命令处理失败" + e.getMessage(), command.getId(), command.getCode())) ; | 
|         } | 
|   | 
|         return BaseResponseUtils.buildSuccess(ReturnCommand.successed("透传命令已接受,即将构造并下发命令。", command.getId(), command.getCode())); | 
|     } | 
|   | 
|     /** | 
|      * 处理发向RTU的外部命令 | 
|      * @return 结果 | 
|      */ | 
|     private BaseResponse<Command> dealMqttCommand(Command command){ | 
|         String rtuAddr = command.getRtuAddr() ; | 
|         if(rtuAddr == null || rtuAddr.trim().equals("")){ | 
|             return BaseResponseUtils.buildError(ReturnCommand.errored("出错,设备ID为空!", command.getId(), command.getCode())) ; | 
|         } | 
|         if(!ServerProperties.mqttUnitEnable.booleanValue()){ | 
|             return BaseResponseUtils.buildError(ReturnCommand.errored("出错,MQTT连接模块配置未启动!", command.getId(), command.getCode())) ; | 
|         } | 
|         if(MqttManager.getInstance().poolIsClose()){ | 
|             return BaseResponseUtils.buildError(ReturnCommand.errored("出错,MQTT连接池水创建成功!", command.getId(), command.getCode())) ; | 
|         } | 
|   | 
|         //生成异步任务 | 
|         WebDownCom4MqttTask task = new WebDownCom4MqttTask() ; | 
|         task.data = command ; | 
|         try{ | 
|             log.info("构造下发MQTT命令" + command.getCode() + "的核心任务,并放入任务队列中"); | 
|             CoreUnit.getInstance().pushCoreTask(task); | 
|         }catch(Exception e){ | 
|             log.error(e.getMessage(), e); | 
|             return BaseResponseUtils.buildError(ReturnCommand.successed("MQTT命令处理失败" + e.getMessage(), command.getId(), command.getCode())) ; | 
|         } | 
|         return BaseResponseUtils.buildSuccess(ReturnCommand.successed("MQTT命令已接受,即将构造并下发命令。", command.getId(), command.getCode())); | 
|     } | 
|   | 
|   | 
|   | 
| } |