liurunyu
2025-07-01 f4040d9bc0426f9075f68a2e26ee8732ab714ac1
remote模块,增加表阀一体机协议的10、21、35、36、37、38命令功能
20个文件已添加
3个文件已修改
1680 ■■■■■ 已修改文件
pipIrr-platform/pipIrr-web/pipIrr-web-remote/src/main/java/com/dy/pipIrrRemote/monitor/p202404V201/cd10/CdCtrl.java 130 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pipIrr-platform/pipIrr-web/pipIrr-web-remote/src/main/java/com/dy/pipIrrRemote/monitor/p202404V201/cd10/CdDto.java 21 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pipIrr-platform/pipIrr-web/pipIrr-web-remote/src/main/java/com/dy/pipIrrRemote/monitor/p202404V201/cd10/CdParam.java 21 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pipIrr-platform/pipIrr-web/pipIrr-web-remote/src/main/java/com/dy/pipIrrRemote/monitor/p202404V201/cd10/CdSv.java 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pipIrr-platform/pipIrr-web/pipIrr-web-remote/src/main/java/com/dy/pipIrrRemote/monitor/p202404V201/cd21/CdDto.java 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pipIrr-platform/pipIrr-web/pipIrr-web-remote/src/main/java/com/dy/pipIrrRemote/monitor/p202404V201/cd35/CdCtrl.java 225 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pipIrr-platform/pipIrr-web/pipIrr-web-remote/src/main/java/com/dy/pipIrrRemote/monitor/p202404V201/cd35/CdDto.java 30 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pipIrr-platform/pipIrr-web/pipIrr-web-remote/src/main/java/com/dy/pipIrrRemote/monitor/p202404V201/cd35/CdParam.java 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pipIrr-platform/pipIrr-web/pipIrr-web-remote/src/main/java/com/dy/pipIrrRemote/monitor/p202404V201/cd35/CdSv.java 80 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pipIrr-platform/pipIrr-web/pipIrr-web-remote/src/main/java/com/dy/pipIrrRemote/monitor/p202404V201/cd36/CdCtrl.java 225 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pipIrr-platform/pipIrr-web/pipIrr-web-remote/src/main/java/com/dy/pipIrrRemote/monitor/p202404V201/cd36/CdDto.java 30 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pipIrr-platform/pipIrr-web/pipIrr-web-remote/src/main/java/com/dy/pipIrrRemote/monitor/p202404V201/cd36/CdParam.java 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pipIrr-platform/pipIrr-web/pipIrr-web-remote/src/main/java/com/dy/pipIrrRemote/monitor/p202404V201/cd36/CdSv.java 80 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pipIrr-platform/pipIrr-web/pipIrr-web-remote/src/main/java/com/dy/pipIrrRemote/monitor/p202404V201/cd37/CdCtrl.java 232 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pipIrr-platform/pipIrr-web/pipIrr-web-remote/src/main/java/com/dy/pipIrrRemote/monitor/p202404V201/cd37/CdDto.java 33 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pipIrr-platform/pipIrr-web/pipIrr-web-remote/src/main/java/com/dy/pipIrrRemote/monitor/p202404V201/cd37/CdParam.java 33 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pipIrr-platform/pipIrr-web/pipIrr-web-remote/src/main/java/com/dy/pipIrrRemote/monitor/p202404V201/cd37/CdSv.java 80 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pipIrr-platform/pipIrr-web/pipIrr-web-remote/src/main/java/com/dy/pipIrrRemote/monitor/p202404V201/cd38/CdCtrl.java 232 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pipIrr-platform/pipIrr-web/pipIrr-web-remote/src/main/java/com/dy/pipIrrRemote/monitor/p202404V201/cd38/CdDto.java 33 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pipIrr-platform/pipIrr-web/pipIrr-web-remote/src/main/java/com/dy/pipIrrRemote/monitor/p202404V201/cd38/CdParam.java 33 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pipIrr-platform/pipIrr-web/pipIrr-web-remote/src/main/java/com/dy/pipIrrRemote/monitor/p202404V201/cd38/CdSv.java 80 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pipIrr-platform/pipIrr-web/pipIrr-web-remote/src/main/java/com/dy/pipIrrRemote/monitor/p202404V201/cd92/CdCtrl.java 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pipIrr-platform/pipIrr-web/pipIrr-web-remote/src/main/java/com/dy/pipIrrRemote/monitor/p202404V201/cdA2/CdCtrl.java 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pipIrr-platform/pipIrr-web/pipIrr-web-remote/src/main/java/com/dy/pipIrrRemote/monitor/p202404V201/cd10/CdCtrl.java
New file
@@ -0,0 +1,130 @@
package com.dy.pipIrrRemote.monitor.p202404V201.cd10;
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.DataCdXyVo;
import com.dy.common.util.Callback;
import com.dy.common.util.IPUtils;
import com.dy.common.util.NumUtil;
import com.dy.common.webUtil.BaseResponse;
import com.dy.common.webUtil.BaseResponseUtils;
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.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;
/**
 * @Author: liurunyu
 * @Date: 2025/5/15 10:42
 * @Description
 */
@Slf4j
@Tag(name = "远程命令", description = "设置设备终端地址")
@RestController("p202404V201Cd10Ctrl")
@RequestMapping(path = "p202404V201/cd10")
@RequiredArgsConstructor
@Scope("prototype") //因为有对象类属性,所以采用原型模式,每次请求新建一个实例对象
public class CdCtrl extends ComCtrl {
    private static final String RtuSuccessMsg = "控制器接收并执行命令成功,无返回数据";
    private static final String ComCode = "10" ;
    @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) {
                //发送命令前-3:保存命令日志
                CdParam comParam = CdParam.builder().commandCode(ComCode).projectNo(projectNo).controllerType(controllerType)
                        .rtuNewAddr(dto.rtuNewAddr)//控制器新地址
                        .build();
                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, null);
                        }
                    } catch (Exception e) {
                        res = BaseResponseUtils.buildFail("服务端构造并向通信中间件发送请求时异常" + (e.getMessage() == null ? "" : e.getMessage()));
                    } finally {
                        //最终
                        super.end();
                    }
                }
            }
        }
        return res ;
    }
    @Override
    protected String checkDto(DtoBase dto) {
        if(dto != null){
            CdDto myo = (CdDto) dto ;
            //地址示例  37142501020100013
            if(!NumUtil.isPlusIntNumber(myo.rtuNewAddr)){
                return "控制器新地址不正确" ;
            }
            if(myo.rtuNewAddr.length() != 17 || myo.rtuNewAddr.startsWith("0")){
                return "控制器新地址不正确" ;
            }
        }
        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();
                DataCdXyVo cvo = JSON.parseObject(json, DataCdXyVo.class) ;
                if(cvo != null){
                    msg = cvo.toStr(false) ;
                }else{
                    msg = RtuSuccessMsg ;
                }
            }
        }else{
            msg = RtuSuccessMsg ;
        }
        return msg;
    }
}
pipIrr-platform/pipIrr-web/pipIrr-web-remote/src/main/java/com/dy/pipIrrRemote/monitor/p202404V201/cd10/CdDto.java
New file
@@ -0,0 +1,21 @@
package com.dy.pipIrrRemote.monitor.p202404V201.cd10;
import com.dy.pipIrrRemote.common.dto.DtoBase;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
 * @Author: liurunyu
 * @Date: 2025/5/15 10:42
 * @Description
 */
@Data
@EqualsAndHashCode(callSuper=true)
public class CdDto extends DtoBase {
    public static final long serialVersionUID = 202505151042001L;
    @NotEmpty(message = "控制器新地址不能为空")
    public String rtuNewAddr ;//控制器新地址
}
pipIrr-platform/pipIrr-web/pipIrr-web-remote/src/main/java/com/dy/pipIrrRemote/monitor/p202404V201/cd10/CdParam.java
New file
@@ -0,0 +1,21 @@
package com.dy.pipIrrRemote.monitor.p202404V201.cd10;
import com.dy.pipIrrRemote.monitor.common.CdParameter;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import lombok.experimental.SuperBuilder;
/**
 * @Author: liurunyu
 * @Date: 2025/5/15 10:42
 * @Description
 */
@Data
@ToString(callSuper = true)
@EqualsAndHashCode(callSuper = true)
@SuperBuilder
public class CdParam extends CdParameter {
    public Integer channel ;//IP通道号(取值范围 1、2).
    public String rtuNewAddr ;//控制器新地址
 }
pipIrr-platform/pipIrr-web/pipIrr-web-remote/src/main/java/com/dy/pipIrrRemote/monitor/p202404V201/cd10/CdSv.java
New file
@@ -0,0 +1,15 @@
package com.dy.pipIrrRemote.monitor.p202404V201.cd10;
import com.dy.pipIrrRemote.monitor.common.ComSv;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
/**
 * @Author: liurunyu
 * @Date: 2025/5/15 10:42
 * @Description
 */
@Slf4j
@Service("cd10Sv")
public class CdSv extends ComSv {
}
pipIrr-platform/pipIrr-web/pipIrr-web-remote/src/main/java/com/dy/pipIrrRemote/monitor/p202404V201/cd21/CdDto.java
@@ -1,6 +1,7 @@
package com.dy.pipIrrRemote.monitor.p202404V201.cd21;
import com.dy.pipIrrRemote.common.dto.DtoBase;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import lombok.EqualsAndHashCode;
@@ -17,7 +18,7 @@
    public static final long serialVersionUID = 202505151042001L;
    @NotNull(message = "IP通道号不能为空")
    public Integer channel ;//IP通道号(取值范围 1、2).
    @NotNull(message = "IP不能为空")
    @NotEmpty(message = "IP不能为空")
    public String ip ;//IP(例如 125.235.35.89)
    @NotNull(message = "端口号不能为空")
    public Integer port ;//端口号(0~65536)
pipIrr-platform/pipIrr-web/pipIrr-web-remote/src/main/java/com/dy/pipIrrRemote/monitor/p202404V201/cd35/CdCtrl.java
New file
@@ -0,0 +1,225 @@
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() ;
    }
}
pipIrr-platform/pipIrr-web/pipIrr-web-remote/src/main/java/com/dy/pipIrrRemote/monitor/p202404V201/cd35/CdDto.java
New file
@@ -0,0 +1,30 @@
package com.dy.pipIrrRemote.monitor.p202404V201.cd35;
import com.dy.pipIrrRemote.common.dto.DtoBase;
import jakarta.validation.constraints.Max;
import jakarta.validation.constraints.Min;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
 * @Author: liurunyu
 * @Date: 2025/6/30 08:30
 * @Description
 */
@Data
@EqualsAndHashCode(callSuper=true)
public class CdDto extends DtoBase {
    public static final long serialVersionUID = 202505130833001L;
    @NotEmpty(message = "用户虚拟卡不能为空")
    public String vtCardId ;//用户卡(虚拟卡)序列号(17位数字)(6字节BCD,2字节HEX)
    @NotNull(message = "用水时长不能为空")
    @Min(value = 1, message = "用水时长不能小于1")
    @Max(value = 9999, message = "用水时长不能大于9999")
    public Integer minutes ;//用水时长(0~9999分钟)
}
pipIrr-platform/pipIrr-web/pipIrr-web-remote/src/main/java/com/dy/pipIrrRemote/monitor/p202404V201/cd35/CdParam.java
New file
@@ -0,0 +1,26 @@
package com.dy.pipIrrRemote.monitor.p202404V201.cd35;
import com.dy.pipIrrRemote.monitor.common.CdParameter;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import lombok.experimental.SuperBuilder;
/**
 * @Author: liurunyu
 * @Date: 2025/6/30 08:30
 * @Description
 */
@Data
@ToString(callSuper = true)
@EqualsAndHashCode(callSuper = true)
@SuperBuilder
public class CdParam extends CdParameter {
    public String icCardNo ;//用户卡序列号(17位数字)(6字节BCD,2字节HEX)
    public Double waterRemain ;//用户剩余水量, 两个小数点, 单位m3, 0~99999999.99
    public Double moneyRemain ;//用户剩余金额, 两个小数点, 单位元, 0~999999.99
    public Double waterPrice ;//水量单价 单位:元, 2个小数点
    public Double elePrice ;//电量单价 单位:元, 2个小数点
    public String orderNo ;//订单号(16位数字)
    public Integer minutes ;//用水时长(0~9999分钟)
}
pipIrr-platform/pipIrr-web/pipIrr-web-remote/src/main/java/com/dy/pipIrrRemote/monitor/p202404V201/cd35/CdSv.java
New file
@@ -0,0 +1,80 @@
package com.dy.pipIrrRemote.monitor.p202404V201.cd35;
import com.dy.pipIrrGlobal.daoPr.PrIntakeVcMapper;
import com.dy.pipIrrGlobal.daoPr.PrWaterPriceMapper;
import com.dy.pipIrrGlobal.daoRm.RmCommandOpenMapper;
import com.dy.pipIrrGlobal.daoSe.SeVirtualCardMapper;
import com.dy.pipIrrGlobal.pojoRm.RmCommandOpen;
import com.dy.pipIrrGlobal.pojoSe.SeVirtualCard;
import com.dy.pipIrrGlobal.voSe.VoVirtualCard;
import com.dy.pipIrrRemote.monitor.common.ComSv;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.Date;
import java.util.List;
/**
 * @Author: liurunyu
 * @Date: 2025/6/30 08:30
 * @Description
 */
@Slf4j
@Service("cd35Sv")
public class CdSv extends ComSv {
    @Autowired
    protected SeVirtualCardMapper seVirtualCardDao ;
    @Autowired
    protected PrWaterPriceMapper prWaterPriceDao ;
    @Autowired
    protected PrIntakeVcMapper prIntakeVcDao ;
    @Autowired
    protected RmCommandOpenMapper rmCommandOpenDao ;
    public VoVirtualCard selectClientVtCardById(Long id){
        return seVirtualCardDao.getVcById(id) ;
    }
    public Double selectWaterPrice(){
        return prWaterPriceDao.getPrice() ;
    }
    /**
     * 根据取水口ID获取与之绑定虚拟卡ID
     * @param intakeId
     * @return
     */
    public Long selectVcIdByIntakeId(Long intakeId) {
        return prIntakeVcDao.getVcIdByIntakeId(intakeId);
    }
    /**
     * 设置虚拟卡被占用
     */
    @Transactional(rollbackFor = Exception.class)
    public void setVcUsed(Long id, Long intakeId){
        SeVirtualCard po = new SeVirtualCard() ;
        po.setId(id);
        po.setIntakeId(intakeId);
        po.setInUse((byte)1);
        po.setOpenTime(new Date());
        seVirtualCardDao.updateByPrimaryKeySelective(po);
    }
    public RmCommandOpen getCommandOpen(Long intakeId){
        List<RmCommandOpen> list = rmCommandOpenDao.selectByIntakeId(intakeId) ;
        if(list != null && list.size() > 0){
            return list.get(0) ;
        }
        return null ;
    }
    @Transactional(rollbackFor = Exception.class)
    public void saveCommandOpen(RmCommandOpen po){
        rmCommandOpenDao.insert(po) ;
    }
    @Transactional(rollbackFor = Exception.class)
    public void updateCommandOpen(RmCommandOpen po){
        rmCommandOpenDao.updateByPrimaryKeySelective(po) ;
    }
}
pipIrr-platform/pipIrr-web/pipIrr-web-remote/src/main/java/com/dy/pipIrrRemote/monitor/p202404V201/cd36/CdCtrl.java
New file
@@ -0,0 +1,225 @@
package com.dy.pipIrrRemote.monitor.p202404V201.cd36;
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 9:01
 * @Description
 */
@Slf4j
@Tag(name = "远程命令", description = "APP端远程定量开启水泵/阀门")
@RestController("p202404V201Cd36Ctrl")
@RequestMapping(path = "p202404V201/cd36")
@RequiredArgsConstructor
@Scope("prototype") //因为有对象类属性,所以采用原型模式,每次请求新建一个实例对象
public class CdCtrl extends ComCtrl {
    private static final String RtuSuccessMsg = "控制器接收并执行命令成功,无返回数据";
    private static final String ComCode = "36" ;
    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位数字)
                        .waterAmount(dto.waterAmount)//预用水量(0~9999 m3)
                        .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() ;
    }
}
pipIrr-platform/pipIrr-web/pipIrr-web-remote/src/main/java/com/dy/pipIrrRemote/monitor/p202404V201/cd36/CdDto.java
New file
@@ -0,0 +1,30 @@
package com.dy.pipIrrRemote.monitor.p202404V201.cd36;
import com.dy.pipIrrRemote.common.dto.DtoBase;
import jakarta.validation.constraints.Max;
import jakarta.validation.constraints.Min;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
 * @Author: liurunyu
 * @Date: 2025/6/30 9:01
 * @Description
 */
@Data
@EqualsAndHashCode(callSuper=true)
public class CdDto extends DtoBase {
    public static final long serialVersionUID = 202505130833001L;
    @NotEmpty(message = "用户虚拟卡不能为空")
    public String vtCardId ;//用户卡(虚拟卡)序列号(17位数字)(6字节BCD,2字节HEX)
    @NotNull(message = "用水量不能为空")
    @Min(value = 1, message = "用水量不能小于1")
    @Max(value = 9999, message = "用水量不能大于9999")
    public Integer waterAmount ;//预用水量(0~9999 m3)
}
pipIrr-platform/pipIrr-web/pipIrr-web-remote/src/main/java/com/dy/pipIrrRemote/monitor/p202404V201/cd36/CdParam.java
New file
@@ -0,0 +1,26 @@
package com.dy.pipIrrRemote.monitor.p202404V201.cd36;
import com.dy.pipIrrRemote.monitor.common.CdParameter;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import lombok.experimental.SuperBuilder;
/**
 * @Author: liurunyu
 * @Date: 2025/6/30 9:01
 * @Description
 */
@Data
@ToString(callSuper = true)
@EqualsAndHashCode(callSuper = true)
@SuperBuilder
public class CdParam extends CdParameter {
    public String icCardNo ;//用户卡序列号(17位数字)(6字节BCD,2字节HEX)
    public Double waterRemain ;//用户剩余水量, 两个小数点, 单位m3, 0~99999999.99
    public Double moneyRemain ;//用户剩余金额, 两个小数点, 单位元, 0~999999.99
    public Double waterPrice ;//水量单价 单位:元, 2个小数点
    public Double elePrice ;//电量单价 单位:元, 2个小数点
    public String orderNo ;//订单号(16位数字)
    public Integer waterAmount ;//预用水量(0~9999 m3)
}
pipIrr-platform/pipIrr-web/pipIrr-web-remote/src/main/java/com/dy/pipIrrRemote/monitor/p202404V201/cd36/CdSv.java
New file
@@ -0,0 +1,80 @@
package com.dy.pipIrrRemote.monitor.p202404V201.cd36;
import com.dy.pipIrrGlobal.daoPr.PrIntakeVcMapper;
import com.dy.pipIrrGlobal.daoPr.PrWaterPriceMapper;
import com.dy.pipIrrGlobal.daoRm.RmCommandOpenMapper;
import com.dy.pipIrrGlobal.daoSe.SeVirtualCardMapper;
import com.dy.pipIrrGlobal.pojoRm.RmCommandOpen;
import com.dy.pipIrrGlobal.pojoSe.SeVirtualCard;
import com.dy.pipIrrGlobal.voSe.VoVirtualCard;
import com.dy.pipIrrRemote.monitor.common.ComSv;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.Date;
import java.util.List;
/**
 * @Author: liurunyu
 * @Date: 2025/6/30 9:01
 * @Description
 */
@Slf4j
@Service("cd36Sv")
public class CdSv extends ComSv {
    @Autowired
    protected SeVirtualCardMapper seVirtualCardDao ;
    @Autowired
    protected PrWaterPriceMapper prWaterPriceDao ;
    @Autowired
    protected PrIntakeVcMapper prIntakeVcDao ;
    @Autowired
    protected RmCommandOpenMapper rmCommandOpenDao ;
    public VoVirtualCard selectClientVtCardById(Long id){
        return seVirtualCardDao.getVcById(id) ;
    }
    public Double selectWaterPrice(){
        return prWaterPriceDao.getPrice() ;
    }
    /**
     * 根据取水口ID获取与之绑定虚拟卡ID
     * @param intakeId
     * @return
     */
    public Long selectVcIdByIntakeId(Long intakeId) {
        return prIntakeVcDao.getVcIdByIntakeId(intakeId);
    }
    /**
     * 设置虚拟卡被占用
     */
    @Transactional(rollbackFor = Exception.class)
    public void setVcUsed(Long id, Long intakeId){
        SeVirtualCard po = new SeVirtualCard() ;
        po.setId(id);
        po.setIntakeId(intakeId);
        po.setInUse((byte)1);
        po.setOpenTime(new Date());
        seVirtualCardDao.updateByPrimaryKeySelective(po);
    }
    public RmCommandOpen getCommandOpen(Long intakeId){
        List<RmCommandOpen> list = rmCommandOpenDao.selectByIntakeId(intakeId) ;
        if(list != null && list.size() > 0){
            return list.get(0) ;
        }
        return null ;
    }
    @Transactional(rollbackFor = Exception.class)
    public void saveCommandOpen(RmCommandOpen po){
        rmCommandOpenDao.insert(po) ;
    }
    @Transactional(rollbackFor = Exception.class)
    public void updateCommandOpen(RmCommandOpen po){
        rmCommandOpenDao.updateByPrimaryKeySelective(po) ;
    }
}
pipIrr-platform/pipIrr-web/pipIrr-web-remote/src/main/java/com/dy/pipIrrRemote/monitor/p202404V201/cd37/CdCtrl.java
New file
@@ -0,0 +1,232 @@
package com.dy.pipIrrRemote.monitor.p202404V201.cd37;
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.util.DateTime;
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 9:30
 * @Description
 */
@Slf4j
@Tag(name = "远程命令", description = "APP端计划远程定时开启水泵/阀门")
@RestController("p202404V201Cd37Ctrl")
@RequestMapping(path = "p202404V201/cd37")
@RequiredArgsConstructor
@Scope("prototype") //因为有对象类属性,所以采用原型模式,每次请求新建一个实例对象
public class CdCtrl extends ComCtrl {
    private static final String RtuSuccessMsg = "控制器接收并执行命令成功,无返回数据";
    private static final String ComCode = "37" ;
    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) ;
                int[] ymdHms = DateTime.yyyy_MM_dd_HH_MM_SS_2_ymdhmsGroup(dto.ymdHms) ;
                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位数字)
                        .year(ymdHms[0])//年
                        .month(ymdHms[1])//月
                        .day(ymdHms[2])//日
                        .hour(ymdHms[3])//时
                        .minute(ymdHms[4])//分
                        .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() ;
    }
}
pipIrr-platform/pipIrr-web/pipIrr-web-remote/src/main/java/com/dy/pipIrrRemote/monitor/p202404V201/cd37/CdDto.java
New file
@@ -0,0 +1,33 @@
package com.dy.pipIrrRemote.monitor.p202404V201.cd37;
import com.dy.pipIrrRemote.common.dto.DtoBase;
import jakarta.validation.constraints.Max;
import jakarta.validation.constraints.Min;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
 * @Author: liurunyu
 * @Date: 2025/6/30 9:30
 * @Description
 */
@Data
@EqualsAndHashCode(callSuper=true)
public class CdDto extends DtoBase {
    public static final long serialVersionUID = 202505130833001L;
    @NotEmpty(message = "用户虚拟卡不能为空")
    public String vtCardId ;//用户卡(虚拟卡)序列号(17位数字)(6字节BCD,2字节HEX)
    @NotEmpty(message = "计划开阀时间不能为空")
    public String ymdHms ;//年月日时分秒(格式yyyy-MM-dd HH:mm:SS)
    @NotNull(message = "用水时长不能为空")
    @Min(value = 1, message = "用水时长不能小于1")
    @Max(value = 9999, message = "用水时长不能大于9999")
    public Integer minutes ;//用水时长(0~9999分钟)
}
pipIrr-platform/pipIrr-web/pipIrr-web-remote/src/main/java/com/dy/pipIrrRemote/monitor/p202404V201/cd37/CdParam.java
New file
@@ -0,0 +1,33 @@
package com.dy.pipIrrRemote.monitor.p202404V201.cd37;
import com.dy.pipIrrRemote.monitor.common.CdParameter;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import lombok.experimental.SuperBuilder;
/**
 * @Author: liurunyu
 * @Date: 2025/6/30 9:30
 * @Description
 */
@Data
@ToString(callSuper = true)
@EqualsAndHashCode(callSuper = true)
@SuperBuilder
public class CdParam extends CdParameter {
    public String icCardNo ;//用户卡序列号(17位数字)(6字节BCD,2字节HEX)
    public Double waterRemain ;//用户剩余水量, 两个小数点, 单位m3, 0~99999999.99
    public Double moneyRemain ;//用户剩余金额, 两个小数点, 单位元, 0~999999.99
    public Double waterPrice ;//水量单价 单位:元, 2个小数点
    public Double elePrice ;//电量单价 单位:元, 2个小数点
    public String orderNo ;//订单号(16位数字)
    public Integer year ; //计划开阀时间---年
    public Integer month ;//计划开阀时间---月
    public Integer day ;//计划开阀时间---日
    public Integer hour ;//计划开阀时间---时
    public Integer minute ;//计划开阀时间---分
    public Integer minutes ;//用水时长(0~9999分钟)
}
pipIrr-platform/pipIrr-web/pipIrr-web-remote/src/main/java/com/dy/pipIrrRemote/monitor/p202404V201/cd37/CdSv.java
New file
@@ -0,0 +1,80 @@
package com.dy.pipIrrRemote.monitor.p202404V201.cd37;
import com.dy.pipIrrGlobal.daoPr.PrIntakeVcMapper;
import com.dy.pipIrrGlobal.daoPr.PrWaterPriceMapper;
import com.dy.pipIrrGlobal.daoRm.RmCommandOpenMapper;
import com.dy.pipIrrGlobal.daoSe.SeVirtualCardMapper;
import com.dy.pipIrrGlobal.pojoRm.RmCommandOpen;
import com.dy.pipIrrGlobal.pojoSe.SeVirtualCard;
import com.dy.pipIrrGlobal.voSe.VoVirtualCard;
import com.dy.pipIrrRemote.monitor.common.ComSv;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.Date;
import java.util.List;
/**
 * @Author: liurunyu
 * @Date: 2025/6/30 9:30
 * @Description
 */
@Slf4j
@Service("cd37Sv")
public class CdSv extends ComSv {
    @Autowired
    protected SeVirtualCardMapper seVirtualCardDao ;
    @Autowired
    protected PrWaterPriceMapper prWaterPriceDao ;
    @Autowired
    protected PrIntakeVcMapper prIntakeVcDao ;
    @Autowired
    protected RmCommandOpenMapper rmCommandOpenDao ;
    public VoVirtualCard selectClientVtCardById(Long id){
        return seVirtualCardDao.getVcById(id) ;
    }
    public Double selectWaterPrice(){
        return prWaterPriceDao.getPrice() ;
    }
    /**
     * 根据取水口ID获取与之绑定虚拟卡ID
     * @param intakeId
     * @return
     */
    public Long selectVcIdByIntakeId(Long intakeId) {
        return prIntakeVcDao.getVcIdByIntakeId(intakeId);
    }
    /**
     * 设置虚拟卡被占用
     */
    @Transactional(rollbackFor = Exception.class)
    public void setVcUsed(Long id, Long intakeId){
        SeVirtualCard po = new SeVirtualCard() ;
        po.setId(id);
        po.setIntakeId(intakeId);
        po.setInUse((byte)1);
        po.setOpenTime(new Date());
        seVirtualCardDao.updateByPrimaryKeySelective(po);
    }
    public RmCommandOpen getCommandOpen(Long intakeId){
        List<RmCommandOpen> list = rmCommandOpenDao.selectByIntakeId(intakeId) ;
        if(list != null && list.size() > 0){
            return list.get(0) ;
        }
        return null ;
    }
    @Transactional(rollbackFor = Exception.class)
    public void saveCommandOpen(RmCommandOpen po){
        rmCommandOpenDao.insert(po) ;
    }
    @Transactional(rollbackFor = Exception.class)
    public void updateCommandOpen(RmCommandOpen po){
        rmCommandOpenDao.updateByPrimaryKeySelective(po) ;
    }
}
pipIrr-platform/pipIrr-web/pipIrr-web-remote/src/main/java/com/dy/pipIrrRemote/monitor/p202404V201/cd38/CdCtrl.java
New file
@@ -0,0 +1,232 @@
package com.dy.pipIrrRemote.monitor.p202404V201.cd38;
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.util.DateTime;
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 9:47
 * @Description
 */
@Slf4j
@Tag(name = "远程命令", description = "APP端远程计划定量开启水泵/阀门")
@RestController("p202404V201Cd38Ctrl")
@RequestMapping(path = "p202404V201/cd38")
@RequiredArgsConstructor
@Scope("prototype") //因为有对象类属性,所以采用原型模式,每次请求新建一个实例对象
public class CdCtrl extends ComCtrl {
    private static final String RtuSuccessMsg = "控制器接收并执行命令成功,无返回数据";
    private static final String ComCode = "38" ;
    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) ;
                int[] ymdHms = DateTime.yyyy_MM_dd_HH_MM_SS_2_ymdhmsGroup(dto.ymdHms) ;
                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位数字)
                        .year(ymdHms[0])//年
                        .month(ymdHms[1])//月
                        .day(ymdHms[2])//日
                        .hour(ymdHms[3])//时
                        .minute(ymdHms[4])//分
                        .waterAmount(dto.waterAmount)//预用水量(0~9999 m3)
                        .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() ;
    }
}
pipIrr-platform/pipIrr-web/pipIrr-web-remote/src/main/java/com/dy/pipIrrRemote/monitor/p202404V201/cd38/CdDto.java
New file
@@ -0,0 +1,33 @@
package com.dy.pipIrrRemote.monitor.p202404V201.cd38;
import com.dy.pipIrrRemote.common.dto.DtoBase;
import jakarta.validation.constraints.Max;
import jakarta.validation.constraints.Min;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
 * @Author: liurunyu
 * @Date: 2025/6/30 9:47
 * @Description
 */
@Data
@EqualsAndHashCode(callSuper=true)
public class CdDto extends DtoBase {
    public static final long serialVersionUID = 202505130833001L;
    @NotEmpty(message = "用户虚拟卡不能为空")
    public String vtCardId ;//用户卡(虚拟卡)序列号(17位数字)(6字节BCD,2字节HEX)
    @NotEmpty(message = "计划开阀时间不能为空")
    public String ymdHms ;//年月日时分秒(格式yyyy-MM-dd HH:mm:SS)
    @NotNull(message = "用水量不能为空")
    @Min(value = 1, message = "用水量不能小于1")
    @Max(value = 9999, message = "用水量不能大于9999")
    public Integer waterAmount ;//预用水量(0~9999 m3)
}
pipIrr-platform/pipIrr-web/pipIrr-web-remote/src/main/java/com/dy/pipIrrRemote/monitor/p202404V201/cd38/CdParam.java
New file
@@ -0,0 +1,33 @@
package com.dy.pipIrrRemote.monitor.p202404V201.cd38;
import com.dy.pipIrrRemote.monitor.common.CdParameter;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import lombok.experimental.SuperBuilder;
/**
 * @Author: liurunyu
 * @Date: 2025/6/30 9:47
 * @Description
 */
@Data
@ToString(callSuper = true)
@EqualsAndHashCode(callSuper = true)
@SuperBuilder
public class CdParam extends CdParameter {
    public String icCardNo ;//用户卡序列号(17位数字)(6字节BCD,2字节HEX)
    public Double waterRemain ;//用户剩余水量, 两个小数点, 单位m3, 0~99999999.99
    public Double moneyRemain ;//用户剩余金额, 两个小数点, 单位元, 0~999999.99
    public Double waterPrice ;//水量单价 单位:元, 2个小数点
    public Double elePrice ;//电量单价 单位:元, 2个小数点
    public String orderNo ;//订单号(16位数字)
    public Integer year ; //计划开阀时间---年
    public Integer month ;//计划开阀时间---月
    public Integer day ;//计划开阀时间---日
    public Integer hour ;//计划开阀时间---时
    public Integer minute ;//计划开阀时间---分
    public Integer waterAmount ;//预用水量(0~9999 m3)
}
pipIrr-platform/pipIrr-web/pipIrr-web-remote/src/main/java/com/dy/pipIrrRemote/monitor/p202404V201/cd38/CdSv.java
New file
@@ -0,0 +1,80 @@
package com.dy.pipIrrRemote.monitor.p202404V201.cd38;
import com.dy.pipIrrGlobal.daoPr.PrIntakeVcMapper;
import com.dy.pipIrrGlobal.daoPr.PrWaterPriceMapper;
import com.dy.pipIrrGlobal.daoRm.RmCommandOpenMapper;
import com.dy.pipIrrGlobal.daoSe.SeVirtualCardMapper;
import com.dy.pipIrrGlobal.pojoRm.RmCommandOpen;
import com.dy.pipIrrGlobal.pojoSe.SeVirtualCard;
import com.dy.pipIrrGlobal.voSe.VoVirtualCard;
import com.dy.pipIrrRemote.monitor.common.ComSv;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.Date;
import java.util.List;
/**
 * @Author: liurunyu
 * @Date: 2025/6/30 9:47
 * @Description
 */
@Slf4j
@Service("cd38Sv")
public class CdSv extends ComSv {
    @Autowired
    protected SeVirtualCardMapper seVirtualCardDao ;
    @Autowired
    protected PrWaterPriceMapper prWaterPriceDao ;
    @Autowired
    protected PrIntakeVcMapper prIntakeVcDao ;
    @Autowired
    protected RmCommandOpenMapper rmCommandOpenDao ;
    public VoVirtualCard selectClientVtCardById(Long id){
        return seVirtualCardDao.getVcById(id) ;
    }
    public Double selectWaterPrice(){
        return prWaterPriceDao.getPrice() ;
    }
    /**
     * 根据取水口ID获取与之绑定虚拟卡ID
     * @param intakeId
     * @return
     */
    public Long selectVcIdByIntakeId(Long intakeId) {
        return prIntakeVcDao.getVcIdByIntakeId(intakeId);
    }
    /**
     * 设置虚拟卡被占用
     */
    @Transactional(rollbackFor = Exception.class)
    public void setVcUsed(Long id, Long intakeId){
        SeVirtualCard po = new SeVirtualCard() ;
        po.setId(id);
        po.setIntakeId(intakeId);
        po.setInUse((byte)1);
        po.setOpenTime(new Date());
        seVirtualCardDao.updateByPrimaryKeySelective(po);
    }
    public RmCommandOpen getCommandOpen(Long intakeId){
        List<RmCommandOpen> list = rmCommandOpenDao.selectByIntakeId(intakeId) ;
        if(list != null && list.size() > 0){
            return list.get(0) ;
        }
        return null ;
    }
    @Transactional(rollbackFor = Exception.class)
    public void saveCommandOpen(RmCommandOpen po){
        rmCommandOpenDao.insert(po) ;
    }
    @Transactional(rollbackFor = Exception.class)
    public void updateCommandOpen(RmCommandOpen po){
        rmCommandOpenDao.updateByPrimaryKeySelective(po) ;
    }
}
pipIrr-platform/pipIrr-web/pipIrr-web-remote/src/main/java/com/dy/pipIrrRemote/monitor/p202404V201/cd92/CdCtrl.java
@@ -45,7 +45,7 @@
    private static final String ComCode = "92" ;
    private static final Double maxRemainMoney = 9999.9999D ;//协议支持的剩余金额最大值
    public static final Double MaxRemainMoney = 9999.9999D ;//协议支持的剩余金额最大值
    @Autowired
    private CdSv sv ;
@@ -83,8 +83,8 @@
                if(vcPo.getMoney() <= 0.0){
                    return BaseResponseUtils.buildErrorMsg("农户该虚拟卡中剩余金额为0,不能再应用其开阀") ;
                }
                if(vcPo.getMoney() >= maxRemainMoney){
                    return BaseResponseUtils.buildErrorMsg("农户该虚拟卡中剩余金额大于协议支持的最大值" + maxRemainMoney + ",不能再应用其开阀") ;
                if(vcPo.getMoney() >= MaxRemainMoney){
                    return BaseResponseUtils.buildErrorMsg("农户该虚拟卡中剩余金额大于协议支持的最大值" + MaxRemainMoney + ",不能再应用其开阀") ;
                }
                Double waterPrice = sv.selectWaterPrice() ;
                if(waterPrice == null){
pipIrr-platform/pipIrr-web/pipIrr-web-remote/src/main/java/com/dy/pipIrrRemote/monitor/p202404V201/cdA2/CdCtrl.java
@@ -45,7 +45,7 @@
    private static final String ComCode = "A2" ;
    private static final Double maxRemainMoney = 9999.9999D ;//协议支持的剩余金额最大值
    private static final Double MaxRemainMoney = com.dy.pipIrrRemote.monitor.p202404V201.cd92.CdCtrl.MaxRemainMoney;//协议支持的剩余金额最大值
    @Autowired
    private CdSv sv ;
@@ -83,8 +83,8 @@
                if(vcPo.getMoney() <= 0.0){
                    return BaseResponseUtils.buildErrorMsg("农户该虚拟卡中剩余金额为0,不能再应用其开阀") ;
                }
                if(vcPo.getMoney() >= maxRemainMoney){
                    return BaseResponseUtils.buildErrorMsg("农户该虚拟卡中剩余金额大于协议支持的最大值" + maxRemainMoney + ",不能再应用其开阀") ;
                if(vcPo.getMoney() >= MaxRemainMoney){
                    return BaseResponseUtils.buildErrorMsg("农户该虚拟卡中剩余金额大于协议支持的最大值" + MaxRemainMoney + ",不能再应用其开阀") ;
                }
                Double waterPrice = sv.selectWaterPrice() ;
                if(waterPrice == null){