package com.dy.rtuMw.web.com;
|
|
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.tasks.RtuDownTask;
|
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 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.List;
|
|
|
/**
|
* @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){
|
File logFile = ResourceUnit.getInstance().getLogFile(rtuAddr + ".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=" + (rtuAddr + ".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){
|
List<String> list = new ArrayList() ;
|
File logFile = ResourceUnit.getInstance().getLogFile(rtuAddr + ".log") ;
|
if(logFile != null && logFile.exists()){
|
BufferedReader reader = null ;
|
try {
|
reader = new BufferedReader(new FileReader(logFile)) ;
|
String line ;
|
while((line = reader.readLine()) != null){
|
list.add(line) ;
|
}
|
return BaseResponseUtils.buildSuccess(list);
|
} catch (Exception e) {
|
list.add("读取控制器(" + rtuAddr + ")的日志文件异常:" + (e.getMessage() == null?"":("," + e.getMessage()))) ;
|
return BaseResponseUtils.buildSuccess(list);
|
}finally{
|
if(reader != null){
|
try{
|
reader.close();
|
}catch(Exception e){
|
}
|
}
|
}
|
}else{
|
list.add("未得到控制器(" + rtuAddr + ")的日志文件") ;
|
return BaseResponseUtils.buildSuccess(list);
|
}
|
}
|
/**
|
* 接收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) ;
|
/*
|
boolean error = false ;
|
if(reCom.param != null && reCom.param != null){
|
CommandBackParam cbp = (CommandBackParam)reCom.param ;
|
if(cbp.getSuccess() != null && !cbp.getSuccess().booleanValue()){
|
error = true ;
|
return BaseResponseUtils.buildError(ReturnCommand.errored(cbp.getMessage(), com.getId(), null));
|
}
|
}
|
if(!error){
|
return BaseResponseUtils.buildError(ReturnCommand.errored(cbp.getMessage(), com.getId(), null));
|
}
|
*/
|
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的外部命令,异步处理,web端jroups成员同步得到命令处理结果,但构造命令及下发命令和命令结果接收要异步得到
|
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.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())) ;
|
}
|
}
|
|
//生成异步任务
|
RtuDownTask task = new RtuDownTask() ;
|
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()));
|
}
|
|
}
|