| package com.dy.pipIrrRemote.monitor.p202404V201.cd35; | 
|   | 
| import com.alibaba.fastjson2.JSON; | 
| import com.alibaba.fastjson2.JSONObject; | 
| import com.dy.common.aop.SsoAop; | 
| import com.dy.common.mw.protocol.Command; | 
| import com.dy.common.mw.protocol.p206V202404.upVos.DataCd92_A2Vo; | 
| import com.dy.common.util.Callback; | 
| import com.dy.common.webUtil.BaseResponse; | 
| import com.dy.common.webUtil.BaseResponseUtils; | 
| import com.dy.pipIrrGlobal.pojoRm.RmCommandOpen; | 
| import com.dy.pipIrrGlobal.voSe.VoVirtualCard; | 
| import com.dy.pipIrrRemote.common.dto.DtoBase; | 
| import com.dy.pipIrrRemote.monitor.common.ComCtrl; | 
| import io.swagger.v3.oas.annotations.tags.Tag; | 
| import jakarta.validation.Valid; | 
| import lombok.RequiredArgsConstructor; | 
| import lombok.extern.slf4j.Slf4j; | 
| import org.apache.commons.lang3.RandomStringUtils; | 
| import org.springframework.beans.factory.annotation.Autowired; | 
| import org.springframework.context.annotation.Scope; | 
| 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 java.util.Date; | 
|   | 
| /** | 
|  * @Author: liurunyu | 
|  * @Date: 2025/6/30 08:30 | 
|  * @Description | 
|  */ | 
| @Slf4j | 
| @Tag(name = "远程命令", description = "APP端远程定时开启水泵/阀门") | 
| @RestController("p202404V201Cd35Ctrl") | 
| @RequestMapping(path = "p202404V201/cd35") | 
| @RequiredArgsConstructor | 
| @Scope("prototype") //因为有对象类属性,所以采用原型模式,每次请求新建一个实例对象 | 
| public class CdCtrl extends ComCtrl { | 
|   | 
|     private static final String RtuSuccessMsg = "控制器接收并执行命令成功,无返回数据"; | 
|   | 
|     private static final String ComCode = "35" ; | 
|   | 
|     private static final Double MaxRemainMoney = com.dy.pipIrrRemote.monitor.p202404V201.cd92.CdCtrl.MaxRemainMoney;//协议支持的剩余金额最大值 | 
|   | 
|     @Autowired | 
|     private CdSv sv ; | 
|     /** | 
|      * 向设备(控制器)发送命令 | 
|      * @param dto 前端发来的值对象 | 
|      * @param bindingResult 对dto验证的结果 | 
|      * @return 返回前端 | 
|      */ | 
|     @PostMapping(path = "send", consumes = MediaType.APPLICATION_JSON_VALUE) | 
|     @SsoAop() | 
|     public BaseResponse<Object> send(@RequestBody @Valid CdDto dto, BindingResult bindingResult) { | 
|         BaseResponse<Object> res ; | 
|         //发送命令前-1:验证 | 
|         res = super.pre1(sv, ComCode, dto, bindingResult); | 
|         if(res == null) { | 
|             //发送命令前-2:获得数据 | 
|             res = super.pre2(sv, ComCode, dto, bindingResult); | 
|             if (res == null) { | 
|                 if(dto.vtCardId == null || "".equals(dto.vtCardId.trim())){ | 
|                     Long vtId = sv.selectVcIdByIntakeId(dto.getIntakeId()) ; | 
|                     if(vtId == null) { | 
|                         return BaseResponseUtils.buildErrorMsg("请选择一张虚拟卡"); | 
|                     }else{ | 
|                         dto.vtCardId = vtId.toString() ; | 
|                     } | 
|                 } | 
|                 VoVirtualCard vcPo = sv.selectClientVtCardById(Long.parseLong(dto.vtCardId.trim())) ; | 
|                 if(vcPo == null){ | 
|                     return BaseResponseUtils.buildErrorMsg("服务端出错,未得到农户虚拟卡") ; | 
|                 } | 
|                 if(vcPo.getInUse().booleanValue()){ | 
|                     return BaseResponseUtils.buildErrorMsg("农户该虚拟卡已经被占用,不能再应用其开阀") ; | 
|                 } | 
|                 if(vcPo.getMoney() <= 0.0){ | 
|                     return BaseResponseUtils.buildErrorMsg("农户该虚拟卡中剩余金额为0,不能再应用其开阀") ; | 
|                 } | 
|                 if(vcPo.getMoney() >= MaxRemainMoney){ | 
|                     return BaseResponseUtils.buildErrorMsg("农户该虚拟卡中剩余金额大于协议支持的最大值" + MaxRemainMoney + ",不能再应用其开阀") ; | 
|                 } | 
|                 Double waterPrice = sv.selectWaterPrice() ; | 
|                 if(waterPrice == null){ | 
|                     return BaseResponseUtils.buildErrorMsg("服务端出错,未得到水价") ; | 
|                 } | 
|                 String orderNo = RandomStringUtils.randomNumeric(16) ; | 
|                 CdParam comParam = CdParam.builder().commandCode(ComCode).projectNo(projectNo).controllerType(controllerType) | 
|                         .icCardNo("" + vcPo.getVcNum())//用户卡序列号(17位数字)(6字节BCD,2字节HEX) | 
|                         .waterRemain(0.0)//用户剩余水量, 两个小数点, 单位m3, 0~99999999.99 | 
|                         .moneyRemain(vcPo.getMoney())//用户剩余水量, 两个小数点, 单位m3, 0~99999999.99 | 
|                         .waterPrice(waterPrice)//水量单价 单位:元, 2个小数点 | 
|                         .elePrice(0.0)//电量单价 单位:元, 2个小数点 | 
|                         .orderNo(orderNo)//订单号(16位数字) | 
|                         .minutes(dto.minutes)//用水时长(0~9999分钟) | 
|                         .build(); | 
|                 //发送命令前-3:保存命令日志 | 
|                 res = super.pre3(sv, dto.getIntakeId(), dto.getOperator(), ComCode, comParam); | 
|                 if (res == null) { | 
|                     //发送命令前-4:准备Feature | 
|                     super.pre4(); | 
|                     try { | 
|                         //创建外部命令(发给控制器) | 
|                         Command com = sv.createOuterCommand(ctrlPo.getRtuAddr(), "" + comId, ComCode); | 
|                         com.rtuResultSendWebUrl = rtuResultSendWebUrl; | 
|                         com.param = comParam; | 
|                         //发送命令 | 
|                         res = super.doSend(sv, com); | 
|                         if (res == null) { | 
|                             //发送命令后 | 
|                             res = super.after(ComCode, new Callback() { | 
|                                 @Override | 
|                                 public void call(Object obj) { | 
|                                     Boolean success = (Boolean) obj; | 
|                                     if(success){ | 
|                                         // 添加常用取水口或更新使用信息 | 
|                                         sv.addOrUpdateOftenUseIntake(dto.getOperator(), dto.getIntakeId()) ; | 
|                                         //开阀成功,虚拟卡记录上标记已被占用 | 
|                                         sv.setVcUsed(vcPo.getId(), dto.getIntakeId()); | 
|                                         //记录开阀命令,以备远程关阀 | 
|                                         RmCommandOpen comOpen = sv.getCommandOpen(dto.getIntakeId()); | 
|                                         if(comOpen == null){ | 
|                                             RmCommandOpen po = newRmCommandOpen(comId, ctrlPo.getProtocol(), ComCode, comName, dto.getIntakeId(), ctrlPo.getRtuAddr(), vcPo.getVcNum(), orderNo, dto.getOperator()) ; | 
|                                             sv.saveCommandOpen(po); | 
|                                         }else{ | 
|                                             setRmCommandOpen(comOpen, comId, ctrlPo.getProtocol(), ComCode, comName, dto.getIntakeId(), ctrlPo.getRtuAddr(), vcPo.getVcNum(), orderNo, dto.getOperator()) ; | 
|                                             sv.updateCommandOpen(comOpen); | 
|                                         } | 
|                                     } | 
|                                 } | 
|                                 @Override | 
|                                 public void call(Object... objs) { | 
|                                 } | 
|                                 @Override | 
|                                 public void exception(Exception e) { | 
|                                 } | 
|                             }); | 
|                         } | 
|                     } catch (Exception e) { | 
|                         res = BaseResponseUtils.buildFail("服务端构造并向通信中间件发送请求时异常" + (e.getMessage() == null ? "" : e.getMessage())); | 
|                     } finally { | 
|                         //最终 | 
|                         super.end(); | 
|                     } | 
|                 } | 
|             } | 
|         } | 
|         return res ; | 
|     } | 
|   | 
|     @Override | 
|     protected String checkDto(DtoBase dto) { | 
|         return null; | 
|     } | 
|   | 
|     @Override | 
|     protected String dealComResult(String code, JSONObject resultData, Callback callback){ | 
|         String msg; | 
|         if(resultData != null){ | 
|             JSONObject codeData = resultData.getJSONObject("data") ; | 
|             if(codeData == null){ | 
|                 msg = RtuSuccessMsg ; | 
|             }else { | 
|                 String json = codeData.toJSONString(); | 
|                 DataCd92_A2Vo cvo = JSON.parseObject(json, DataCd92_A2Vo.class) ; | 
|                 if(cvo != null){ | 
|                     if(callback != null){ | 
|                         if(cvo.opResult != null && cvo.opResult.byteValue() == (byte)1){ | 
|                             callback.call(true);//开阀成功 | 
|                         }else{ | 
|                             callback.call(false);//开阀失败 | 
|                         } | 
|                     } | 
|                     msg = cvo.toStr(false) ; | 
|                 }else{ | 
|                     msg = RtuSuccessMsg ; | 
|                 } | 
|             } | 
|         }else{ | 
|             msg = RtuSuccessMsg ; | 
|         } | 
|         return msg; | 
|     } | 
|   | 
|     private RmCommandOpen newRmCommandOpen(Long comId, | 
|                                            String protocol, | 
|                                            String comCode, | 
|                                            String comName, | 
|                                            Long intakeId, | 
|                                            String rtuAddr, | 
|                                            Long vcNum, | 
|                                            String orderNo, | 
|                                            Long operator){ | 
|         RmCommandOpen po = new RmCommandOpen() ; | 
|         this.setRmCommandOpen(po, comId, protocol, comCode, comName, intakeId, rtuAddr, vcNum, orderNo, operator); | 
|         return po ; | 
|     } | 
|     private void setRmCommandOpen(RmCommandOpen po, | 
|                                   Long comId, | 
|                                   String protocol, | 
|                                   String comCode, | 
|                                   String comName, | 
|                                   Long intakeId, | 
|                                   String rtuAddr, | 
|                                   Long vcNum, | 
|                                   String orderNo, | 
|                                   Long operator){ | 
|         po.comId = comId ; | 
|         po.protocol = protocol ; | 
|         po.commandCode = comCode ; | 
|         po.commandName = comName ; | 
|         po.intakeId = intakeId ; | 
|         po.rtuAddr = rtuAddr ; | 
|         po.vcNum = vcNum ; | 
|         po.orderNo = orderNo ; | 
|         po.operator = operator ; | 
|         po.sendTime = new Date() ; | 
|     } | 
| } |