1、实现万用token(0000-0000-1234-9876-5);
2、web端单独实现命令结果等待器,并修改相关部分;
3、web端实现透传命令;
4、修改一些不当注释;
5、优化一些代码。
| | |
| | | public String protocol ;//数据所对应的协议名称 |
| | | public Short protocolVer;//数据所对应的协议版本号(1~255) |
| | | public String code ;//数据所对应的功能码: |
| | | public Object subData ;//对应各个功能码的具体数据 |
| | | public Object subData ;//对应各个协议数据 |
| | | public String hex ;//上报数据的十六进制 |
| | | |
| | | public String toString() { |
| | |
| | | |
| | | public String rtuAddr ;//RtuAddr |
| | | |
| | | public Object subData ; |
| | | public Object subData ;;//功能码数据 |
| | | |
| | | public String dt ;//通信中间件产生的收报时间(yyyy-MM-dd hh:mm:ss) |
| | | |
| | |
| | | |
| | | public String rtuAddr ;//RtuAddr |
| | | |
| | | public Object subData ; |
| | | public Object subData ;//功能码数据 |
| | | |
| | | public String dt ;//通信中间件产生的收报时间(yyyy-MM-dd hh:mm:ss) |
| | | |
| | |
| | | |
| | | public String rtuAddr ;//RtuAddr |
| | | |
| | | public Object subData ; |
| | | public Object subData ;//功能码数据 |
| | | |
| | | public String dt ;//通信中间件产生的收报时间(yyyy-MM-dd hh:mm:ss) |
| | | |
New file |
| | |
| | | package com.dy.pipIrrGlobal.command; |
| | | |
| | | import java.util.Map; |
| | | import java.util.concurrent.CompletableFuture; |
| | | import java.util.concurrent.ConcurrentHashMap; |
| | | |
| | | /** |
| | | * @Author: liurunyu |
| | | * @Date: 2025/5/6 16:33 |
| | | * @Description |
| | | */ |
| | | public class ComResultWait { |
| | | |
| | | //ConcurrentHashMap是线程安全的 |
| | | private static final Map<Long, CompletableFuture> features = new ConcurrentHashMap<>(); |
| | | |
| | | public static void put(Long key, CompletableFuture value) { |
| | | features.put(key, value); |
| | | } |
| | | public static CompletableFuture get(Long key) { |
| | | return features.get(key); |
| | | } |
| | | |
| | | public static void remove(Long key){ |
| | | features.remove(key) ; |
| | | } |
| | | |
| | | } |
| | |
| | | |
| | | protected String commandTypeOuter = CommandType.outerCommand; |
| | | |
| | | // 存储实例化的 CompletableFuture<Data> 对象 |
| | | protected static Map<Long, Object> features = new HashMap<>(); |
| | | //protected static Boolean setuped = false; |
| | | |
| | | @Autowired |
| | | private RestTemplate restTemplate; |
| | | |
| | |
| | | */ |
| | | protected BaseResponse<Data> dealWithCallBack(Long comId, Command com) { |
| | | CompletableFuture<JSONObject> feature = new CompletableFuture<>(); |
| | | features.put(comId, feature); |
| | | ComResultWait.put(comId, feature); |
| | | try { |
| | | // 发送命令 |
| | | JSONObject response_SendCom = (JSONObject) JSON.toJSON(sendCom2Mw(com)); |
| | | if (response_SendCom == null || !response_SendCom.getString("code").equals("0001")) { |
| | | // 请求失败,RTU未上线,清除feature |
| | | features.remove(comId); |
| | | ComResultWait.remove(comId); |
| | | JSONObject job_param = response_SendCom.getJSONObject("content").getJSONObject("param"); |
| | | return BaseResponseUtils.buildErrorMsg(job_param.getString("message")); |
| | | } |
| | | |
| | | JSONObject resultData = feature.get(180, TimeUnit.SECONDS); |
| | | features.remove(comId); |
| | | ComResultWait.remove(comId); |
| | | |
| | | Long commandId = resultData.getLong("commandId"); |
| | | if (commandId.equals(comId)) { |
New file |
| | |
| | | package com.dy.pipIrrGlobal.command; |
| | | |
| | | import com.alibaba.fastjson2.JSON; |
| | | import com.alibaba.fastjson2.JSONObject; |
| | | import com.dy.common.mw.protocol.Command; |
| | | import com.dy.common.mw.protocol.CommandBackParam; |
| | | import com.dy.common.mw.protocol.p206V1.CodeV1; |
| | | import com.dy.common.mw.protocol.p206V1.ProtocolConstantV206V1; |
| | | import com.dy.common.mw.protocol.p206V2.CodeV2; |
| | | import com.dy.common.mw.protocol.p206V2.ProtocolConstantV206V2; |
| | | import com.dy.common.mw.protocol.p206V202404.CodeV202404; |
| | | import com.dy.common.mw.protocol.p206V202404.ProtocolConstantV206V202404; |
| | | import com.dy.common.webUtil.BaseResponse; |
| | | import com.dy.pipIrrGlobal.daoPr.PrControllerMapper; |
| | | import com.dy.pipIrrGlobal.daoRm.RmCommandHistoryMapper; |
| | | import com.dy.pipIrrGlobal.pojoPr.PrController; |
| | | import com.dy.pipIrrGlobal.pojoRm.RmCommandHistory; |
| | | import com.dy.pipIrrGlobal.rtuMw.Web2RtuMw; |
| | | |
| | | import java.util.Date; |
| | | |
| | | /** |
| | | * @Author: liurunyu |
| | | * @Date: 2025/5/6 11:41 |
| | | * @Description |
| | | */ |
| | | public class CommandSv extends Web2RtuMw { |
| | | |
| | | |
| | | /** |
| | | * 从数据库中查询控制器对象 |
| | | * @param prControllerDao |
| | | * @param intakeId |
| | | * @return |
| | | */ |
| | | public PrController getRtu(PrControllerMapper prControllerDao, Long intakeId){ |
| | | return prControllerDao.getRtu(intakeId, null); |
| | | } |
| | | |
| | | /** |
| | | * 检查协议是否支持 |
| | | * @param ctrlPo |
| | | * @return |
| | | */ |
| | | public String checkProtocol(PrController ctrlPo){ |
| | | if(!ctrlPo.getProtocol().equals(ProtocolConstantV206V1.protocolName) |
| | | && !ctrlPo.getProtocol().equals(ProtocolConstantV206V2.protocolName) |
| | | && !ctrlPo.getProtocol().equals(ProtocolConstantV206V202404.protocolName)) { |
| | | return "对应控制器协议" + ctrlPo.getProtocol() + "未实现命令发送逻辑" ; |
| | | } |
| | | return null ; |
| | | } |
| | | |
| | | /** |
| | | * 根据协议获取命令名称 |
| | | * @param nowComCode |
| | | * @param ctrlPo |
| | | * @return |
| | | */ |
| | | public String getCommandName(String nowComCode, PrController ctrlPo){ |
| | | if(ctrlPo.getProtocol().equals(ProtocolConstantV206V1.protocolName)) { |
| | | return CodeV1.getCodeName(nowComCode) ; |
| | | }else if(ctrlPo.getProtocol().equals(ProtocolConstantV206V2.protocolName)) { |
| | | return CodeV2.getCodeName(nowComCode) ; |
| | | }else if(ctrlPo.getProtocol().equals(ProtocolConstantV206V202404.protocolName)) { |
| | | return CodeV202404.getCodeName(nowComCode) ; |
| | | } |
| | | return null ; |
| | | } |
| | | |
| | | /** |
| | | * 保存命令历史记录 |
| | | * @param rmCommandHistoryDao |
| | | * @param comId |
| | | * @param protocol |
| | | * @param commandCode |
| | | * @param commandName |
| | | * @param intakeId |
| | | * @param rtuAddr |
| | | * @param param |
| | | * @param operator |
| | | * @return |
| | | */ |
| | | public RmCommandHistory saveComHistoryPo(RmCommandHistoryMapper rmCommandHistoryDao, |
| | | Long comId, |
| | | String protocol, |
| | | String commandCode, |
| | | String commandName, |
| | | Long intakeId, |
| | | String rtuAddr, |
| | | Object param, |
| | | Long operator) { |
| | | RmCommandHistory po = new RmCommandHistory(); |
| | | po.setComId(comId); |
| | | po.setCommandCode(commandCode); |
| | | po.setCommandName(commandName); |
| | | po.setIntakeId(intakeId); |
| | | po.setRtuAddr(rtuAddr); |
| | | po.setProtocol(protocol); |
| | | po.setParam((JSONObject) JSON.toJSON(param)); |
| | | po.setSendTime(new Date()); |
| | | po.setOperator(operator); |
| | | rmCommandHistoryDao.insertSelective(po) ; |
| | | return po; |
| | | } |
| | | |
| | | /** |
| | | * 处理通信中间件返回的命令处理结果 |
| | | * @param res |
| | | * @return |
| | | */ |
| | | public String dealMwDealResponse(BaseResponse res){ |
| | | if(res != null){ |
| | | Command reCom = JSON.parseObject(res.getContent() == null ? null : JSON.toJSONString(res.getContent()), Command.class) ; |
| | | CommandBackParam bakParam = JSON.parseObject((reCom== null || reCom.param == null) ? null : JSON.toJSONString(reCom.param), CommandBackParam.class) ; |
| | | if(res.isSuccess()){ |
| | | if(bakParam != null){ |
| | | if(bakParam.getSuccess().booleanValue()){ |
| | | //通信中间件成功处理了命令 |
| | | //等待控制器接收并执行命令后的应答,然后通信中间件通知本模块 |
| | | return null ; |
| | | }else{ |
| | | return "通信中间件处理命令失败,失败信息:" + bakParam.getMessage(); |
| | | } |
| | | }else{ |
| | | return "通信中间件返回命令结果中不包含CommandBackParam类型参数"; |
| | | } |
| | | }else{ |
| | | if(bakParam != null){ |
| | | if(bakParam.getSuccess().booleanValue()){ |
| | | //通信中间件成功处理了命令 |
| | | //等待控制器接收并执行命令后的应答,然后通信中间件通知本模块 |
| | | return "通信中间件处理命令失败,失败信息:" + (res.getMsg() == null? "" : ("," + res.getMsg())) ; |
| | | }else{ |
| | | return "通信中间件处理命令失败,失败信息:" + bakParam.getMessage(); |
| | | } |
| | | }else{ |
| | | return "通信中间件处理命令失败,失败信息:" + (res.getMsg() == null? "" : ("," + res.getMsg())) ; |
| | | } |
| | | } |
| | | }else{ |
| | | return "通信中间件返回命令结果为null"; |
| | | } |
| | | } |
| | | |
| | | } |
| | |
| | | private static final String pro_mw = "mw"; |
| | | private static final String pro_url = "url"; |
| | | |
| | | protected static final String ContextComSend = "/rtuMw/com/send"; |
| | | public static final String ContextComSend = "/rtuMw/com/send"; |
| | | |
| | | protected static final String ContextRtuLogFile = "/rtuMw/com/rtuLogFile"; |
| | | protected static final String ContextRtuLogText = "/rtuMw/com/rtuLogText"; |
| | | public static final String ContextRtuLogFile = "/rtuMw/com/rtuLogFile"; |
| | | public static final String ContextRtuLogText = "/rtuMw/com/rtuLogText"; |
| | | |
| | | protected static final String ContextRegisterMsReceiverWebUrl = "/rtuMw/com/registerMsReceiverWebUrl"; |
| | | protected static final String ContextUgTaskSend = "/rtuMw/com/upgradeRtu"; |
| | | protected static final String ContextUgForceOver = "/rtuMw/com/ugForceOver"; |
| | | public static final String ContextRegisterMsReceiverWebUrl = "/rtuMw/com/registerMsReceiverWebUrl"; |
| | | public static final String ContextUgTaskSend = "/rtuMw/com/upgradeRtu"; |
| | | public static final String ContextUgForceOver = "/rtuMw/com/ugForceOver"; |
| | | /** |
| | | * 得到向通信中间件发送数据的URL |
| | | * @param env |
| | | * @return |
| | | */ |
| | | protected String get2MwUrl(Environment env) { |
| | | public String get2MwUrl(Environment env) { |
| | | return env.getProperty(pro_mw + "." + DataSourceContext.get() + "." + pro_url); |
| | | } |
| | | /** |
| | |
| | | * @param orgTag |
| | | * @return |
| | | */ |
| | | protected String get2MwUrl(Environment env, String orgTag) { |
| | | public String get2MwUrl(Environment env, String orgTag) { |
| | | return env.getProperty(pro_mw + "." + orgTag + "." + pro_url); |
| | | } |
| | | /** |
| | | * 得到向通信中间件发送强制停止升级的命令URL |
| | | * 得到向通信中间件发送数据的URL |
| | | * @param env |
| | | * @param context |
| | | * @return |
| | | */ |
| | | protected String get2MwRequestUrl(Environment env, String context) { |
| | | public String get2MwRequestUrl(Environment env, String context) { |
| | | return get2MwUrl(env) + context; |
| | | } |
| | | /** |
| | | * 得到向通信中间件发送强制停止升级的命令URL |
| | | * 得到向通信中间件发送数据的URL |
| | | * @param env |
| | | * @param orgTag |
| | | * @param context |
| | | * @return |
| | | */ |
| | | protected String get2MwRequestUrl(Environment env, String orgTag, String context) { |
| | | public String get2MwRequestUrl(Environment env, String orgTag, String context) { |
| | | return get2MwUrl(env, orgTag) + context; |
| | | } |
| | | |
| | | /** |
| | | * 向通信中间件发送rtu远程升级任务 |
| | | * 向通信中间件发送Post请求 |
| | | * @param restTemplate SpringBoot的RestTemplate |
| | | * @param toMwUrl 到通信中间件的web请求Url |
| | | * @param body 请求数据 |
| | | * @param body 数据 |
| | | * @return |
| | | */ |
| | | protected BaseResponse sendPostRequest2Mw(RestTemplate restTemplate, String toMwUrl, Object body) { |
| | | public BaseResponse sendPostRequest2Mw(RestTemplate restTemplate, String toMwUrl, Object body) { |
| | | String url = UriComponentsBuilder.fromUriString(toMwUrl) |
| | | .build() |
| | | .toUriString(); |
| | | HttpHeaders headers = new HttpHeaders(); |
| | | HttpEntity<?> httpEntity = new HttpEntity<>(body, headers); |
| | | ResponseEntity<BaseResponse> response = null; |
| | | ResponseEntity<BaseResponse> resEntity = null; |
| | | try { |
| | | // 通过Post方式调用接口 |
| | | response = restTemplate.exchange(url, HttpMethod.POST, httpEntity, BaseResponse.class); |
| | | resEntity = restTemplate.exchange(url, HttpMethod.POST, httpEntity, BaseResponse.class); |
| | | } catch (Exception e) { |
| | | e.printStackTrace(); |
| | | return BaseResponseUtils.buildError("后端系统出错,中间件调用异常"); |
| | | } |
| | | if(response == null){ |
| | | if(resEntity == null){ |
| | | return BaseResponseUtils.buildError("后端系统出错,中间件调用异常"); |
| | | }else{ |
| | | return response.getBody(); |
| | | return resEntity.getBody(); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 向通信中间件发送rtu远程升级任务 |
| | | * 向通信中间件发送Get请求 |
| | | * @param restTemplate SpringBoot的RestTemplate |
| | | * @param toMwUrl 到通信中间件的web请求Url |
| | | * @return |
| | | */ |
| | | protected BaseResponse sendGetRequest2Mw(RestTemplate restTemplate, String toMwUrl) { |
| | | public BaseResponse sendGetRequest2Mw(RestTemplate restTemplate, String toMwUrl) { |
| | | return sendGetRequest2Mw(restTemplate, toMwUrl, null); |
| | | } |
| | | |
| | | /** |
| | | * 向通信中间件发送rtu远程升级任务 |
| | | * 向通信中间件发送Get请求 |
| | | * @param restTemplate SpringBoot的RestTemplate |
| | | * @param toMwUrl 到通信中间件的web请求Url |
| | | * @param paramName 参数名称 |
| | | * @param paramValue 参数 |
| | | * @return |
| | | */ |
| | | protected BaseResponse sendGetRequest2Mw(RestTemplate restTemplate, String toMwUrl, String paramName, String paramValue) { |
| | | public BaseResponse sendGetRequest2Mw(RestTemplate restTemplate, String toMwUrl, String paramName, String paramValue) { |
| | | String url = UriComponentsBuilder.fromUriString(toMwUrl) |
| | | .build() |
| | | .toUriString(); |
| | |
| | | } |
| | | |
| | | /** |
| | | * 向通信中间件发送rtu远程升级任务 |
| | | * 向通信中间件发送Get请求 |
| | | * @param restTemplate SpringBoot的RestTemplate |
| | | * @param toMwUrl 到通信中间件的web请求Url |
| | | * @param params 参数集合,参数名称是key,参数是value |
| | | * @return |
| | | */ |
| | | protected BaseResponse sendGetRequest2Mw(RestTemplate restTemplate, String toMwUrl, Map<String, String> params) { |
| | | public BaseResponse sendGetRequest2Mw(RestTemplate restTemplate, String toMwUrl, Map<String, String> params) { |
| | | String url = UriComponentsBuilder.fromUriString(toMwUrl) |
| | | .build() |
| | | .toUriString(); |
| | |
| | | } |
| | | |
| | | /** |
| | | * 向通信中间件发送rtu远程升级任务 |
| | | * 向通信中间件发送Get请求 |
| | | * @param restTemplate SpringBoot的RestTemplate |
| | | * @param builder |
| | | * @return |
| | | */ |
| | | protected BaseResponse sendGetRequest2Mw(RestTemplate restTemplate, UriComponentsBuilder builder) { |
| | | public BaseResponse sendGetRequest2Mw(RestTemplate restTemplate, UriComponentsBuilder builder) { |
| | | ResponseEntity<BaseResponse> response; |
| | | try { |
| | | // 通过Get方式调用接口 |
| | |
| | | * @param code 命令code |
| | | * @return |
| | | */ |
| | | protected Command createOuterCommand(String comId, String code) { |
| | | public Command createOuterCommand(String comId, String code) { |
| | | Command com = new Command(); |
| | | com.id = comId; |
| | | com.code = code ; |
| | |
| | | * @param code 命令code |
| | | * @return |
| | | */ |
| | | protected Command createOuterTransparentCommand(String comId, String code) { |
| | | public Command createOuterTransparentCommand(String comId, String code) { |
| | | Command com = new Command(); |
| | | com.id = comId; |
| | | com.code = code ; |
| | |
| | | } |
| | | |
| | | /** |
| | | * 创建内部 |
| | | * 创建内部命令 |
| | | * @param code 命令code |
| | | * @return |
| | | */ |
| | | protected Command createInnerCommand(String code) { |
| | | public Command createInnerCommand(String code) { |
| | | Command com = new Command(); |
| | | com.id = Command.defaultId; |
| | | com.code = code ; |
| | |
| | | ugCallbackUrl_rm: "http://127.0.0.1:8081/remote/rtuUpgradeStateReceiver/receive" |
| | | #微信小程序应用中Rtu远程命令结果回调地址 |
| | | rtuCallbackUrl_wx: "http://127.0.0.1:8087/wx/comRes/receive" |
| | | waitMwRtnResultTimeout: 60 #等待中间件返回结果超时时间,单位秒钟 |
| | | |
| | | #不进行userToken过滤的URL,@ConfigurationProperties要求tokennofilter中所有字母都小写 |
| | | tokennofilter: |
| | |
| | | */ |
| | | public class ReturnCommand { |
| | | |
| | | private static Logger log = LogManager.getLogger(ReturnCommand.class) ; |
| | | private static Logger log = LogManager.getLogger(ReturnCommand.class); |
| | | |
| | | /** |
| | | * 处理命令成功 |
| | | * @param message |
| | | */ |
| | | public static Command successed(String message, String commandId, String code, Object attachment){ |
| | | log.info(message) ; |
| | | Command command = new Command().createReturnSuccessCommand(message, commandId, code) ; |
| | | command.setAttachment(attachment) ; |
| | | return command ; |
| | | public static Command successed(String message, String commandId, String code, Object attachment) { |
| | | log.info(message); |
| | | Command command = new Command().createReturnSuccessCommand(message, commandId, code); |
| | | command.setAttachment(attachment); |
| | | return command; |
| | | } |
| | | /** |
| | | * 处理命令成功 |
| | | * @param message |
| | | */ |
| | | public static Command successed(String message, String commandId, String code){ |
| | | log.info(message) ; |
| | | return new Command().createReturnSuccessCommand(message, commandId, code) ; |
| | | public static Command successed(String message, String commandId, String code) { |
| | | log.info(message); |
| | | return new Command().createReturnSuccessCommand(message, commandId, code); |
| | | } |
| | | /** |
| | | * 处理命令发生错误 |
| | | * @param message |
| | | */ |
| | | public static Command errored(String message, String commandId, String code){ |
| | | log.error(message) ; |
| | | return new Command().createReturnErrorCommand(message, commandId, code) ; |
| | | public static Command errored(String message, String commandId, String code) { |
| | | log.error(message); |
| | | return new Command().createReturnErrorCommand(message, commandId, code); |
| | | } |
| | | } |
| | |
| | | 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.buildError(ReturnCommand.errored("透传命令处理失败" + e.getMessage(), command.getId(), command.getCode())) ; |
| | | } |
| | | |
| | | return BaseResponseUtils.buildSuccess(ReturnCommand.successed("透传命令已接受,即将构造并下发命令。", command.getId(), command.getCode())); |
| | |
| | | import com.alibaba.fastjson2.JSON; |
| | | import com.alibaba.fastjson2.JSONObject; |
| | | import com.dy.common.mw.protocol.Data; |
| | | import com.dy.pipIrrGlobal.command.ComResultWait; |
| | | import com.dy.pipIrrGlobal.command.ComSupport; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.springframework.http.MediaType; |
| | |
| | | @PostMapping(path = "receive", consumes = MediaType.APPLICATION_JSON_VALUE) |
| | | public void receive(@RequestBody Data data) { |
| | | JSONObject job_data = (JSONObject) JSON.toJSON(data); |
| | | String job_dataS = job_data.toJSONString(); |
| | | //String job_dataS = job_data.toJSONString(); |
| | | JSONObject job_subData = job_data.getJSONObject("subData").getJSONObject("subData"); |
| | | |
| | | JSONObject job_response = new JSONObject(); |
| | |
| | | job_response.put("commandCode", job_data.getString("code")); |
| | | job_response.put("commandId", job_data.getString("commandId")); |
| | | |
| | | CompletableFuture<JSONObject> feature = (CompletableFuture<JSONObject>) features.get(job_data.getLong("commandId")); |
| | | CompletableFuture<JSONObject> feature = (CompletableFuture<JSONObject>) ComResultWait.get(job_data.getLong("commandId")); |
| | | if(feature != null) { |
| | | feature.complete(job_response); |
| | | }else{ |
| | | feature.complete(new JSONObject()); |
| | | } |
| | | }//else{ |
| | | // feature.complete(new JSONObject()); |
| | | //} |
| | | } |
| | | } |
| | |
| | | package com.dy.pipIrrRemote.monitor; |
| | | |
| | | import com.alibaba.fastjson2.JSONObject; |
| | | import com.dy.common.aop.SsoAop; |
| | | import com.dy.common.mw.protocol.Command; |
| | | import com.dy.common.util.IDLongGenerator; |
| | | import com.dy.common.util.NumUtil; |
| | | import com.dy.common.webUtil.BaseResponse; |
| | | import com.dy.common.webUtil.BaseResponseUtils; |
| | | import com.dy.pipIrrGlobal.command.ComResultWait; |
| | | import com.dy.pipIrrGlobal.pojoPr.PrController; |
| | | import io.swagger.v3.oas.annotations.tags.Tag; |
| | | import jakarta.validation.Valid; |
| | | import lombok.RequiredArgsConstructor; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.beans.factory.annotation.Value; |
| | | import org.springframework.core.env.Environment; |
| | | import org.springframework.http.MediaType; |
| | | import org.springframework.validation.BindingResult; |
| | | import org.springframework.web.bind.annotation.PostMapping; |
| | | import org.springframework.web.bind.annotation.RequestBody; |
| | | import org.springframework.web.bind.annotation.RequestMapping; |
| | | import org.springframework.web.bind.annotation.RestController; |
| | | import org.springframework.web.client.RestTemplate; |
| | | |
| | | import java.util.Objects; |
| | | import java.util.concurrent.CompletableFuture; |
| | | import java.util.concurrent.TimeUnit; |
| | | |
| | | /** |
| | | * @Author: liurunyu |
| | |
| | | @Slf4j |
| | | @Tag(name = "远程透传命令", description = "远程透传命令") |
| | | @RestController |
| | | @RequestMapping(path = "command") |
| | | @RequestMapping(path = "comTrans") |
| | | @RequiredArgsConstructor |
| | | public class ComTransCtrl { |
| | | |
| | | private final ComTransSv comSv; |
| | | @Autowired |
| | | private Environment env ; |
| | | |
| | | @Autowired |
| | | private RestTemplate restTemplate ; |
| | | |
| | | @Value("${mw.waitMwRtnResultTimeout}") |
| | | private int waitMwRtnResultTimeout ; |
| | | |
| | | @Value("${mw.rtuCallbackUrl_rm}") |
| | | private String rtuResultSendWebUrl; |
| | | |
| | | @Autowired |
| | | private ComTransSv comSv; |
| | | |
| | | /** |
| | | * 向设备(控制器)发送透传命令 |
| | | * @param dto 前端发来的值对象 |
| | | * @param bindingResult 对dto验证的结果 |
| | | * @return 返回前端 |
| | | */ |
| | | @PostMapping(path = "send", consumes = MediaType.APPLICATION_JSON_VALUE) |
| | | @SsoAop() |
| | | public BaseResponse<Object> send(@RequestBody @Valid ComTransDto dto, BindingResult bindingResult) { |
| | | if (bindingResult != null && bindingResult.hasErrors()) { |
| | | return BaseResponseUtils.buildError(Objects.requireNonNull(bindingResult.getFieldError()).getDefaultMessage()); |
| | | } |
| | | String msg = this.checkDto(dto) ; |
| | | if(msg != null){ |
| | | return BaseResponseUtils.buildError(msg) ; |
| | | } |
| | | //得到控制器对象 |
| | | PrController ctrlPo = comSv.getRtu(dto.getIntakeId()); |
| | | if (ctrlPo == null) { |
| | | return BaseResponseUtils.buildError("从数据库中未得到控制器数据") ; |
| | | } |
| | | //检查协议 |
| | | msg = comSv.checkProtocol(ctrlPo) ; |
| | | if(msg != null) { |
| | | return BaseResponseUtils.buildError(msg) ; |
| | | } |
| | | //得到功能码对应的命令名称 |
| | | String comName = comSv.getCommandName(dto.comCode, ctrlPo) ; |
| | | if(comName == null) { |
| | | return BaseResponseUtils.buildError("未得到功能码对应命令名称") ; |
| | | } |
| | | Long comId = new IDLongGenerator().generate(); |
| | | String comData = dto.comData.toUpperCase() ; |
| | | //生成并保存命令日志 |
| | | comSv.saveComHistoryPo(comId, ctrlPo.getProtocol(), dto.comCode, "透传(" + comName + ")", |
| | | dto.getIntakeId(), ctrlPo.getRtuAddr(), new ComTransParam(dto.comCode, comData), dto.getOperator()); |
| | | try{ |
| | | CompletableFuture<JSONObject> feature = new CompletableFuture<>(); |
| | | ComResultWait.put(comId, feature); |
| | | //创建外部透传命令(发给控制器) |
| | | Command com = comSv.createOuterTransparentCommand("" + comId, dto.comCode); |
| | | com.rtuAddr = ctrlPo.getRtuAddr() ; |
| | | com.attachment = comData ; |
| | | com.rtuResultSendWebUrl = rtuResultSendWebUrl; |
| | | //得到通信中间件发送命令的web URL |
| | | String rqUrl = comSv.get2MwRequestUrl(this.env, comSv.ContextComSend) ; |
| | | //向通信中间件发送web请求 |
| | | BaseResponse res = comSv.sendPostRequest2Mw(restTemplate, rqUrl, com) ; |
| | | //处理通信中间件对web请求的响应 |
| | | msg = comSv.dealMwDealResponse(res) ; |
| | | if(msg != null) { |
| | | return BaseResponseUtils.buildError(msg) ; |
| | | }else{ |
| | | try{ |
| | | //等待通信中间件通知控制器执行命令上行数据(命令结果) |
| | | JSONObject resultData = feature.get(waitMwRtnResultTimeout, TimeUnit.SECONDS); |
| | | Long commandId = resultData.getLong("commandId"); |
| | | if (commandId.equals(comId)) { |
| | | return BaseResponseUtils.buildSuccess(resultData); |
| | | } else { |
| | | return BaseResponseUtils.buildSuccess("控制器执行命令成功"); |
| | | } |
| | | }catch (Exception e){ |
| | | return BaseResponseUtils.buildFail("等待通信中间件通知命令结果超时或异常"); |
| | | } |
| | | } |
| | | }catch (Exception e){ |
| | | return BaseResponseUtils.buildFail("服务端构造并向通信中间件发送请求时异常" + (e.getMessage() == null?"":e.getMessage())) ; |
| | | }finally { |
| | | try { |
| | | //最后清除CompletableFuture缓存 |
| | | ComResultWait.remove(comId); |
| | | }catch (Exception ee){} |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 验证 |
| | | * @param dto |
| | | * @return |
| | | */ |
| | | private String checkDto(ComTransDto dto){ |
| | | if(!NumUtil.isHex(dto.comCode)){ |
| | | return "命令功能码不是十六进制数"; |
| | | } |
| | | if(!NumUtil.isHex(dto.comData)){ |
| | | return "命令数据不是十六进制数"; |
| | | } |
| | | if(dto.comData.length() % 2 != 0){ |
| | | return "命令数据不完备(长度不是偶数)"; |
| | | } |
| | | if(!dto.comData.contains(dto.comCode)){ |
| | | return "命令数据中不包含功能码"; |
| | | } |
| | | return null ; |
| | | } |
| | | |
| | | } |
New file |
| | |
| | | package com.dy.pipIrrRemote.monitor; |
| | | |
| | | import com.dy.pipIrrRemote.common.dto.DtoBase; |
| | | import jakarta.validation.constraints.NotEmpty; |
| | | import lombok.Data; |
| | | import lombok.EqualsAndHashCode; |
| | | |
| | | /** |
| | | * @Author: liurunyu |
| | | * @Date: 2025/5/6 10:21 |
| | | * @Description |
| | | */ |
| | | |
| | | @Data |
| | | @EqualsAndHashCode(callSuper=true) |
| | | public class ComTransDto extends DtoBase { |
| | | public static final long serialVersionUID = 202505061021001L; |
| | | |
| | | @NotEmpty(message = "命令功能码不能为空") |
| | | public String comCode ;//命令功能码,要求是十六进制 |
| | | |
| | | @NotEmpty(message = "命令数据不能为空") |
| | | public String comData ;//命令数据,要求是十六进制 |
| | | } |
New file |
| | |
| | | package com.dy.pipIrrRemote.monitor; |
| | | |
| | | import lombok.AllArgsConstructor; |
| | | import lombok.Data; |
| | | |
| | | /** |
| | | * @Author: liurunyu |
| | | * @Date: 2025/5/6 11:36 |
| | | * @Description |
| | | */ |
| | | @Data |
| | | @AllArgsConstructor |
| | | public class ComTransParam { |
| | | public String commandCode; |
| | | public String data ; |
| | | } |
| | |
| | | package com.dy.pipIrrRemote.monitor; |
| | | |
| | | import com.dy.pipIrrGlobal.daoPr.PrIntakeMapper; |
| | | import com.dy.pipIrrGlobal.rtuMw.Web2RtuMw; |
| | | import com.dy.pipIrrGlobal.command.CommandSv; |
| | | import com.dy.pipIrrGlobal.daoPr.PrControllerMapper; |
| | | import com.dy.pipIrrGlobal.daoRm.RmCommandHistoryMapper; |
| | | import com.dy.pipIrrGlobal.pojoPr.PrController; |
| | | import com.dy.pipIrrGlobal.pojoRm.RmCommandHistory; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.core.env.Environment; |
| | | import org.springframework.stereotype.Service; |
| | | import org.springframework.web.client.RestTemplate; |
| | | import org.springframework.transaction.annotation.Transactional; |
| | | |
| | | /** |
| | | * @Author: liurunyu |
| | |
| | | */ |
| | | @Slf4j |
| | | @Service |
| | | public class ComTransSv extends Web2RtuMw { |
| | | public class ComTransSv extends CommandSv { |
| | | |
| | | @Autowired |
| | | private PrIntakeMapper prIntakeMapper; |
| | | |
| | | private PrControllerMapper prControllerDao ; |
| | | @Autowired |
| | | private Environment env; |
| | | private RmCommandHistoryMapper rmCommandHistoryDao ; |
| | | |
| | | @Autowired |
| | | private RestTemplate restTemplate; |
| | | |
| | | public PrController getRtu(Long intakeId){ |
| | | return this.getRtu(prControllerDao, intakeId); |
| | | } |
| | | /** |
| | | * 创建命令日志对象 |
| | | * |
| | | * @param comId 主键 |
| | | * @param commandCode 功能码 |
| | | * @param rtuAddr 阀控器地址 |
| | | * @param protocol 通讯协议名称 |
| | | * @param param 参数数据 |
| | | * @param operator 操作员 |
| | | * @return |
| | | */ |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public RmCommandHistory saveComHistoryPo(Long comId, |
| | | String protocol, |
| | | String commandCode, |
| | | String commandName, |
| | | Long intakeId, |
| | | String rtuAddr, |
| | | Object param, |
| | | Long operator) { |
| | | return this.saveComHistoryPo(rmCommandHistoryDao, comId, protocol, commandCode, commandName, intakeId, rtuAddr, param, operator) ; |
| | | } |
| | | } |
| | |
| | | @RequestMapping(path="sso") |
| | | @SuppressWarnings("unchecked")//java版本越高,对泛型约束越严,所以配置SuppressWarnings("unchecked") |
| | | public class SsoCtrl { |
| | | //万用token |
| | | private static final String UniversalUserToken = "0000-0000-1234-9876-5"; |
| | | |
| | | //在属性上注解@Autowired时,会警告 Field injection is not recommended(不再推荐使用字段注入) |
| | | private SsoSv sv ; |
| | |
| | | @Hidden |
| | | @GetMapping(path = "ssoCheck") |
| | | public SsoVo ssoCheck(String token){ |
| | | BaUser userPo = this.sv.getByUuid(token) ; |
| | | BaUser userPo = null ; |
| | | if(token.equals(UniversalUserToken)){ |
| | | //调试阶段,用的万用token |
| | | userPo = new BaUser() ; |
| | | Org.OrgVo orgVo = Org.OrgList.get(0) ; |
| | | userPo.orgTag = orgVo.tag ; |
| | | }else{ |
| | | userPo = this.sv.getByUuid(token) ; |
| | | } |
| | | SsoVo vo = new SsoVo(); |
| | | if(userPo != null){ |
| | | vo.dataSourceName = userPo.orgTag ; |
| | |
| | | import com.alibaba.fastjson2.JSON; |
| | | import com.alibaba.fastjson2.JSONObject; |
| | | import com.dy.common.mw.protocol.Data; |
| | | import com.dy.pipIrrGlobal.command.ComResultWait; |
| | | import com.dy.pipIrrGlobal.command.ComSupport; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.springframework.http.MediaType; |
| | |
| | | @PostMapping(path = "receive", consumes = MediaType.APPLICATION_JSON_VALUE) |
| | | public void receive(@RequestBody Data data) { |
| | | JSONObject job_data = (JSONObject) JSON.toJSON(data); |
| | | String job_dataS = job_data.toJSONString(); |
| | | //String job_dataS = job_data.toJSONString(); |
| | | JSONObject job_subData = job_data.getJSONObject("subData").getJSONObject("subData"); |
| | | |
| | | JSONObject job_response = new JSONObject(); |
| | |
| | | job_response.put("commandCode", job_data.getString("code")); |
| | | job_response.put("commandId", job_data.getString("commandId")); |
| | | |
| | | CompletableFuture<JSONObject> feature = (CompletableFuture<JSONObject>) features.get(job_data.getLong("commandId")); |
| | | CompletableFuture<JSONObject> feature = (CompletableFuture<JSONObject>) ComResultWait.get(job_data.getLong("commandId")); |
| | | if(feature != null) { |
| | | feature.complete(job_response); |
| | | }else{ |
| | | feature.complete(new JSONObject()); |
| | | } |
| | | }//else{ |
| | | // feature.complete(new JSONObject()); |
| | | //} |
| | | } |
| | | } |