zhubaomin
昨天 d730e2a289b38356e28a04b35a0cb2e7b4c6c282
Merge branch 'master' of http://8.140.179.55:20000/r/pipIrr-SV
1 文件已重命名
44个文件已修改
39个文件已添加
4158 ■■■■■ 已修改文件
pipIrr-platform/pipIrr-common/src/main/java/com/dy/common/mw/protocol/p206V202404/CodeV202404.java 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pipIrr-platform/pipIrr-common/src/main/java/com/dy/common/mw/protocol/p206V202404/downVos/ComCd35Vo.java 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pipIrr-platform/pipIrr-common/src/main/java/com/dy/common/mw/protocol/p206V202404/downVos/ComCd36Vo.java 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pipIrr-platform/pipIrr-common/src/main/java/com/dy/common/mw/protocol/p206V202404/downVos/ComCd37Vo.java 23 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pipIrr-platform/pipIrr-common/src/main/java/com/dy/common/mw/protocol/p206V202404/downVos/ComCd38Vo.java 23 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pipIrr-platform/pipIrr-common/src/main/java/com/dy/common/mw/protocol/p206V202404/downVos/ComCd9DVo.java 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pipIrr-platform/pipIrr-common/src/main/java/com/dy/common/mw/protocol/p206V202404/parse/Cd_35_36_37_38Up.java 92 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pipIrr-platform/pipIrr-common/src/main/java/com/dy/common/mw/protocol/p206V202404/parse/Cd_35_Down.java 225 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pipIrr-platform/pipIrr-common/src/main/java/com/dy/common/mw/protocol/p206V202404/parse/Cd_36_Down.java 225 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pipIrr-platform/pipIrr-common/src/main/java/com/dy/common/mw/protocol/p206V202404/parse/Cd_37_Down.java 267 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pipIrr-platform/pipIrr-common/src/main/java/com/dy/common/mw/protocol/p206V202404/parse/Cd_38_Down.java 266 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pipIrr-platform/pipIrr-common/src/main/java/com/dy/common/mw/protocol/p206V202404/parse/Cd_93_A3_Up.java 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pipIrr-platform/pipIrr-common/src/main/java/com/dy/common/mw/protocol/p206V202404/parse/Cd_9D_Down.java 120 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pipIrr-platform/pipIrr-common/src/main/java/com/dy/common/mw/protocol/p206V202404/parse/global/GlParse.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
pipIrr-platform/pipIrr-common/src/main/java/com/dy/common/mw/protocol/p206V202404/upVos/DataCd35_36Vo.java 114 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pipIrr-platform/pipIrr-common/src/main/java/com/dy/common/mw/protocol/p206V202404/upVos/DataCd92_A2Vo.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
pipIrr-platform/pipIrr-common/src/main/java/com/dy/common/mw/protocol/p206V202404/upVos/DataCd93_9D_A3Vo.java 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pipIrr-platform/pipIrr-global/src/main/java/com/dy/pipIrrGlobal/command/CommandSv.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pipIrr-platform/pipIrr-global/src/main/java/com/dy/pipIrrGlobal/daoRm/RmCommandOpenMapper.java 31 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pipIrr-platform/pipIrr-global/src/main/java/com/dy/pipIrrGlobal/daoRm/RmManureHistoryMapper.java 5 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pipIrr-platform/pipIrr-global/src/main/java/com/dy/pipIrrGlobal/daoRm/RmManureLastMapper.java 5 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pipIrr-platform/pipIrr-global/src/main/java/com/dy/pipIrrGlobal/daoRm/RmSoilDayMapper.java 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pipIrr-platform/pipIrr-global/src/main/java/com/dy/pipIrrGlobal/daoRm/RmSoilHistoryMapper.java 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pipIrr-platform/pipIrr-global/src/main/java/com/dy/pipIrrGlobal/daoRm/RmSoilLastMapper.java 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pipIrr-platform/pipIrr-global/src/main/java/com/dy/pipIrrGlobal/daoRm/RmWeatherHistoryMapper.java 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pipIrr-platform/pipIrr-global/src/main/java/com/dy/pipIrrGlobal/daoRm/RmWeatherLastMapper.java 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pipIrr-platform/pipIrr-global/src/main/java/com/dy/pipIrrGlobal/pojoRm/RmCommandOpen.java 82 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pipIrr-platform/pipIrr-global/src/main/java/com/dy/pipIrrGlobal/voRm/VoManure.java 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pipIrr-platform/pipIrr-global/src/main/java/com/dy/pipIrrGlobal/voRm/VoSoil.java 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pipIrr-platform/pipIrr-global/src/main/java/com/dy/pipIrrGlobal/voRm/VoSoilDay.java 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pipIrr-platform/pipIrr-global/src/main/java/com/dy/pipIrrGlobal/voRm/VoWeather.java 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pipIrr-platform/pipIrr-global/src/main/resources/mapper/PrStManureMapper.xml 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
pipIrr-platform/pipIrr-global/src/main/resources/mapper/PrStSoilMapper.xml 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
pipIrr-platform/pipIrr-global/src/main/resources/mapper/PrStWeatherMapper.xml 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
pipIrr-platform/pipIrr-global/src/main/resources/mapper/RmCommandOpenMapper.xml 181 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pipIrr-platform/pipIrr-global/src/main/resources/mapper/RmManureHistoryMapper.xml 19 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pipIrr-platform/pipIrr-global/src/main/resources/mapper/RmManureLastMapper.xml 16 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pipIrr-platform/pipIrr-global/src/main/resources/mapper/RmSoilDayMapper.xml 36 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pipIrr-platform/pipIrr-global/src/main/resources/mapper/RmSoilHistoryMapper.xml 15 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pipIrr-platform/pipIrr-global/src/main/resources/mapper/RmSoilLastMapper.xml 17 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pipIrr-platform/pipIrr-global/src/main/resources/mapper/RmWeatherHistoryMapper.xml 15 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pipIrr-platform/pipIrr-global/src/main/resources/mapper/RmWeatherLastMapper.xml 15 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pipIrr-platform/pipIrr-mw/pipIrr-mw-rtu/src/main/java/com/dy/rtuMw/resource/rtuLog/RtuLogManager.java 4 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
pipIrr-platform/pipIrr-mw/pipIrr-mw-rtu/src/main/resources/config.properties 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pipIrr-platform/pipIrr-mw/pipIrr-param-set/src/main/java/com/dy/pipIrrParamSet/console/Command.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pipIrr-platform/pipIrr-web/pipIrr-web-project/src/main/java/com/dy/pipIrrProject/mqtt/manure/ManureDto.java 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pipIrr-platform/pipIrr-web/pipIrr-web-project/src/main/java/com/dy/pipIrrProject/mqtt/soil/SoilDto.java 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pipIrr-platform/pipIrr-web/pipIrr-web-project/src/main/java/com/dy/pipIrrProject/mqtt/weather/WeatherDto.java 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pipIrr-platform/pipIrr-web/pipIrr-web-remote/src/main/java/com/dy/pipIrrRemote/monitor/common/ComSv.java 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
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 57 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pipIrr-platform/pipIrr-web/pipIrr-web-remote/src/main/java/com/dy/pipIrrRemote/monitor/p202404V201/cd92/CdSv.java 25 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pipIrr-platform/pipIrr-web/pipIrr-web-remote/src/main/java/com/dy/pipIrrRemote/monitor/p202404V201/cd93/CdCtrl.java 22 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pipIrr-platform/pipIrr-web/pipIrr-web-remote/src/main/java/com/dy/pipIrrRemote/monitor/p202404V201/cd93/CdSv.java 19 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pipIrr-platform/pipIrr-web/pipIrr-web-remote/src/main/java/com/dy/pipIrrRemote/monitor/p202404V201/cd9D/CdCtrl.java 150 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pipIrr-platform/pipIrr-web/pipIrr-web-remote/src/main/java/com/dy/pipIrrRemote/monitor/p202404V201/cd9D/CdDto.java 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pipIrr-platform/pipIrr-web/pipIrr-web-remote/src/main/java/com/dy/pipIrrRemote/monitor/p202404V201/cd9D/CdParam.java 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pipIrr-platform/pipIrr-web/pipIrr-web-remote/src/main/java/com/dy/pipIrrRemote/monitor/p202404V201/cd9D/CdSv.java 38 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pipIrr-platform/pipIrr-web/pipIrr-web-remote/src/main/java/com/dy/pipIrrRemote/monitor/p202404V201/cdA2/CdCtrl.java 57 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pipIrr-platform/pipIrr-web/pipIrr-web-remote/src/main/java/com/dy/pipIrrRemote/monitor/p202404V201/cdA2/CdSv.java 25 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pipIrr-platform/pipIrr-web/pipIrr-web-remote/src/main/java/com/dy/pipIrrRemote/monitor/p202404V201/cdA3/CdCtrl.java 23 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pipIrr-platform/pipIrr-web/pipIrr-web-remote/src/main/java/com/dy/pipIrrRemote/monitor/p202404V201/cdA3/CdSv.java 17 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pipIrr-platform/pipIrr-web/pipIrr-web-remote/src/main/java/com/dy/pipIrrRemote/mqttSd1/soil/SoilCtrl.java 30 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pipIrr-platform/pipIrr-web/pipIrr-web-remote/src/main/java/com/dy/pipIrrRemote/mqttSd1/soil/SoilSv.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pipIrr-platform/pipIrr-common/src/main/java/com/dy/common/mw/protocol/p206V202404/CodeV202404.java
@@ -41,6 +41,12 @@
    public static final String cd_9B = "9B" ; //清除设备终端注册号
    public static final String cd_9C = "9C" ; //黑名单远程强制关闭水泵/阀门
    public static final String cd_C2 = "C2" ; //开关水泵/阀门成功/失败上报
    public static final String cd_9D = "9D" ; //正常远程关闭水泵/阀门
    public static final String cd_35 = "35" ; //APP端远程定时开启水泵/阀门
    public static final String cd_36 = "36" ; //APP端远程定量开启水泵/阀门
    public static final String cd_37 = "37" ; //APP端计划远程定时开启水泵/阀门
    public static final String cd_38 = "38" ; //APP端远程计划定量开启水泵/阀门
    public static final String cd_1600 = "1600" ;//升级复位
    public static final String cd_1601 = "1601" ;//升级配置
@@ -90,6 +96,13 @@
            (code.equals(cd_9B) ? "清除设备终端注册号" :
            (code.equals(cd_9C) ? "黑名单远程强制关闭水泵/阀门" :
            (code.equals(cd_C2) ? "开关水泵/阀门结果上报" :
            (code.equals(cd_9D) ? "正常远程关闭水泵/阀门" :
            (code.equals(cd_35) ? "APP端远程定时开启水泵/阀门" :
            (code.equals(cd_36) ? "APP端远程定量开启水泵/阀门" :
            (code.equals(cd_37) ? "APP端计划远程定时开启水泵/阀门" :
            (code.equals(cd_38) ? "APP端远程计划定量开启水泵/阀门" :
            (code.equals(cd_1600) ? "升级复位" :
            (code.equals(cd_1601) ? "升级配置" :
            (code.equals(cd_1602) ? "升级数据" :
@@ -97,7 +110,7 @@
            (code.equals(cd_9601) ? "升级配置" :
            (code.equals(cd_9602) ? "升级数据" :
            (code.equals(cd_9603) ? "升级校验" :
            "")))))))))))))))))))))))))))))))))))))))))))))) ;
            ""))))))))))))))))))))))))))))))))))))))))))))))))))) ;
        if(name == null || name.equals("")){
            name = code ;
        }
pipIrr-platform/pipIrr-common/src/main/java/com/dy/common/mw/protocol/p206V202404/downVos/ComCd35Vo.java
New file
@@ -0,0 +1,16 @@
package com.dy.common.mw.protocol.p206V202404.downVos;
import lombok.Data;
@Data
public class ComCd35Vo {
    public String controllerType;//控制器类型 01(0x01):测控一体阀;02(0x02):表阀一体机;57(0x57):井电控制器
    public Integer projectNo ;//项目编号
    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-common/src/main/java/com/dy/common/mw/protocol/p206V202404/downVos/ComCd36Vo.java
New file
@@ -0,0 +1,16 @@
package com.dy.common.mw.protocol.p206V202404.downVos;
import lombok.Data;
@Data
public class ComCd36Vo {
    public String controllerType;//控制器类型 01(0x01):测控一体阀;02(0x02):表阀一体机;57(0x57):井电控制器
    public Integer projectNo ;//项目编号
    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-common/src/main/java/com/dy/common/mw/protocol/p206V202404/downVos/ComCd37Vo.java
New file
@@ -0,0 +1,23 @@
package com.dy.common.mw.protocol.p206V202404.downVos;
import lombok.Data;
@Data
public class ComCd37Vo {
    public String controllerType;//控制器类型 01(0x01):测控一体阀;02(0x02):表阀一体机;57(0x57):井电控制器
    public Integer projectNo ;//项目编号
    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-common/src/main/java/com/dy/common/mw/protocol/p206V202404/downVos/ComCd38Vo.java
New file
@@ -0,0 +1,23 @@
package com.dy.common.mw.protocol.p206V202404.downVos;
import lombok.Data;
@Data
public class ComCd38Vo {
    public String controllerType;//控制器类型 01(0x01):测控一体阀;02(0x02):表阀一体机;57(0x57):井电控制器
    public Integer projectNo ;//项目编号
    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-common/src/main/java/com/dy/common/mw/protocol/p206V202404/downVos/ComCd9DVo.java
New file
@@ -0,0 +1,12 @@
package com.dy.common.mw.protocol.p206V202404.downVos;
import lombok.Data;
@Data
public class ComCd9DVo {
    public String controllerType;//控制器类型 01(0x01):测控一体阀;02(0x02):表阀一体机;57(0x57):井电控制器
    public Integer projectNo ;//项目编号
    public String icCardAddr ;//用户卡地址)(4字节HEX)
    public String icCardNo ;//用户卡序列号(17位数字)(6字节BCD,2字节HEX)
    public String orderNo ;//订单号(16位数字)
}
pipIrr-platform/pipIrr-common/src/main/java/com/dy/common/mw/protocol/p206V202404/parse/Cd_35_36_37_38Up.java
New file
@@ -0,0 +1,92 @@
package com.dy.common.mw.protocol.p206V202404.parse;
import com.dy.common.mw.protocol.*;
import com.dy.common.mw.protocol.p206V202404.*;
import com.dy.common.mw.protocol.p206V202404.parse.global.GlParse;
import com.dy.common.mw.protocol.p206V202404.upVos.DataCd35_36Vo;
import com.dy.common.mw.protocol.rtuState.ValveStateInfo;
import com.dy.common.util.ByteUtil;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
@AnnotationCodeUp(ifAny={
        CodeV202404.cd_35,
        CodeV202404.cd_36,
        CodeV202404.cd_37,
        CodeV202404.cd_38
})
@SuppressWarnings("unused")
public class Cd_35_36_37_38Up implements CodeParse{
    private static final Logger log = LogManager.getLogger(Cd_35_36_37_38Up.class);
    /**
     * 分析上行数据
     */
    @Override
    public MidResult[] parse(Boolean isLowPower, CodeParseParams params, CodeParseCallback callback)throws Exception {
        ParseParamsForUpV202404 para = (ParseParamsForUpV202404)params ;
        int bsLen = new CommonV202404().parseDataLen4P202404(para.upBuffer) ;
        if(bsLen > 0){
            this.doParse(para.upBuffer,
                    bsLen,
                    para.upCode,
                    para.data) ;
        }
        log.info("\n分析命令应答数据<" + CodeV202404.getCodeName(para.upCode) + " RTU地址=" + para.rtuAddr + ">:\n" + para.data.toString());
        MidResultFromRtu midRs = new MidResultFromRtu() ;
        midRs.protocolName = para.protocolName ;//协议名称
        midRs.protocolVersion = para.protocolVersion ;//协议版本号
        midRs.rtuAddr = para.rtuAddr ;//Rtu地址
        midRs.upCode = para.upCode ;//上行数据中的功能码
        midRs.upHex = para.upHex ;//上行数据十六进制形式
        midRs.upBuffer = para.upBuffer ;//上行数据字节数组
        midRs.data = para.data ;//解析后的数据
        midRs.reportOrResponse_trueOrFalse = false ;
        callback.callback(midRs.reportOrResponse_trueOrFalse, para.data.subData==null?null:((DataV202404)(para.data.subData)).subData);
        if(para.data != null && para.data.getSubData() != null){
            DataCd35_36Vo subData = (DataCd35_36Vo)((DataV202404)para.data.getSubData()).subData ;
            //opResult ;//开启泵/阀结果: 0x00:成功 0x81:失败
            callback.notify(new ValveStateInfo(subData.opResult.byteValue() == 0 ? true:false));
        }
        return new MidResult[]{midRs} ;
    }
    /**
     * 执行分析
     * @param bs 字节数组
     * @param bsLen 字节长度(总包长,包括包头和包尾)
     * @param dataCode 功能码
     * @param data 数据
     * @throws Exception 异常
     */
    protected void doParse(byte[] bs, int bsLen, String dataCode, Data data) throws Exception {
        DataV202404 dV202404 = (DataV202404)data.getSubData() ;
        DataCd35_36Vo cdData = new DataCd35_36Vo(CodeV202404.getCodeName(dataCode)) ;
        dV202404.subData = cdData ;
        int index = ProtocolConstantV206V202404.dataIndex ;
        cdData.controllerType = ByteUtil.bytes2Hex(bs, false, index, 1) ;
        index++ ;
        cdData.projectNo = (int)bs[index];
        index++ ;
        cdData.icCardNo = GlParse.parseIcCardNo(bs, index, 6, 2) ;
        index += 8 ;
        cdData.orderNo = ByteUtil.BCD2String_BE(bs, index, index + 7) ;
        //index += 8 ;
        //cdData.opDt = GlParse.parseRtuDt(bs, index) ;
        index += 6 ;
        cdData.opType = bs[index];
        index ++ ;
        cdData.opResult = bs[index];
    }
}
pipIrr-platform/pipIrr-common/src/main/java/com/dy/common/mw/protocol/p206V202404/parse/Cd_35_Down.java
New file
@@ -0,0 +1,225 @@
package com.dy.common.mw.protocol.p206V202404.parse;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.dy.common.mw.protocol.*;
import com.dy.common.mw.protocol.p206V202404.CodeV202404;
import com.dy.common.mw.protocol.p206V202404.ParseParamsForDownV202404;
import com.dy.common.mw.protocol.p206V202404.downVos.ComCd35Vo;
import com.dy.common.mw.protocol.p206V202404.downVos.ComCd92_A2Vo;
import com.dy.common.mw.protocol.p206V202404.parse.global.GlCreate;
import com.dy.common.util.ByteUtil;
import com.dy.common.util.NumUtil;
@AnnotationCodeDown(ifAny={
        CodeV202404.cd_35
})
public class Cd_35_Down implements CodeParse {
    @Override
    public MidResult[] parse(Boolean isLowPower, CodeParseParams params, CodeParseCallback callback) throws Exception {
        ParseParamsForDownV202404 para = (ParseParamsForDownV202404) params ;
        byte[] bs = this.doParse(para) ;
        MidResultToRtu midRs = new MidResultToRtu() ;
        midRs.protocolName = para.protocolName ;//协议名称
        midRs.protocolVersion = para.protocolVersion ;//协议版本号
        midRs.rtuResultSendWebUrl = para.rtuResultSendWebUrl ;
        midRs.rtuAddr = para.rtuAddr ;//Rtu地址
        midRs.commandId = para.commandId ;//命令ID,发起命令的客户端(web端)生成,以匹配命令结果
        midRs.downCode = para.commandCode ;//下行命令功能码;
        midRs.downCodeName = CodeV202404.getCodeName(para.commandCode) ;//下行命令功能码名称;
        midRs.downBuffer = bs ;//下行命令数据
        midRs.downBufHex = ByteUtil.bytes2Hex(bs, true) ;//下行命令数据十六进制形式
        midRs.hasResponse = true ;//是否有应答
        midRs.maxSendTimes = null ;//命令最大发送次数(当收不到应答时,将重发),如果不设置,命令缓存器进行补充设置
        midRs.isCachForOffLine = false ;//RTU不在线,命令是否缓存,低功耗时为true
        midRs.isSendFirst = false ;//命令应答,首先发送,防止RTU重新上报
        if(isLowPower != null && isLowPower.booleanValue()){
            //低功耗时,尽快发送
            midRs.isQuickSend = true ;
        }
        return new MidResult[]{midRs} ;
    }
    /**
     * 构造下行数据
     * @param para 参数
     * @return 字节数组
     * @throws Exception 异常
     */
    public byte[] doParse(ParseParamsForDownV202404 para) throws Exception {
        byte[] bytes = GlCreate.createStart2Cd(para.rtuAddr, para.commandCode);
        if(para.param != null){
            JSONObject obj = (JSONObject)para.param;
            String json = obj.toJSONString();
            ComCd35Vo cvo = JSON.parseObject(json, ComCd35Vo.class) ;
            if(cvo == null){
                throw new Exception("json转ComCd35Vo为null") ;
            }
            if(cvo.waterRemain != null){
                if(cvo.waterRemain < 0 || cvo.waterRemain > 99999999.99){
                    throw new Exception("用户剩余水量必须是0~99999999.99范围内的数据") ;
                }
            }
            if(cvo.moneyRemain != null){
                if(cvo.moneyRemain < 0 || cvo.moneyRemain > 999999.99){
                    throw new Exception("用户剩余金额必须是0~999999.99范围内的数据") ;
                }
            }
            if(cvo.waterPrice != null){
                if(cvo.waterPrice < 0 || cvo.waterPrice > 99.99){
                    throw new Exception("水量单价必须是0~99.99范围内的数据") ;
                }
            }
            if(cvo.elePrice != null){
                if(cvo.elePrice < 0 || cvo.elePrice > 99.99){
                    throw new Exception("电量单价必须是0~99.99范围内的数据") ;
                }
            }
            if(!NumUtil.isPlusIntNumber(cvo.orderNo)){
                throw new Exception("订单号必须是16位数字") ;
            }
            if(cvo.orderNo.length() != 16){
                throw new Exception("订单号必须是16位数字") ;
            }
            if(cvo.minutes == null || cvo.minutes == 0.0){
                throw new Exception("用水时长不能为空或为0") ;
            }
            if(cvo.minutes < 0 || cvo.minutes > 9999){
                throw new Exception("用水时长取值范围是0~9999分钟") ;
            }
            byte[] bs = new byte[47] ;
            int index = 0 ;
            bs[index] = (byte)(Integer.parseInt(cvo.controllerType, 16));
            index ++ ;
            bs[index] = cvo.projectNo.byteValue() ;
            index ++ ;
            GlCreate.createValveOrPump(cvo.controllerType, bs, index) ;
            index ++ ;
            GlCreate.createIcCardNo(cvo.icCardNo, bs, index);
            index += 8 ;
            if(cvo.waterRemain == null){
                cvo.waterRemain = 0.0 ;
            }
            String strTemp = "" + Double.valueOf(cvo.waterRemain * 100).intValue() ;
            byte[] bTemp = ByteUtil.string2BCD_LE(strTemp) ;
            int bTempLen = bTemp.length ;
            int count = 0 ;
            for(int i = 0 ; i < bTempLen; i++){
                bs[index++] = bTemp[i] ;
                count ++ ;
                if(count >= 5){
                    break ;
                }
            }
            for(; count < 5; count++){
                bs[index++] = 0 ;
            }
            if(cvo.moneyRemain == null){
                cvo.moneyRemain = 0.0 ;
            }
            strTemp = "" + (Double.valueOf(cvo.moneyRemain * 10000)).intValue() ;
            bTemp = ByteUtil.string2BCD_LE(strTemp) ;
            bTempLen = bTemp.length ;
            count = 0 ;
            for(int i = 0 ; i < bTempLen; i++){
                bs[index++] = bTemp[i] ;
                count ++ ;
                if(count >= 4){
                    break ;
                }
            }
            for(; count < 4; count++){
                bs[index++] = 0 ;
            }
            if(cvo.waterPrice == null){
                cvo.waterPrice = 0.0 ;
            }
            strTemp = "" + (Double.valueOf(cvo.waterPrice * 100)).intValue() ;
            bTemp = ByteUtil.string2BCD_LE(strTemp) ;
            bTempLen = bTemp.length ;
            count = 0 ;
            for(int i = 0 ; i < bTempLen; i++){
                bs[index++] = bTemp[i] ;
                count ++ ;
                if(count >= 2){
                    break ;
                }
            }
            for(; count < 2; count++){
                bs[index++] = 0 ;
            }
            if(cvo.elePrice == null){
                cvo.elePrice = 0.0 ;
            }
            strTemp = "" + (Double.valueOf(cvo.elePrice * 100)).intValue() ;
            bTemp = ByteUtil.string2BCD_LE(strTemp) ;
            bTempLen = bTemp.length ;
            count = 0 ;
            for(int i = 0 ; i < bTempLen; i++){
                bs[index++] = bTemp[i] ;
                count ++ ;
                if(count >= 2){
                    break ;
                }
            }
            for(; count < 2; count++){
                bs[index++] = 0 ;
            }
            ByteUtil.string2BCD_BE(bs, cvo.orderNo, index) ;
            index += 8 ;
            GlCreate.createDt(bs, index);
            index += 6 ;
            bTemp = ByteUtil.int2BCD_LE(cvo.minutes) ;
            bTempLen = bTemp.length ;
            count = 0 ;
            for(int i = 0 ; i < bTempLen; i++){
                bs[index++] = bTemp[i] ;
                count ++ ;
                if(count >= 2){
                    break ;
                }
            }
            for(; count < 2; count++){
                bs[index++] = 0 ;
            }
            GlCreate.createPw(bs, index);
            index += 2 ;
            GlCreate.createS2D(bs, index) ;
            index += 4 ;
            bs[index] = 0 ; //时延
            bytes = ByteUtil.bytesMerge(bytes, bs) ;
        }else{
            throw new Exception("下行命令参数据为null") ;
        }
        GlCreate.createLen(bytes);//长度放字节数组中
        byte[] bsTail = GlCreate.createCrcTail(bytes) ;//CRC和尾
        bytes = ByteUtil.bytesMerge(bytes, bsTail) ;
        return bytes ;
    }
}
pipIrr-platform/pipIrr-common/src/main/java/com/dy/common/mw/protocol/p206V202404/parse/Cd_36_Down.java
New file
@@ -0,0 +1,225 @@
package com.dy.common.mw.protocol.p206V202404.parse;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.dy.common.mw.protocol.*;
import com.dy.common.mw.protocol.p206V202404.CodeV202404;
import com.dy.common.mw.protocol.p206V202404.ParseParamsForDownV202404;
import com.dy.common.mw.protocol.p206V202404.downVos.ComCd35Vo;
import com.dy.common.mw.protocol.p206V202404.downVos.ComCd36Vo;
import com.dy.common.mw.protocol.p206V202404.parse.global.GlCreate;
import com.dy.common.util.ByteUtil;
import com.dy.common.util.NumUtil;
@AnnotationCodeDown(ifAny={
        CodeV202404.cd_36
})
public class Cd_36_Down implements CodeParse {
    @Override
    public MidResult[] parse(Boolean isLowPower, CodeParseParams params, CodeParseCallback callback) throws Exception {
        ParseParamsForDownV202404 para = (ParseParamsForDownV202404) params ;
        byte[] bs = this.doParse(para) ;
        MidResultToRtu midRs = new MidResultToRtu() ;
        midRs.protocolName = para.protocolName ;//协议名称
        midRs.protocolVersion = para.protocolVersion ;//协议版本号
        midRs.rtuResultSendWebUrl = para.rtuResultSendWebUrl ;
        midRs.rtuAddr = para.rtuAddr ;//Rtu地址
        midRs.commandId = para.commandId ;//命令ID,发起命令的客户端(web端)生成,以匹配命令结果
        midRs.downCode = para.commandCode ;//下行命令功能码;
        midRs.downCodeName = CodeV202404.getCodeName(para.commandCode) ;//下行命令功能码名称;
        midRs.downBuffer = bs ;//下行命令数据
        midRs.downBufHex = ByteUtil.bytes2Hex(bs, true) ;//下行命令数据十六进制形式
        midRs.hasResponse = true ;//是否有应答
        midRs.maxSendTimes = null ;//命令最大发送次数(当收不到应答时,将重发),如果不设置,命令缓存器进行补充设置
        midRs.isCachForOffLine = false ;//RTU不在线,命令是否缓存,低功耗时为true
        midRs.isSendFirst = false ;//命令应答,首先发送,防止RTU重新上报
        if(isLowPower != null && isLowPower.booleanValue()){
            //低功耗时,尽快发送
            midRs.isQuickSend = true ;
        }
        return new MidResult[]{midRs} ;
    }
    /**
     * 构造下行数据
     * @param para 参数
     * @return 字节数组
     * @throws Exception 异常
     */
    public byte[] doParse(ParseParamsForDownV202404 para) throws Exception {
        byte[] bytes = GlCreate.createStart2Cd(para.rtuAddr, para.commandCode);
        if(para.param != null){
            JSONObject obj = (JSONObject)para.param;
            String json = obj.toJSONString();
            ComCd36Vo cvo = JSON.parseObject(json, ComCd36Vo.class) ;
            if(cvo == null){
                throw new Exception("json转ComCd35Vo为null") ;
            }
            if(cvo.waterRemain != null){
                if(cvo.waterRemain < 0 || cvo.waterRemain > 99999999.99){
                    throw new Exception("用户剩余水量必须是0~99999999.99范围内的数据") ;
                }
            }
            if(cvo.moneyRemain != null){
                if(cvo.moneyRemain < 0 || cvo.moneyRemain > 999999.99){
                    throw new Exception("用户剩余金额必须是0~999999.99范围内的数据") ;
                }
            }
            if(cvo.waterPrice != null){
                if(cvo.waterPrice < 0 || cvo.waterPrice > 99.99){
                    throw new Exception("水量单价必须是0~99.99范围内的数据") ;
                }
            }
            if(cvo.elePrice != null){
                if(cvo.elePrice < 0 || cvo.elePrice > 99.99){
                    throw new Exception("电量单价必须是0~99.99范围内的数据") ;
                }
            }
            if(!NumUtil.isPlusIntNumber(cvo.orderNo)){
                throw new Exception("订单号必须是16位数字") ;
            }
            if(cvo.orderNo.length() != 16){
                throw new Exception("订单号必须是16位数字") ;
            }
            if(cvo.waterAmount == null || cvo.waterAmount == 0.0){
                throw new Exception("预用水量不能为空或为0") ;
            }
            if(cvo.waterAmount < 0 || cvo.waterAmount > 9999){
                throw new Exception("预用水量取值范围是0~9999m3") ;
            }
            byte[] bs = new byte[47] ;
            int index = 0 ;
            bs[index] = (byte)(Integer.parseInt(cvo.controllerType, 16));
            index ++ ;
            bs[index] = cvo.projectNo.byteValue() ;
            index ++ ;
            GlCreate.createValveOrPump(cvo.controllerType, bs, index) ;
            index ++ ;
            GlCreate.createIcCardNo(cvo.icCardNo, bs, index);
            index += 8 ;
            if(cvo.waterRemain == null){
                cvo.waterRemain = 0.0 ;
            }
            String strTemp = "" + Double.valueOf(cvo.waterRemain * 100).intValue() ;
            byte[] bTemp = ByteUtil.string2BCD_LE(strTemp) ;
            int bTempLen = bTemp.length ;
            int count = 0 ;
            for(int i = 0 ; i < bTempLen; i++){
                bs[index++] = bTemp[i] ;
                count ++ ;
                if(count >= 5){
                    break ;
                }
            }
            for(; count < 5; count++){
                bs[index++] = 0 ;
            }
            if(cvo.moneyRemain == null){
                cvo.moneyRemain = 0.0 ;
            }
            strTemp = "" + (Double.valueOf(cvo.moneyRemain * 10000)).intValue() ;
            bTemp = ByteUtil.string2BCD_LE(strTemp) ;
            bTempLen = bTemp.length ;
            count = 0 ;
            for(int i = 0 ; i < bTempLen; i++){
                bs[index++] = bTemp[i] ;
                count ++ ;
                if(count >= 4){
                    break ;
                }
            }
            for(; count < 4; count++){
                bs[index++] = 0 ;
            }
            if(cvo.waterPrice == null){
                cvo.waterPrice = 0.0 ;
            }
            strTemp = "" + (Double.valueOf(cvo.waterPrice * 100)).intValue() ;
            bTemp = ByteUtil.string2BCD_LE(strTemp) ;
            bTempLen = bTemp.length ;
            count = 0 ;
            for(int i = 0 ; i < bTempLen; i++){
                bs[index++] = bTemp[i] ;
                count ++ ;
                if(count >= 2){
                    break ;
                }
            }
            for(; count < 2; count++){
                bs[index++] = 0 ;
            }
            if(cvo.elePrice == null){
                cvo.elePrice = 0.0 ;
            }
            strTemp = "" + (Double.valueOf(cvo.elePrice * 100)).intValue() ;
            bTemp = ByteUtil.string2BCD_LE(strTemp) ;
            bTempLen = bTemp.length ;
            count = 0 ;
            for(int i = 0 ; i < bTempLen; i++){
                bs[index++] = bTemp[i] ;
                count ++ ;
                if(count >= 2){
                    break ;
                }
            }
            for(; count < 2; count++){
                bs[index++] = 0 ;
            }
            ByteUtil.string2BCD_BE(bs, cvo.orderNo, index) ;
            index += 8 ;
            GlCreate.createDt(bs, index);
            index += 6 ;
            bTemp = ByteUtil.int2BCD_LE(cvo.waterAmount) ;
            bTempLen = bTemp.length ;
            count = 0 ;
            for(int i = 0 ; i < bTempLen; i++){
                bs[index++] = bTemp[i] ;
                count ++ ;
                if(count >= 2){
                    break ;
                }
            }
            for(; count < 2; count++){
                bs[index++] = 0 ;
            }
            GlCreate.createPw(bs, index);
            index += 2 ;
            GlCreate.createS2D(bs, index) ;
            index += 4 ;
            bs[index] = 0 ; //时延
            bytes = ByteUtil.bytesMerge(bytes, bs) ;
        }else{
            throw new Exception("下行命令参数据为null") ;
        }
        GlCreate.createLen(bytes);//长度放字节数组中
        byte[] bsTail = GlCreate.createCrcTail(bytes) ;//CRC和尾
        bytes = ByteUtil.bytesMerge(bytes, bsTail) ;
        return bytes ;
    }
}
pipIrr-platform/pipIrr-common/src/main/java/com/dy/common/mw/protocol/p206V202404/parse/Cd_37_Down.java
New file
@@ -0,0 +1,267 @@
package com.dy.common.mw.protocol.p206V202404.parse;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.dy.common.mw.protocol.*;
import com.dy.common.mw.protocol.p206V202404.CodeV202404;
import com.dy.common.mw.protocol.p206V202404.ParseParamsForDownV202404;
import com.dy.common.mw.protocol.p206V202404.downVos.ComCd35Vo;
import com.dy.common.mw.protocol.p206V202404.downVos.ComCd37Vo;
import com.dy.common.mw.protocol.p206V202404.parse.global.GlCreate;
import com.dy.common.util.ByteUtil;
import com.dy.common.util.NumUtil;
@AnnotationCodeDown(ifAny={
        CodeV202404.cd_37
})
public class Cd_37_Down implements CodeParse {
    @Override
    public MidResult[] parse(Boolean isLowPower, CodeParseParams params, CodeParseCallback callback) throws Exception {
        ParseParamsForDownV202404 para = (ParseParamsForDownV202404) params ;
        byte[] bs = this.doParse(para) ;
        MidResultToRtu midRs = new MidResultToRtu() ;
        midRs.protocolName = para.protocolName ;//协议名称
        midRs.protocolVersion = para.protocolVersion ;//协议版本号
        midRs.rtuResultSendWebUrl = para.rtuResultSendWebUrl ;
        midRs.rtuAddr = para.rtuAddr ;//Rtu地址
        midRs.commandId = para.commandId ;//命令ID,发起命令的客户端(web端)生成,以匹配命令结果
        midRs.downCode = para.commandCode ;//下行命令功能码;
        midRs.downCodeName = CodeV202404.getCodeName(para.commandCode) ;//下行命令功能码名称;
        midRs.downBuffer = bs ;//下行命令数据
        midRs.downBufHex = ByteUtil.bytes2Hex(bs, true) ;//下行命令数据十六进制形式
        midRs.hasResponse = true ;//是否有应答
        midRs.maxSendTimes = null ;//命令最大发送次数(当收不到应答时,将重发),如果不设置,命令缓存器进行补充设置
        midRs.isCachForOffLine = false ;//RTU不在线,命令是否缓存,低功耗时为true
        midRs.isSendFirst = false ;//命令应答,首先发送,防止RTU重新上报
        if(isLowPower != null && isLowPower.booleanValue()){
            //低功耗时,尽快发送
            midRs.isQuickSend = true ;
        }
        return new MidResult[]{midRs} ;
    }
    /**
     * 构造下行数据
     * @param para 参数
     * @return 字节数组
     * @throws Exception 异常
     */
    public byte[] doParse(ParseParamsForDownV202404 para) throws Exception {
        byte[] bytes = GlCreate.createStart2Cd(para.rtuAddr, para.commandCode);
        if(para.param != null){
            JSONObject obj = (JSONObject)para.param;
            String json = obj.toJSONString();
            ComCd37Vo cvo = JSON.parseObject(json, ComCd37Vo.class) ;
            if(cvo == null){
                throw new Exception("json转ComCd37Vo为null") ;
            }
            if(cvo.waterRemain != null){
                if(cvo.waterRemain < 0 || cvo.waterRemain > 99999999.99){
                    throw new Exception("用户剩余水量必须是0~99999999.99范围内的数据") ;
                }
            }
            if(cvo.moneyRemain != null){
                if(cvo.moneyRemain < 0 || cvo.moneyRemain > 999999.99){
                    throw new Exception("用户剩余金额必须是0~999999.99范围内的数据") ;
                }
            }
            if(cvo.waterPrice != null){
                if(cvo.waterPrice < 0 || cvo.waterPrice > 99.99){
                    throw new Exception("水量单价必须是0~99.99范围内的数据") ;
                }
            }
            if(cvo.elePrice != null){
                if(cvo.elePrice < 0 || cvo.elePrice > 99.99){
                    throw new Exception("电量单价必须是0~99.99范围内的数据") ;
                }
            }
            if(!NumUtil.isPlusIntNumber(cvo.orderNo)){
                throw new Exception("订单号必须是16位数字") ;
            }
            if(cvo.orderNo.length() != 16){
                throw new Exception("订单号必须是16位数字") ;
            }
            if(cvo.year == null){
                throw new Exception("计划开阀时间---年不能为空") ;
            }
            if(cvo.year < 24 || cvo.year > 9999){
                throw new Exception("计划开阀时间---年不正确") ;
            }
            if(cvo.year > 99 && cvo.year < 2024){
                throw new Exception("计划开阀时间---年不正确") ;
            }
            if(cvo.month == null){
                throw new Exception("计划开阀时间---月不能为空") ;
            }
            if(cvo.month < 1 || cvo.month > 12){
                throw new Exception("计划开阀时间---月不正确") ;
            }
            if(cvo.day == null){
                throw new Exception("计划开阀时间---日不能为空") ;
            }
            if(cvo.day < 1 || cvo.day > 31){
                throw new Exception("计划开阀时间---日不正确") ;
            }
            if(cvo.hour == null){
                throw new Exception("计划开阀时间---时不能为空") ;
            }
            if(cvo.hour < 0 || cvo.hour > 23){
                throw new Exception("计划开阀时间---时不正确") ;
            }
            if(cvo.minute == null){
                throw new Exception("计划开阀时间---时不能为空") ;
            }
            if(cvo.minute < 0 || cvo.minute > 59){
                throw new Exception("计划开阀时间---分不正确") ;
            }
            if(cvo.minutes == null || cvo.minutes == 0.0){
                throw new Exception("用水时长不能为空或为0") ;
            }
            if(cvo.minutes < 0 || cvo.minutes > 9999){
                throw new Exception("用水时长取值范围是0~9999分钟") ;
            }
            byte[] bs = new byte[53] ;
            int index = 0 ;
            bs[index] = (byte)(Integer.parseInt(cvo.controllerType, 16));
            index ++ ;
            bs[index] = cvo.projectNo.byteValue() ;
            index ++ ;
            GlCreate.createValveOrPump(cvo.controllerType, bs, index) ;
            index ++ ;
            GlCreate.createIcCardNo(cvo.icCardNo, bs, index);
            index += 8 ;
            if(cvo.waterRemain == null){
                cvo.waterRemain = 0.0 ;
            }
            String strTemp = "" + Double.valueOf(cvo.waterRemain * 100).intValue() ;
            byte[] bTemp = ByteUtil.string2BCD_LE(strTemp) ;
            int bTempLen = bTemp.length ;
            int count = 0 ;
            for(int i = 0 ; i < bTempLen; i++){
                bs[index++] = bTemp[i] ;
                count ++ ;
                if(count >= 5){
                    break ;
                }
            }
            for(; count < 5; count++){
                bs[index++] = 0 ;
            }
            if(cvo.moneyRemain == null){
                cvo.moneyRemain = 0.0 ;
            }
            strTemp = "" + (Double.valueOf(cvo.moneyRemain * 10000)).intValue() ;
            bTemp = ByteUtil.string2BCD_LE(strTemp) ;
            bTempLen = bTemp.length ;
            count = 0 ;
            for(int i = 0 ; i < bTempLen; i++){
                bs[index++] = bTemp[i] ;
                count ++ ;
                if(count >= 4){
                    break ;
                }
            }
            for(; count < 4; count++){
                bs[index++] = 0 ;
            }
            if(cvo.waterPrice == null){
                cvo.waterPrice = 0.0 ;
            }
            strTemp = "" + (Double.valueOf(cvo.waterPrice * 100)).intValue() ;
            bTemp = ByteUtil.string2BCD_LE(strTemp) ;
            bTempLen = bTemp.length ;
            count = 0 ;
            for(int i = 0 ; i < bTempLen; i++){
                bs[index++] = bTemp[i] ;
                count ++ ;
                if(count >= 2){
                    break ;
                }
            }
            for(; count < 2; count++){
                bs[index++] = 0 ;
            }
            if(cvo.elePrice == null){
                cvo.elePrice = 0.0 ;
            }
            strTemp = "" + (Double.valueOf(cvo.elePrice * 100)).intValue() ;
            bTemp = ByteUtil.string2BCD_LE(strTemp) ;
            bTempLen = bTemp.length ;
            count = 0 ;
            for(int i = 0 ; i < bTempLen; i++){
                bs[index++] = bTemp[i] ;
                count ++ ;
                if(count >= 2){
                    break ;
                }
            }
            for(; count < 2; count++){
                bs[index++] = 0 ;
            }
            ByteUtil.string2BCD_BE(bs, cvo.orderNo, index) ;
            index += 8 ;
            GlCreate.createDt(bs, index);
            index += 6 ;
            bs[index++] = 0 ;//秒
            bs[index++] = ByteUtil.int2BCD_LE(cvo.minute)[0] ;
            bs[index++] = ByteUtil.int2BCD_LE(cvo.hour)[0] ;
            bs[index++] = ByteUtil.int2BCD_LE(cvo.day)[0] ;
            bs[index++] = ByteUtil.int2BCD_LE(cvo.month)[0] ;
            bs[index++] = ByteUtil.int2BCD_LE(cvo.year)[0] ;
            bTemp = ByteUtil.int2BCD_LE(cvo.minutes) ;
            bTempLen = bTemp.length ;
            count = 0 ;
            for(int i = 0 ; i < bTempLen; i++){
                bs[index++] = bTemp[i] ;
                count ++ ;
                if(count >= 2){
                    break ;
                }
            }
            for(; count < 2; count++){
                bs[index++] = 0 ;
            }
            GlCreate.createPw(bs, index);
            index += 2 ;
            GlCreate.createS2D(bs, index) ;
            index += 4 ;
            bs[index] = 0 ; //时延
            bytes = ByteUtil.bytesMerge(bytes, bs) ;
        }else{
            throw new Exception("下行命令参数据为null") ;
        }
        GlCreate.createLen(bytes);//长度放字节数组中
        byte[] bsTail = GlCreate.createCrcTail(bytes) ;//CRC和尾
        bytes = ByteUtil.bytesMerge(bytes, bsTail) ;
        return bytes ;
    }
}
pipIrr-platform/pipIrr-common/src/main/java/com/dy/common/mw/protocol/p206V202404/parse/Cd_38_Down.java
New file
@@ -0,0 +1,266 @@
package com.dy.common.mw.protocol.p206V202404.parse;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.dy.common.mw.protocol.*;
import com.dy.common.mw.protocol.p206V202404.CodeV202404;
import com.dy.common.mw.protocol.p206V202404.ParseParamsForDownV202404;
import com.dy.common.mw.protocol.p206V202404.downVos.ComCd38Vo;
import com.dy.common.mw.protocol.p206V202404.parse.global.GlCreate;
import com.dy.common.util.ByteUtil;
import com.dy.common.util.NumUtil;
@AnnotationCodeDown(ifAny={
        CodeV202404.cd_38
})
public class Cd_38_Down implements CodeParse {
    @Override
    public MidResult[] parse(Boolean isLowPower, CodeParseParams params, CodeParseCallback callback) throws Exception {
        ParseParamsForDownV202404 para = (ParseParamsForDownV202404) params ;
        byte[] bs = this.doParse(para) ;
        MidResultToRtu midRs = new MidResultToRtu() ;
        midRs.protocolName = para.protocolName ;//协议名称
        midRs.protocolVersion = para.protocolVersion ;//协议版本号
        midRs.rtuResultSendWebUrl = para.rtuResultSendWebUrl ;
        midRs.rtuAddr = para.rtuAddr ;//Rtu地址
        midRs.commandId = para.commandId ;//命令ID,发起命令的客户端(web端)生成,以匹配命令结果
        midRs.downCode = para.commandCode ;//下行命令功能码;
        midRs.downCodeName = CodeV202404.getCodeName(para.commandCode) ;//下行命令功能码名称;
        midRs.downBuffer = bs ;//下行命令数据
        midRs.downBufHex = ByteUtil.bytes2Hex(bs, true) ;//下行命令数据十六进制形式
        midRs.hasResponse = true ;//是否有应答
        midRs.maxSendTimes = null ;//命令最大发送次数(当收不到应答时,将重发),如果不设置,命令缓存器进行补充设置
        midRs.isCachForOffLine = false ;//RTU不在线,命令是否缓存,低功耗时为true
        midRs.isSendFirst = false ;//命令应答,首先发送,防止RTU重新上报
        if(isLowPower != null && isLowPower.booleanValue()){
            //低功耗时,尽快发送
            midRs.isQuickSend = true ;
        }
        return new MidResult[]{midRs} ;
    }
    /**
     * 构造下行数据
     * @param para 参数
     * @return 字节数组
     * @throws Exception 异常
     */
    public byte[] doParse(ParseParamsForDownV202404 para) throws Exception {
        byte[] bytes = GlCreate.createStart2Cd(para.rtuAddr, para.commandCode);
        if(para.param != null){
            JSONObject obj = (JSONObject)para.param;
            String json = obj.toJSONString();
            ComCd38Vo cvo = JSON.parseObject(json, ComCd38Vo.class) ;
            if(cvo == null){
                throw new Exception("json转ComCd35Vo为null") ;
            }
            if(cvo.waterRemain != null){
                if(cvo.waterRemain < 0 || cvo.waterRemain > 99999999.99){
                    throw new Exception("用户剩余水量必须是0~99999999.99范围内的数据") ;
                }
            }
            if(cvo.moneyRemain != null){
                if(cvo.moneyRemain < 0 || cvo.moneyRemain > 999999.99){
                    throw new Exception("用户剩余金额必须是0~999999.99范围内的数据") ;
                }
            }
            if(cvo.waterPrice != null){
                if(cvo.waterPrice < 0 || cvo.waterPrice > 99.99){
                    throw new Exception("水量单价必须是0~99.99范围内的数据") ;
                }
            }
            if(cvo.elePrice != null){
                if(cvo.elePrice < 0 || cvo.elePrice > 99.99){
                    throw new Exception("电量单价必须是0~99.99范围内的数据") ;
                }
            }
            if(!NumUtil.isPlusIntNumber(cvo.orderNo)){
                throw new Exception("订单号必须是16位数字") ;
            }
            if(cvo.orderNo.length() != 16){
                throw new Exception("订单号必须是16位数字") ;
            }
            if(cvo.year == null){
                throw new Exception("计划开阀时间---年不能为空") ;
            }
            if(cvo.year < 24 || cvo.year > 9999){
                throw new Exception("计划开阀时间---年不正确") ;
            }
            if(cvo.year > 99 && cvo.year < 2024){
                throw new Exception("计划开阀时间---年不正确") ;
            }
            if(cvo.month == null){
                throw new Exception("计划开阀时间---月不能为空") ;
            }
            if(cvo.month < 1 || cvo.month > 12){
                throw new Exception("计划开阀时间---月不正确") ;
            }
            if(cvo.day == null){
                throw new Exception("计划开阀时间---日不能为空") ;
            }
            if(cvo.day < 1 || cvo.day > 31){
                throw new Exception("计划开阀时间---日不正确") ;
            }
            if(cvo.hour == null){
                throw new Exception("计划开阀时间---时不能为空") ;
            }
            if(cvo.hour < 0 || cvo.hour > 23){
                throw new Exception("计划开阀时间---时不正确") ;
            }
            if(cvo.minute == null){
                throw new Exception("计划开阀时间---时不能为空") ;
            }
            if(cvo.minute < 0 || cvo.minute > 59){
                throw new Exception("计划开阀时间---分不正确") ;
            }
            if(cvo.waterAmount == null || cvo.waterAmount == 0.0){
                throw new Exception("预用水量不能为空或为0") ;
            }
            if(cvo.waterAmount < 0 || cvo.waterAmount > 9999){
                throw new Exception("预用水量取值范围是0~9999m3") ;
            }
            byte[] bs = new byte[53] ;
            int index = 0 ;
            bs[index] = (byte)(Integer.parseInt(cvo.controllerType, 16));
            index ++ ;
            bs[index] = cvo.projectNo.byteValue() ;
            index ++ ;
            GlCreate.createValveOrPump(cvo.controllerType, bs, index) ;
            index ++ ;
            GlCreate.createIcCardNo(cvo.icCardNo, bs, index);
            index += 8 ;
            if(cvo.waterRemain == null){
                cvo.waterRemain = 0.0 ;
            }
            String strTemp = "" + Double.valueOf(cvo.waterRemain * 100).intValue() ;
            byte[] bTemp = ByteUtil.string2BCD_LE(strTemp) ;
            int bTempLen = bTemp.length ;
            int count = 0 ;
            for(int i = 0 ; i < bTempLen; i++){
                bs[index++] = bTemp[i] ;
                count ++ ;
                if(count >= 5){
                    break ;
                }
            }
            for(; count < 5; count++){
                bs[index++] = 0 ;
            }
            if(cvo.moneyRemain == null){
                cvo.moneyRemain = 0.0 ;
            }
            strTemp = "" + (Double.valueOf(cvo.moneyRemain * 10000)).intValue() ;
            bTemp = ByteUtil.string2BCD_LE(strTemp) ;
            bTempLen = bTemp.length ;
            count = 0 ;
            for(int i = 0 ; i < bTempLen; i++){
                bs[index++] = bTemp[i] ;
                count ++ ;
                if(count >= 4){
                    break ;
                }
            }
            for(; count < 4; count++){
                bs[index++] = 0 ;
            }
            if(cvo.waterPrice == null){
                cvo.waterPrice = 0.0 ;
            }
            strTemp = "" + (Double.valueOf(cvo.waterPrice * 100)).intValue() ;
            bTemp = ByteUtil.string2BCD_LE(strTemp) ;
            bTempLen = bTemp.length ;
            count = 0 ;
            for(int i = 0 ; i < bTempLen; i++){
                bs[index++] = bTemp[i] ;
                count ++ ;
                if(count >= 2){
                    break ;
                }
            }
            for(; count < 2; count++){
                bs[index++] = 0 ;
            }
            if(cvo.elePrice == null){
                cvo.elePrice = 0.0 ;
            }
            strTemp = "" + (Double.valueOf(cvo.elePrice * 100)).intValue() ;
            bTemp = ByteUtil.string2BCD_LE(strTemp) ;
            bTempLen = bTemp.length ;
            count = 0 ;
            for(int i = 0 ; i < bTempLen; i++){
                bs[index++] = bTemp[i] ;
                count ++ ;
                if(count >= 2){
                    break ;
                }
            }
            for(; count < 2; count++){
                bs[index++] = 0 ;
            }
            ByteUtil.string2BCD_BE(bs, cvo.orderNo, index) ;
            index += 8 ;
            GlCreate.createDt(bs, index);
            index += 6 ;
            bs[index++] = 0 ;//秒
            bs[index++] = ByteUtil.int2BCD_LE(cvo.minute)[0] ;
            bs[index++] = ByteUtil.int2BCD_LE(cvo.hour)[0] ;
            bs[index++] = ByteUtil.int2BCD_LE(cvo.day)[0] ;
            bs[index++] = ByteUtil.int2BCD_LE(cvo.month)[0] ;
            bs[index++] = ByteUtil.int2BCD_LE(cvo.year)[0] ;
            bTemp = ByteUtil.int2BCD_LE(cvo.waterAmount) ;
            bTempLen = bTemp.length ;
            count = 0 ;
            for(int i = 0 ; i < bTempLen; i++){
                bs[index++] = bTemp[i] ;
                count ++ ;
                if(count >= 2){
                    break ;
                }
            }
            for(; count < 2; count++){
                bs[index++] = 0 ;
            }
            GlCreate.createPw(bs, index);
            index += 2 ;
            GlCreate.createS2D(bs, index) ;
            index += 4 ;
            bs[index] = 0 ; //时延
            bytes = ByteUtil.bytesMerge(bytes, bs) ;
        }else{
            throw new Exception("下行命令参数据为null") ;
        }
        GlCreate.createLen(bytes);//长度放字节数组中
        byte[] bsTail = GlCreate.createCrcTail(bytes) ;//CRC和尾
        bytes = ByteUtil.bytesMerge(bytes, bsTail) ;
        return bytes ;
    }
}
pipIrr-platform/pipIrr-common/src/main/java/com/dy/common/mw/protocol/p206V202404/parse/Cd_93_A3_Up.java
@@ -4,13 +4,14 @@
import com.dy.common.mw.protocol.*;
import com.dy.common.mw.protocol.p206V202404.*;
import com.dy.common.mw.protocol.p206V202404.parse.global.GlParse;
import com.dy.common.mw.protocol.p206V202404.upVos.DataCd93_A3Vo;
import com.dy.common.mw.protocol.p206V202404.upVos.DataCd93_9D_A3Vo;
import com.dy.common.mw.protocol.rtuState.ValveStateInfo;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
@AnnotationCodeUp(ifAny={
        CodeV202404.cd_93,
        CodeV202404.cd_9D,
        CodeV202404.cd_A3
})
@SuppressWarnings("unused")
@@ -46,7 +47,7 @@
        callback.callback(midRs.reportOrResponse_trueOrFalse, para.data.subData==null?null:((DataV202404)(para.data.subData)).subData);
        if(para.data != null && para.data.getSubData() != null){
            DataCd93_A3Vo subData = (DataCd93_A3Vo)((DataV202404)para.data.getSubData()).subData ;
            DataCd93_9D_A3Vo subData = (DataCd93_9D_A3Vo)((DataV202404)para.data.getSubData()).subData ;
            //opResult ;//关泵/阀结果: 0x00:成功 0x81:失败
            callback.notify(new ValveStateInfo(subData.clResult.byteValue()==0?false:true));
        }
@@ -63,7 +64,7 @@
     */
    protected void doParse(byte[] bs, int bsLen, String dataCode, Data data) throws Exception {
        DataV202404 dV202404 = (DataV202404)data.getSubData() ;
        DataCd93_A3Vo cdData = new DataCd93_A3Vo(CodeV202404.getCodeName(dataCode)) ;
        DataCd93_9D_A3Vo cdData = new DataCd93_9D_A3Vo(CodeV202404.getCodeName(dataCode)) ;
        dV202404.subData = cdData ;
        GlParse.parseCd93A3(bs, cdData) ;
pipIrr-platform/pipIrr-common/src/main/java/com/dy/common/mw/protocol/p206V202404/parse/Cd_9D_Down.java
New file
@@ -0,0 +1,120 @@
package com.dy.common.mw.protocol.p206V202404.parse;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.dy.common.mw.protocol.*;
import com.dy.common.mw.protocol.p206V202404.CodeV202404;
import com.dy.common.mw.protocol.p206V202404.ParseParamsForDownV202404;
import com.dy.common.mw.protocol.p206V202404.downVos.ComCd92_A2Vo;
import com.dy.common.mw.protocol.p206V202404.downVos.ComCd9DVo;
import com.dy.common.mw.protocol.p206V202404.parse.global.GlCreate;
import com.dy.common.util.ByteUtil;
import com.dy.common.util.NumUtil;
@AnnotationCodeDown(ifAny={
        CodeV202404.cd_9D
})
public class Cd_9D_Down implements CodeParse {
    @Override
    public MidResult[] parse(Boolean isLowPower, CodeParseParams params, CodeParseCallback callback) throws Exception {
        ParseParamsForDownV202404 para = (ParseParamsForDownV202404) params ;
        byte[] bs = this.doParse(para) ;
        MidResultToRtu midRs = new MidResultToRtu() ;
        midRs.protocolName = para.protocolName ;//协议名称
        midRs.protocolVersion = para.protocolVersion ;//协议版本号
        midRs.rtuResultSendWebUrl = para.rtuResultSendWebUrl ;
        midRs.rtuAddr = para.rtuAddr ;//Rtu地址
        midRs.commandId = para.commandId ;//命令ID,发起命令的客户端(web端)生成,以匹配命令结果
        midRs.downCode = para.commandCode ;//下行命令功能码;
        midRs.downCodeName = CodeV202404.getCodeName(para.commandCode) ;//下行命令功能码名称;
        midRs.downBuffer = bs ;//下行命令数据
        midRs.downBufHex = ByteUtil.bytes2Hex(bs, true) ;//下行命令数据十六进制形式
        midRs.hasResponse = true ;//是否有应答
        midRs.maxSendTimes = null ;//命令最大发送次数(当收不到应答时,将重发),如果不设置,命令缓存器进行补充设置
        midRs.isCachForOffLine = false ;//RTU不在线,命令是否缓存,低功耗时为true
        midRs.isSendFirst = false ;//命令应答,首先发送,防止RTU重新上报
        if(isLowPower != null && isLowPower.booleanValue()){
            //低功耗时,尽快发送
            midRs.isQuickSend = true ;
        }
        return new MidResult[]{midRs} ;
    }
    /**
     * 构造下行数据
     * @param para 参数
     * @return 字节数组
     * @throws Exception 异常
     */
    public byte[] doParse(ParseParamsForDownV202404 para) throws Exception {
        byte[] bytes = GlCreate.createStart2Cd(para.rtuAddr, para.commandCode);
        if(para.param != null){
            JSONObject obj = (JSONObject)para.param;
            String json = obj.toJSONString();
            ComCd9DVo cvo = JSON.parseObject(json, ComCd9DVo.class) ;
            if(cvo == null){
                throw new Exception("json转ComCd9DVo为null") ;
            }
            if(cvo.icCardAddr == null || cvo.icCardAddr.trim().equals("")){
                throw new Exception("用户IC卡地址必须提供") ;
            }
            if(cvo.icCardNo == null || cvo.icCardNo.trim().equals("")){
                throw new Exception("用户IC卡号必须提供") ;
            }
            if(cvo.orderNo == null || cvo.orderNo.trim().equals("")){
                throw new Exception("订单号必须提供") ;
            }
            if(!NumUtil.isPlusIntNumber(cvo.orderNo)){
                throw new Exception("订单号必须是16位数字") ;
            }
            if(cvo.orderNo.length() != 16){
                throw new Exception("订单号必须是16位数字") ;
            }
            byte[] bs = new byte[29] ;
            int index = 0 ;
            bs[index] = (byte)(Integer.parseInt(cvo.controllerType, 16));
            index ++ ;
            bs[index] = cvo.projectNo.byteValue() ;
            index ++ ;
            GlCreate.createValveOrPump(cvo.controllerType, bs, index) ;
            index ++ ;
            GlCreate.createIcCardAddr(cvo.icCardAddr, bs, index) ;
            index += 4 ;
            GlCreate.createIcCardNo(cvo.icCardNo, bs, index);
            index += 8 ;
            ByteUtil.string2BCD_BE(bs, cvo.orderNo, index) ;
            index += 8 ;
            GlCreate.createPw(bs, index);
            index += 2 ;
            GlCreate.createS2D(bs, index) ;
            index += 4 ;
            bs[index] = 0 ; //时延
            bytes = ByteUtil.bytesMerge(bytes, bs) ;
        }else{
            throw new Exception("下行命令参数据为null") ;
        }
        GlCreate.createLen(bytes);//长度放字节数组中
        byte[] bsTail = GlCreate.createCrcTail(bytes) ;//CRC和尾
        bytes = ByteUtil.bytesMerge(bytes, bsTail) ;
        return bytes ;
    }
}
pipIrr-platform/pipIrr-common/src/main/java/com/dy/common/mw/protocol/p206V202404/parse/global/GlParse.java
@@ -306,7 +306,7 @@
     * @param cdData
     * @throws Exception
     */
    public static void parseCd93A3(byte[] bs, DataCd93_A3Vo cdData) throws Exception {
    public static void parseCd93A3(byte[] bs, DataCd93_9D_A3Vo cdData) throws Exception {
        int index = ProtocolConstantV206V202404.dataIndex ;
        cdData.controllerType = ByteUtil.bytes2Hex(bs, false, index, 1) ;
pipIrr-platform/pipIrr-common/src/main/java/com/dy/common/mw/protocol/p206V202404/upVos/DataCd35_36Vo.java
New file
@@ -0,0 +1,114 @@
package com.dy.common.mw.protocol.p206V202404.upVos;
import com.dy.common.mw.protocol.UpComResVo;
import com.dy.common.mw.protocol.p206V202404.CodeV202404;
import com.dy.common.mw.protocol.p206V202404.CommonV202404;
import lombok.Data;
//APP端远程定时开启水泵/阀门
@Data
public class DataCd35_36Vo implements UpComResVo {
    public String controllerType;//控制器类型
    public Integer projectNo ;//项目编号
    public String icCardNo ;//IC卡编号(17位数字)
    public String orderNo ;//订单号(16位数字)
    //public String opDt ;//开泵/阀时间(yyyy-mm-dd HH:MM:SS)
    public Byte opType ;//开阀类型
    public Byte opResult ;//开启泵/阀结果: 0x01:成功 0x81:失败
    public String comName ;//命令名称
    //无参构造函数,设置命令名称
    public DataCd35_36Vo(){
        this.comName = CodeV202404.getCodeName(CodeV202404.cd_35) ;
    }
    //有参构造函数,设置命令名称
    public DataCd35_36Vo(String comName){
        this.comName = comName ;
    }
    //重写toString方法,返回DataCd35Vo对象的字符串表示
    public String toString(){
        StringBuffer sb = new StringBuffer() ;
        sb.append("      " + comName + " : \n") ;
        sb.append("      控制器类型 : ") ;
        sb.append(CommonV202404.ctrlDevType(controllerType)) ;
        sb.append("\n") ;
        sb.append("      项目编号 : ") ;
        sb.append(projectNo == null?"未知":projectNo) ;
        sb.append("\n") ;
        sb.append("      IC卡编号 : ") ;
        sb.append(icCardNo == null?"未知":icCardNo) ;
        sb.append("\n") ;
        sb.append("      订单号 : ") ;
        sb.append(orderNo == null?"未知":orderNo) ;
        sb.append("\n") ;
        /*
        sb.append("      开泵/阀时间 : ") ;
        sb.append(opDt == null?"未知":opDt) ;
        sb.append("\n") ;
         */
        sb.append("      开启泵/阀类型 : ") ;
        sb.append(opType == null?"未知":(opType.byteValue() == 0x02 ? "平台":"用户")) ;
        sb.append("\n") ;
        sb.append("      开启泵/阀结果 : ") ;
        sb.append(opResult == null?"未知":(opResult.byteValue() == 0x01 ? "成功":"失败")) ;
        sb.append("\n") ;
        return sb.toString() ;
    }
    //重写toStr方法,返回DataCd35Vo对象的字符串表示,根据showBase参数决定是否显示基础信息
    public String toStr(boolean showBase){
        StringBuffer sb = new StringBuffer() ;
        if(showBase){
            sb.append(comName + " : \n") ;
            sb.append("控制器类型 : ") ;
            sb.append(CommonV202404.ctrlDevType(controllerType)) ;
            sb.append("\n") ;
            sb.append("项目编号 : ") ;
            sb.append(projectNo == null?"未知":projectNo) ;
            sb.append("\n") ;
        }
        sb.append("IC卡编号 : ") ;
        sb.append(icCardNo == null?"未知":icCardNo) ;
        sb.append("\n") ;
        sb.append("订单号 : ") ;
        sb.append(orderNo == null?"未知":orderNo) ;
        sb.append("\n") ;
        /*
        sb.append("开泵/阀时间 : ") ;
        sb.append(opDt == null?"未知":opDt) ;
        sb.append("\n") ;
         */
        sb.append("开启泵/阀类型 : ") ;
        sb.append(opType == null?"未知":(opType.byteValue() == 0x02 ? "平台":"用户")) ;
        sb.append("\n") ;
        sb.append("开启泵/阀结果 : ") ;
        sb.append(opResult == null?"未知":(opResult.byteValue() == 0x01 ? "成功":"失败")) ;
        sb.append("\n") ;
        return sb.toString() ;
    }
    //重写comLog方法,返回DataCd35Vo对象的字符串表示,用于记录日志
    public String comLog(){
        StringBuilder sb = new StringBuilder() ;
        sb.append("远程开阀命令回复:\n");
        sb.append(opResult == null?"未知":(opResult.byteValue() == 0x01 ? "成功":"失败"));
        sb.append("\n");
        return sb.toString() ;
    }
    //重写comLog方法,根据code参数返回DataCd35Vo对象的字符串表示,用于记录日志
    @Override
    public String comLog(String code) {
        return null;
    }
}
pipIrr-platform/pipIrr-common/src/main/java/com/dy/common/mw/protocol/p206V202404/upVos/DataCd92_A2Vo.java
@@ -16,7 +16,7 @@
    //2025-05-13江海叫删除
    //public String opDt ;//开泵/阀时间(yyyy-mm-dd HH:MM:SS)
    public Byte opType ;//开阀类型
    public Byte opResult ;//开启泵/阀结果: 0x00:成功 0x81:失败
    public Byte opResult ;//开启泵/阀结果: 0x01:成功 0x81:失败
    public String comName ;//命令名称
pipIrr-platform/pipIrr-common/src/main/java/com/dy/common/mw/protocol/p206V202404/upVos/DataCd93_9D_A3Vo.java
File was renamed from pipIrr-platform/pipIrr-common/src/main/java/com/dy/common/mw/protocol/p206V202404/upVos/DataCd93_A3Vo.java
@@ -9,7 +9,7 @@
//平台/APP远程关闭水泵/阀门   +  刷卡关泵/阀上报
@Data
@EqualsAndHashCode(callSuper=false)
public class DataCd93_A3Vo extends AlarmVo implements UpComResVo {
public class DataCd93_9D_A3Vo extends AlarmVo implements UpComResVo {
    public String controllerType;//控制器类型
    public Integer projectNo ;//项目编号
@@ -30,10 +30,10 @@
    public Integer thisDuration;//本次使用时间长, 单位:分钟
    public String comName ;//命令名称
    public DataCd93_A3Vo(){
    public DataCd93_9D_A3Vo(){
        this.comName = CodeV202404.getCodeName(CodeV202404.cd_93) ;
    }
    public DataCd93_A3Vo(String comName){
    public DataCd93_9D_A3Vo(String comName){
        this.comName = comName ;
    }
pipIrr-platform/pipIrr-global/src/main/java/com/dy/pipIrrGlobal/command/CommandSv.java
@@ -16,6 +16,7 @@
import com.dy.pipIrrGlobal.pojoPr.PrController;
import com.dy.pipIrrGlobal.pojoRm.RmCommandHistory;
import com.dy.pipIrrGlobal.rtuMw.Web2RtuMw;
import org.springframework.transaction.annotation.Transactional;
import java.util.Date;
@@ -81,6 +82,7 @@
     * @param operator
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public RmCommandHistory saveComHistoryPo(RmCommandHistoryMapper rmCommandHistoryDao,
                                             Long comId,
                                             String protocol,
pipIrr-platform/pipIrr-global/src/main/java/com/dy/pipIrrGlobal/daoRm/RmCommandOpenMapper.java
New file
@@ -0,0 +1,31 @@
package com.dy.pipIrrGlobal.daoRm;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.dy.pipIrrGlobal.pojoRm.RmCommandOpen;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
/**
 * @Author: liurunyu
 * @Date: 2025/6/27 10:31
 * @Description
 */
@Mapper
public interface RmCommandOpenMapper extends BaseMapper<RmCommandOpen> {
    int deleteByPrimaryKey(Long id);
    int insert(RmCommandOpen record);
    int insertSelective(RmCommandOpen record);
    RmCommandOpen selectByPrimaryKey(Long id);
    List<RmCommandOpen> selectByIntakeId(Long intakeId);
    int updateByPrimaryKeySelective(RmCommandOpen record);
    int updateByPrimaryKey(RmCommandOpen record);
}
pipIrr-platform/pipIrr-global/src/main/java/com/dy/pipIrrGlobal/daoRm/RmManureHistoryMapper.java
@@ -1,7 +1,9 @@
package com.dy.pipIrrGlobal.daoRm;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.dy.pipIrrGlobal.pojoRm.RmManureHistory;
import com.dy.pipIrrGlobal.voRm.VoManure;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
import java.util.Map;
@@ -11,7 +13,8 @@
 * @Date: 2025/6/25 10:03
 * @Description
 */
public interface RmManureHistoryMapper {
@Mapper
public interface RmManureHistoryMapper extends BaseMapper<RmManureHistory> {
    int deleteByPrimaryKey(Long id);
    int insert(RmManureHistory record);
pipIrr-platform/pipIrr-global/src/main/java/com/dy/pipIrrGlobal/daoRm/RmManureLastMapper.java
@@ -1,7 +1,9 @@
package com.dy.pipIrrGlobal.daoRm;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.dy.pipIrrGlobal.pojoRm.RmManureLast;
import com.dy.pipIrrGlobal.voRm.VoManure;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
@@ -12,7 +14,8 @@
 * @Date: 2025/6/25 10:03
 * @Description
 */
public interface RmManureLastMapper {
@Mapper
public interface RmManureLastMapper extends BaseMapper<RmManureLast> {
    int deleteByPrimaryKey(Long id);
    int insert(RmManureLast record);
pipIrr-platform/pipIrr-global/src/main/java/com/dy/pipIrrGlobal/daoRm/RmSoilDayMapper.java
@@ -1,9 +1,12 @@
package com.dy.pipIrrGlobal.daoRm;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.dy.pipIrrGlobal.pojoRm.RmManureLast;
import com.dy.pipIrrGlobal.pojoRm.RmSoilDay;
import com.dy.pipIrrGlobal.pojoRm.RmSoilLast;
import com.dy.pipIrrGlobal.voRm.VoSoil;
import com.dy.pipIrrGlobal.voRm.VoSoilDay;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
@@ -14,7 +17,8 @@
 * @Date: 2025/6/25 10:04
 * @Description
 */
public interface RmSoilDayMapper {
@Mapper
public interface RmSoilDayMapper extends BaseMapper<RmSoilDay> {
    int deleteByPrimaryKey(Long id);
    int insert(RmSoilDay record);
@@ -30,6 +34,12 @@
     * @return
     */
    List<VoSoilDay> selectOneBySoilId(@Param("soilId") Long soilId, @Param("ymd") Integer ymd);
   /**
     * 根据指定条件查询记录
     * @param soilId
     * @return
     */
    List<VoSoilDay> selectOneMonthBySoilId(@Param("soilId") Long soilId, @Param("ymdStart") Integer ymdStart, @Param("ymdEnd") Integer ymdEnd);
    /**
     * 根据指定条件查询记录数量
pipIrr-platform/pipIrr-global/src/main/java/com/dy/pipIrrGlobal/daoRm/RmSoilHistoryMapper.java
@@ -1,7 +1,10 @@
package com.dy.pipIrrGlobal.daoRm;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.dy.pipIrrGlobal.pojoRm.RmSoilDay;
import com.dy.pipIrrGlobal.pojoRm.RmSoilHistory;
import com.dy.pipIrrGlobal.voRm.VoSoil;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
import java.util.Map;
@@ -11,7 +14,8 @@
 * @Date: 2025/6/25 10:04
 * @Description
 */
public interface RmSoilHistoryMapper {
@Mapper
public interface RmSoilHistoryMapper extends BaseMapper<RmSoilHistory> {
    int deleteByPrimaryKey(Long id);
    int insert(RmSoilHistory record);
pipIrr-platform/pipIrr-global/src/main/java/com/dy/pipIrrGlobal/daoRm/RmSoilLastMapper.java
@@ -1,7 +1,10 @@
package com.dy.pipIrrGlobal.daoRm;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.dy.pipIrrGlobal.pojoRm.RmSoilHistory;
import com.dy.pipIrrGlobal.pojoRm.RmSoilLast;
import com.dy.pipIrrGlobal.voRm.VoSoil;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
@@ -12,7 +15,8 @@
 * @Date: 2025/6/25 10:04
 * @Description
 */
public interface RmSoilLastMapper {
@Mapper
public interface RmSoilLastMapper extends BaseMapper<RmSoilLast> {
    int deleteByPrimaryKey(Long id);
    int insert(RmSoilLast record);
pipIrr-platform/pipIrr-global/src/main/java/com/dy/pipIrrGlobal/daoRm/RmWeatherHistoryMapper.java
@@ -1,7 +1,10 @@
package com.dy.pipIrrGlobal.daoRm;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.dy.pipIrrGlobal.pojoRm.RmSoilLast;
import com.dy.pipIrrGlobal.pojoRm.RmWeatherHistory;
import com.dy.pipIrrGlobal.voRm.VoWeather;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
import java.util.Map;
@@ -11,7 +14,8 @@
 * @Date: 2025/6/25 10:39
 * @Description
 */
public interface RmWeatherHistoryMapper {
@Mapper
public interface RmWeatherHistoryMapper extends BaseMapper<RmWeatherHistory> {
    int deleteByPrimaryKey(Long id);
    int insert(RmWeatherHistory record);
pipIrr-platform/pipIrr-global/src/main/java/com/dy/pipIrrGlobal/daoRm/RmWeatherLastMapper.java
@@ -1,7 +1,10 @@
package com.dy.pipIrrGlobal.daoRm;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.dy.pipIrrGlobal.pojoRm.RmWeatherHistory;
import com.dy.pipIrrGlobal.pojoRm.RmWeatherLast;
import com.dy.pipIrrGlobal.voRm.VoWeather;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
@@ -12,7 +15,8 @@
 * @Date: 2025/6/25 10:39
 * @Description
 */
public interface RmWeatherLastMapper {
@Mapper
public interface RmWeatherLastMapper extends BaseMapper<RmWeatherLast> {
    int deleteByPrimaryKey(Long id);
    int insert(RmWeatherLast record);
pipIrr-platform/pipIrr-global/src/main/java/com/dy/pipIrrGlobal/pojoRm/RmCommandOpen.java
New file
@@ -0,0 +1,82 @@
package com.dy.pipIrrGlobal.pojoRm;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.dy.common.po.BaseEntity;
import lombok.*;
import java.util.Date;
/**
 * @Author: liurunyu
 * @Date: 2025/6/27 10:31
 * @Description
 */
@TableName(value = "rm_command_open", autoResultMap = true)
@Data
@Builder
@ToString
@NoArgsConstructor
@AllArgsConstructor
public class RmCommandOpen implements BaseEntity {
    public static final long serialVersionUID = 202506271017001L;
    /**
     * 主键
     */
    @TableId(type = IdType.INPUT)
    public Long id;
    /**
     * 命令id
     */
    public Long comId;
    /**
     * 功能码
     */
    public String commandCode;
    /**
     * 功能命令名称
     */
    public String commandName;
    /**
     * 取水口id
     */
    public Long intakeId;
    /**
     * 控制器地址
     */
    public String rtuAddr;
    /**
     * 协议名称
     */
    public String protocol;
    /**
     * 虚拟卡号
     */
    public Long vcNum;
    /**
     * 订单号
     */
    public String orderNo;
    /**
     * 命令发送时间
     */
    public Date sendTime;
    /**
     * 操作人(用户)
     */
    public Long operator;
}
pipIrr-platform/pipIrr-global/src/main/java/com/dy/pipIrrGlobal/voRm/VoManure.java
@@ -3,6 +3,7 @@
import com.alibaba.fastjson2.annotation.JSONField;
import com.alibaba.fastjson2.writer.ObjectWriterImplToString;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonPropertyOrder;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@@ -14,6 +15,13 @@
 * @Description
 */
@Data
@JsonPropertyOrder({
        "id", "manureId", "manureName", "dt", "alarm",
        "stirRunning1", "stirRunning2", "stirRunning3", "stirRunning4",
        "injectRunning", "irrRunning",
        "manureFlow", "manureTime", "stirTime",
        "stirDuration", "injectDuration"
})
public class VoManure  {
    public static final long serialVersionUID = 202506251634001L;
@@ -34,7 +42,7 @@
     * 水肥机名称
     */
    @Schema(description = "水肥机名称", requiredMode = Schema.RequiredMode.NOT_REQUIRED)
    public Long manureName;
    public String manureName;
    /**
pipIrr-platform/pipIrr-global/src/main/java/com/dy/pipIrrGlobal/voRm/VoSoil.java
@@ -3,6 +3,7 @@
import com.alibaba.fastjson2.annotation.JSONField;
import com.alibaba.fastjson2.writer.ObjectWriterImplToString;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonPropertyOrder;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@@ -14,6 +15,11 @@
 * @Description
 */
@Data
@JsonPropertyOrder({
        "id", "soilId", "soilName", "dt",
        "soilHumidity1", "soilHumidity2", "soilHumidity3", "soilHumidity4", "soilHumidity5",
        "soilTemperature1", "soilTemperature2", "soilTemperature3", "soilTemperature4", "soilTemperature5"
})
public class VoSoil {
    public static final long serialVersionUID = 202506260903001L;
@@ -34,7 +40,7 @@
     * 墒情站名称
     */
    @Schema(description = "墒情站名称", requiredMode = Schema.RequiredMode.NOT_REQUIRED)
    public Long soilName;
    public String soilName;
    /**
pipIrr-platform/pipIrr-global/src/main/java/com/dy/pipIrrGlobal/voRm/VoSoilDay.java
@@ -3,6 +3,7 @@
import com.alibaba.fastjson2.annotation.JSONField;
import com.alibaba.fastjson2.writer.ObjectWriterImplToString;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonPropertyOrder;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@@ -14,6 +15,11 @@
 * @Description
 */
@Data
@JsonPropertyOrder({
        "id", "soilId", "soilName", "dt",
        "soilHumidity1", "soilHumidity2", "soilHumidity3", "soilHumidity4", "soilHumidity5",
        "soilTemperature1", "soilTemperature2", "soilTemperature3", "soilTemperature4", "soilTemperature5"
})
public class VoSoilDay {
    public static final long serialVersionUID = 202506261020001L;
@@ -34,7 +40,7 @@
     * 墒情站名称
     */
    @Schema(description = "墒情站名称", requiredMode = Schema.RequiredMode.NOT_REQUIRED)
    public Long soilName;
    public String soilName;
    /**
pipIrr-platform/pipIrr-global/src/main/java/com/dy/pipIrrGlobal/voRm/VoWeather.java
@@ -3,6 +3,7 @@
import com.alibaba.fastjson2.annotation.JSONField;
import com.alibaba.fastjson2.writer.ObjectWriterImplToString;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonPropertyOrder;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@@ -14,6 +15,13 @@
 * @Description
 */
@Data
@JsonPropertyOrder({
        "id", "weatherId", "weatherName", "dt",
        "airTemperature", "airHumidity",
        "ultraviolet", "lightIntensity",
        "rainfall", "windSpeed",
        "windDirection", "windDirectionStr"
})
public class VoWeather {
    public static final long serialVersionUID = 202506260903001L;
@@ -34,7 +42,7 @@
     * 气象站名称
     */
    @Schema(description = "气象站名称", requiredMode = Schema.RequiredMode.NOT_REQUIRED)
    public Long weatherName;
    public String weatherName;
    /**
pipIrr-platform/pipIrr-global/src/main/resources/mapper/PrStManureMapper.xml
@@ -93,7 +93,7 @@
    select
    <include refid="part_Column_List" />
    FROM pr_st_manure
    WHERE deleted = 0 AND fbox_id=#{fbox_id,jdbcType=VARCHAR} AND no=#{fbox_id,jdbcType=INTEGER}
    WHERE deleted != 1 AND fbox_id=#{fbox_id,jdbcType=VARCHAR} AND no=#{no,jdbcType=INTEGER}
  </select>
  <delete id="deleteByPrimaryKey" parameterType="java.lang.Long">
pipIrr-platform/pipIrr-global/src/main/resources/mapper/PrStSoilMapper.xml
@@ -92,7 +92,7 @@
    select
    <include refid="part_Column_List" />
    FROM pr_st_soil
    WHERE deleted = 0 AND fbox_id=#{fbox_id,jdbcType=VARCHAR} AND no=#{fbox_id,jdbcType=INTEGER}
    WHERE deleted != 1 AND fbox_id=#{fbox_id,jdbcType=VARCHAR} AND no=#{no,jdbcType=INTEGER}
  </select>
  <delete id="deleteByPrimaryKey" parameterType="java.lang.Long">
pipIrr-platform/pipIrr-global/src/main/resources/mapper/PrStWeatherMapper.xml
@@ -86,7 +86,7 @@
    select
    <include refid="part_Column_List" />
    FROM pr_st_weather
    WHERE deleted = 0 AND fbox_id=#{fbox_id,jdbcType=VARCHAR} AND no=#{fbox_id,jdbcType=INTEGER}
    WHERE deleted != 1 AND fbox_id=#{fbox_id,jdbcType=VARCHAR} AND no=#{no,jdbcType=INTEGER}
  </select>
  <select id="selectAllSimple" resultType="com.dy.pipIrrGlobal.voPr.VoMqttSimple">
pipIrr-platform/pipIrr-global/src/main/resources/mapper/RmCommandOpenMapper.xml
New file
@@ -0,0 +1,181 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.dy.pipIrrGlobal.daoRm.RmCommandOpenMapper">
  <resultMap id="BaseResultMap" type="com.dy.pipIrrGlobal.pojoRm.RmCommandOpen">
    <!--@mbg.generated-->
    <!--@Table rm_command_open-->
    <id column="id" jdbcType="BIGINT" property="id" />
    <result column="com_id" jdbcType="BIGINT" property="comId" />
    <result column="command_code" jdbcType="VARCHAR" property="commandCode" />
    <result column="command_name" jdbcType="VARCHAR" property="commandName" />
    <result column="intake_id" jdbcType="BIGINT" property="intakeId" />
    <result column="rtu_addr" jdbcType="VARCHAR" property="rtuAddr" />
    <result column="protocol" jdbcType="VARCHAR" property="protocol" />
    <result column="vc_num" jdbcType="BIGINT" property="vcNum" />
    <result column="order_no" jdbcType="VARCHAR" property="orderNo" />
    <result column="send_time" jdbcType="TIMESTAMP" property="sendTime" />
    <result column="operator" jdbcType="BIGINT" property="operator" />
  </resultMap>
  <sql id="Base_Column_List">
    <!--@mbg.generated-->
    id, com_id, command_code, command_name, intake_id, rtu_addr, protocol, vc_num, order_no,
    send_time, `operator`
  </sql>
  <select id="selectByPrimaryKey" parameterType="java.lang.Long" resultMap="BaseResultMap">
    <!--@mbg.generated-->
    select
    <include refid="Base_Column_List" />
    from rm_command_open
    where id = #{id,jdbcType=BIGINT}
  </select>
  <select id="selectByIntakeId" parameterType="java.lang.Long" resultMap="BaseResultMap">
    <!--@mbg.generated-->
    select
    <include refid="Base_Column_List" />
    from rm_command_open
    where intake_id = #{intakeId,jdbcType=BIGINT}
    order by id DESC
  </select>
  <delete id="deleteByPrimaryKey" parameterType="java.lang.Long">
    <!--@mbg.generated-->
    delete from rm_command_open
    where id = #{id,jdbcType=BIGINT}
  </delete>
  <insert id="insert" parameterType="com.dy.pipIrrGlobal.pojoRm.RmCommandOpen">
    <!--@mbg.generated-->
    insert into rm_command_open (id, com_id, command_code,
      command_name, intake_id, rtu_addr,
      protocol, vc_num, order_no,
      send_time, `operator`)
    values (#{id,jdbcType=BIGINT}, #{comId,jdbcType=BIGINT}, #{commandCode,jdbcType=VARCHAR},
      #{commandName,jdbcType=VARCHAR}, #{intakeId,jdbcType=BIGINT}, #{rtuAddr,jdbcType=VARCHAR},
      #{protocol,jdbcType=VARCHAR}, #{vcNum,jdbcType=BIGINT}, #{orderNo,jdbcType=VARCHAR},
      #{sendTime,jdbcType=TIMESTAMP}, #{operator,jdbcType=BIGINT})
  </insert>
  <insert id="insertSelective" parameterType="com.dy.pipIrrGlobal.pojoRm.RmCommandOpen">
    <!--@mbg.generated-->
    insert into rm_command_open
    <trim prefix="(" suffix=")" suffixOverrides=",">
      <if test="id != null">
        id,
      </if>
      <if test="comId != null">
        com_id,
      </if>
      <if test="commandCode != null">
        command_code,
      </if>
      <if test="commandName != null">
        command_name,
      </if>
      <if test="intakeId != null">
        intake_id,
      </if>
      <if test="rtuAddr != null">
        rtu_addr,
      </if>
      <if test="protocol != null">
        protocol,
      </if>
      <if test="vcNum != null">
        vc_num,
      </if>
      <if test="orderNo != null">
        order_no,
      </if>
      <if test="sendTime != null">
        send_time,
      </if>
      <if test="operator != null">
        `operator`,
      </if>
    </trim>
    <trim prefix="values (" suffix=")" suffixOverrides=",">
      <if test="id != null">
        #{id,jdbcType=BIGINT},
      </if>
      <if test="comId != null">
        #{comId,jdbcType=BIGINT},
      </if>
      <if test="commandCode != null">
        #{commandCode,jdbcType=VARCHAR},
      </if>
      <if test="commandName != null">
        #{commandName,jdbcType=VARCHAR},
      </if>
      <if test="intakeId != null">
        #{intakeId,jdbcType=BIGINT},
      </if>
      <if test="rtuAddr != null">
        #{rtuAddr,jdbcType=VARCHAR},
      </if>
      <if test="protocol != null">
        #{protocol,jdbcType=VARCHAR},
      </if>
      <if test="vcNum != null">
        #{vcNum,jdbcType=BIGINT},
      </if>
      <if test="orderNo != null">
        #{orderNo,jdbcType=VARCHAR},
      </if>
      <if test="sendTime != null">
        #{sendTime,jdbcType=TIMESTAMP},
      </if>
      <if test="operator != null">
        #{operator,jdbcType=BIGINT},
      </if>
    </trim>
  </insert>
  <update id="updateByPrimaryKeySelective" parameterType="com.dy.pipIrrGlobal.pojoRm.RmCommandOpen">
    <!--@mbg.generated-->
    update rm_command_open
    <set>
      <if test="comId != null">
        com_id = #{comId,jdbcType=BIGINT},
      </if>
      <if test="commandCode != null">
        command_code = #{commandCode,jdbcType=VARCHAR},
      </if>
      <if test="commandName != null">
        command_name = #{commandName,jdbcType=VARCHAR},
      </if>
      <if test="intakeId != null">
        intake_id = #{intakeId,jdbcType=BIGINT},
      </if>
      <if test="rtuAddr != null">
        rtu_addr = #{rtuAddr,jdbcType=VARCHAR},
      </if>
      <if test="protocol != null">
        protocol = #{protocol,jdbcType=VARCHAR},
      </if>
      <if test="vcNum != null">
        vc_num = #{vcNum,jdbcType=BIGINT},
      </if>
      <if test="orderNo != null">
        order_no = #{orderNo,jdbcType=VARCHAR},
      </if>
      <if test="sendTime != null">
        send_time = #{sendTime,jdbcType=TIMESTAMP},
      </if>
      <if test="operator != null">
        `operator` = #{operator,jdbcType=BIGINT},
      </if>
    </set>
    where id = #{id,jdbcType=BIGINT}
  </update>
  <update id="updateByPrimaryKey" parameterType="com.dy.pipIrrGlobal.pojoRm.RmCommandOpen">
    <!--@mbg.generated-->
    update rm_command_open
    set com_id = #{comId,jdbcType=BIGINT},
      command_code = #{commandCode,jdbcType=VARCHAR},
      command_name = #{commandName,jdbcType=VARCHAR},
      intake_id = #{intakeId,jdbcType=BIGINT},
      rtu_addr = #{rtuAddr,jdbcType=VARCHAR},
      protocol = #{protocol,jdbcType=VARCHAR},
      vc_num = #{vcNum,jdbcType=BIGINT},
      order_no = #{orderNo,jdbcType=VARCHAR},
      send_time = #{sendTime,jdbcType=TIMESTAMP},
      `operator` = #{operator,jdbcType=BIGINT}
    where id = #{id,jdbcType=BIGINT}
  </update>
</mapper>
pipIrr-platform/pipIrr-global/src/main/resources/mapper/RmManureHistoryMapper.xml
@@ -25,6 +25,17 @@
    id, manure_id, dt, stir_running1, stir_running2, stir_running3, stir_running4, inject_running, 
    irr_running, alarm, manure_flow, manure_time, stir_time, stir_duration, inject_duration
  </sql>
  <sql id="Base_Column_List_with_alias">
    <!--@mbg.generated-->
    ${alias}.id, ${alias}.manure_id, ${alias}.dt,
    ${alias}.stir_running1, ${alias}.stir_running2,
    ${alias}.stir_running3, ${alias}.stir_running4,
    ${alias}.inject_running, ${alias}.irr_running,
    ${alias}.alarm, ${alias}.manure_flow,
    ${alias}.manure_time, ${alias}.stir_time,
    ${alias}.stir_duration, ${alias}.inject_duration
  </sql>
  <select id="selectByPrimaryKey" parameterType="java.lang.Long" resultMap="BaseResultMap">
    <!--@mbg.generated-->
    select 
@@ -48,7 +59,7 @@
      <if test = "name != null and name !=''">
        AND mtb.name LIKE CONCAT('%',#{name},'%')
      </if>
      <if test = "timeStart != null and timeStop != null">
      <if test = "timeStart != null and timeStart !='' and timeStop != null and timeStop != ''">
        AND htb.dt BETWEEN #{timeStart} AND #{timeStop}
      </if>
    </where>
@@ -57,7 +68,9 @@
  <!--根据指定条件查询历史记录-->
  <select id="selectSome" resultType="com.dy.pipIrrGlobal.voRm.VoManure">
    SELECT
    <include refid="Base_Column_List" />,
    <include refid="Base_Column_List_with_alias" >
      <property name="alias" value="htb"/>
    </include>,
    mtb.`name` AS manureName
    FROM rm_manure_history htb
    INNER JOIN pr_st_manure mtb ON mtb.id = htb.manure_id
@@ -71,7 +84,7 @@
      <if test = "name != null and name !=''">
        AND mtb.name LIKE CONCAT('%',#{name},'%')
      </if>
      <if test = "timeStart != null and timeStop != null">
      <if test = "timeStart != null and timeStart !='' and timeStop != null and timeStop != ''">
        AND htb.dt BETWEEN #{timeStart} AND #{timeStop}
      </if>
    </where>
pipIrr-platform/pipIrr-global/src/main/resources/mapper/RmManureLastMapper.xml
@@ -27,6 +27,14 @@
    stir_running4, inject_running, irr_running, alarm, manure_flow, manure_time, stir_time, 
    stir_duration, inject_duration
  </sql>
  <sql id="Base_Column_List_with_alias">
    <!--@mbg.generated-->
    ${alias}.id, ${alias}.last_history_id, ${alias}.manure_id, ${alias}.dt, ${alias}.stir_running1, ${alias}.stir_running2, ${alias}.stir_running3,
    ${alias}.stir_running4, ${alias}.inject_running, ${alias}.irr_running, ${alias}.alarm, ${alias}.manure_flow, ${alias}.manure_time, ${alias}.stir_time,
    ${alias}.stir_duration, ${alias}.inject_duration
  </sql>
  <select id="selectByPrimaryKey" parameterType="java.lang.Long" resultMap="BaseResultMap">
    <!--@mbg.generated-->
    select 
@@ -65,7 +73,7 @@
      <if test = "name != null and name !=''">
        AND mtb.name LIKE CONCAT('%',#{name},'%')
      </if>
      <if test = "timeStart != null and timeStop != null">
      <if test = "timeStart != null and timeStart !='' and timeStop != null and timeStop != ''">
        AND ltb.dt BETWEEN #{timeStart} AND #{timeStop}
      </if>
    </where>
@@ -74,7 +82,9 @@
  <!--根据指定条件查询记录-->
  <select id="selectSome" resultType="com.dy.pipIrrGlobal.voRm.VoManure">
    SELECT
    <include refid="Base_Column_List" />,
    <include refid="Base_Column_List_with_alias" >
      <property name="alias" value="ltb"/>
    </include>,
    mtb.`name` AS manureName
    FROM rm_manure_last ltb
    INNER JOIN pr_st_manure mtb ON mtb.id = ltb.manure_id
@@ -88,7 +98,7 @@
      <if test = "name != null and name !=''">
        AND mtb.name LIKE CONCAT('%',#{name},'%')
      </if>
      <if test = "timeStart != null and timeStop != null">
      <if test = "timeStart != null and timeStart !='' and timeStop != null and timeStop != ''">
        AND ltb.dt BETWEEN #{timeStart} AND #{timeStop}
      </if>
    </where>
pipIrr-platform/pipIrr-global/src/main/resources/mapper/RmSoilDayMapper.xml
@@ -38,6 +38,15 @@
    soil_sum_humidity4, soil_sum_humidity5, soil_sum_temperature1, soil_sum_temperature2, 
    soil_sum_temperature3, soil_sum_temperature4, soil_sum_temperature5
  </sql>
  <sql id="Base_Column_List_with_alias">
    <!--@mbg.generated-->
    ${alias}.id, ${alias}.soil_id, ${alias}.dt, ${alias}.ymd,
    ${alias}.soil_humidity1, ${alias}.soil_humidity2, ${alias}.soil_humidity3, ${alias}.soil_humidity4, ${alias}.soil_humidity5,
    ${alias}.soil_temperature1, ${alias}.soil_temperature2, ${alias}.soil_temperature3, ${alias}.soil_temperature4, ${alias}.soil_temperature5,
    ${alias}.times,
    ${alias}.soil_sum_humidity1, ${alias}.soil_sum_humidity2, ${alias}.soil_sum_humidity3, ${alias}.soil_sum_humidity4, ${alias}.soil_sum_humidity5,
    ${alias}.soil_sum_temperature1, ${alias}.soil_sum_temperature2, ${alias}.soil_sum_temperature3, ${alias}.soil_sum_temperature4, ${alias}.soil_sum_temperature5
  </sql>
  <sql id="Part_Column_List">
    <!--@mbg.generated-->
    id, soil_id, dt, ymd, soil_humidity1, soil_humidity2, soil_humidity3, soil_humidity4,
@@ -68,7 +77,6 @@
    limit 0,1
  </select>
  <!--根据指定条件获取记录-->
  <select id="selectOneBySoilId" resultType="com.dy.pipIrrGlobal.voRm.VoSoilDay">
    select
@@ -85,7 +93,23 @@
    limit 0,1
  </select>
  <!--根据指定条件获取记录-->
  <select id="selectOneMonthBySoilId" resultType="com.dy.pipIrrGlobal.voRm.VoSoilDay">
    select
    <include refid="Part_Column_List" />
    from rm_soil_day
    <where>
      <if test="soilId != null">
        and soil_id = #{soilId}
      </if>
      <if test="ymdStart != null">
        and ymd &gt;= #{ymdStart}
      </if>
      <if test="ymdEnd != null">
        and ymd &lt;= #{ymdEnd}
      </if>
    </where>
  </select>
  <!--根据指定条件查询记录数量-->
  <select id="selectCount" resultType="java.lang.Long">
@@ -103,7 +127,7 @@
      <if test = "name != null and name !=''">
        AND mtb.name LIKE CONCAT('%',#{name},'%')
      </if>
      <if test = "timeStart != null and timeStop != null">
      <if test = "timeStart != null and timeStart !='' and timeStop != null and timeStop != ''">
        AND ltb.dt BETWEEN #{timeStart} AND #{timeStop}
      </if>
    </where>
@@ -112,7 +136,9 @@
  <!--根据指定条件查询记录-->
  <select id="selectSome" resultType="com.dy.pipIrrGlobal.voRm.VoSoilDay">
    SELECT
    <include refid="Base_Column_List" />,
    <include refid="Base_Column_List_with_alias" >
      <property name="alias" value="ltb"/>
    </include>,
    mtb.`name` AS soilName
    FROM rm_soil_day ltb
    INNER JOIN pr_st_soil mtb ON mtb.id = ltb.soil_id
@@ -126,7 +152,7 @@
      <if test = "name != null and name !=''">
        AND mtb.name LIKE CONCAT('%',#{name},'%')
      </if>
      <if test = "timeStart != null and timeStop != null">
      <if test = "timeStart != null and timeStart !='' and timeStop != null and timeStop != ''">
        AND ltb.dt BETWEEN #{timeStart} AND #{timeStop}
      </if>
    </where>
pipIrr-platform/pipIrr-global/src/main/resources/mapper/RmSoilHistoryMapper.xml
@@ -24,6 +24,13 @@
    soil_humidity5, soil_temperature1, soil_temperature2, soil_temperature3, soil_temperature4, 
    soil_temperature5
  </sql>
  <sql id="Base_Column_List_with_alias">
    <!--@mbg.generated-->
    ${alias}.id, ${alias}.soil_id, ${alias}.dt, ${alias}.soil_humidity1,
    ${alias}.soil_humidity2, ${alias}.soil_humidity3, ${alias}.soil_humidity4,
    ${alias}.soil_humidity5, ${alias}.soil_temperature1, ${alias}.soil_temperature2,
    ${alias}.soil_temperature3, ${alias}.soil_temperature4, ${alias}.soil_temperature5
  </sql>
  <select id="selectByPrimaryKey" parameterType="java.lang.Long" resultMap="BaseResultMap">
    <!--@mbg.generated-->
    select 
@@ -47,7 +54,7 @@
      <if test = "name != null and name !=''">
        AND mtb.name LIKE CONCAT('%',#{name},'%')
      </if>
      <if test = "timeStart != null and timeStop != null">
      <if test = "timeStart != null and timeStart !='' and timeStop != null and timeStop != ''">
        AND htb.dt BETWEEN #{timeStart} AND #{timeStop}
      </if>
    </where>
@@ -56,7 +63,9 @@
  <!--根据指定条件查询历史记录-->
  <select id="selectSome" resultType="com.dy.pipIrrGlobal.voRm.VoSoil">
    SELECT
    <include refid="Base_Column_List" />,
    <include refid="Base_Column_List_with_alias" >
      <property name="alias" value="htb"/>
    </include>,
    mtb.`name` AS soilName
    FROM rm_soil_history htb
    INNER JOIN pr_st_soil mtb ON mtb.id = htb.soil_id
@@ -70,7 +79,7 @@
      <if test = "name != null and name !=''">
        AND mtb.name LIKE CONCAT('%',#{name},'%')
      </if>
      <if test = "timeStart != null and timeStop != null">
      <if test = "timeStart != null and timeStart !='' and timeStop != null and timeStop != ''">
        AND htb.dt BETWEEN #{timeStart} AND #{timeStop}
      </if>
    </where>
pipIrr-platform/pipIrr-global/src/main/resources/mapper/RmSoilLastMapper.xml
@@ -25,6 +25,15 @@
    soil_humidity4, soil_humidity5, soil_temperature1, soil_temperature2, soil_temperature3, 
    soil_temperature4, soil_temperature5
  </sql>
  <sql id="Base_Column_List_with_alias">
    <!--@mbg.generated-->
    ${alias}.id, ${alias}.last_history_id, ${alias}.soil_id, ${alias}.dt, ${alias}.soil_humidity1,
    ${alias}.soil_humidity2, ${alias}.soil_humidity3, ${alias}.soil_humidity4,
    ${alias}.soil_humidity5, ${alias}.soil_temperature1, ${alias}.soil_temperature2,
    ${alias}.soil_temperature3, ${alias}.soil_temperature4, ${alias}.soil_temperature5
  </sql>
  <select id="selectByPrimaryKey" parameterType="java.lang.Long" resultMap="BaseResultMap">
    <!--@mbg.generated-->
    select 
@@ -64,7 +73,7 @@
      <if test = "name != null and name !=''">
        AND mtb.name LIKE CONCAT('%',#{name},'%')
      </if>
      <if test = "timeStart != null and timeStop != null">
      <if test = "timeStart != null and timeStart !='' and timeStop != null and timeStop != ''">
        AND ltb.dt BETWEEN #{timeStart} AND #{timeStop}
      </if>
    </where>
@@ -73,7 +82,9 @@
  <!--根据指定条件查询记录-->
  <select id="selectSome" resultType="com.dy.pipIrrGlobal.voRm.VoSoil">
    SELECT
    <include refid="Base_Column_List" />,
    <include refid="Base_Column_List_with_alias" >
      <property name="alias" value="ltb"/>
    </include>,
    mtb.`name` AS soilName
    FROM rm_soil_last ltb
    INNER JOIN pr_st_soil mtb ON mtb.id = ltb.soil_id
@@ -87,7 +98,7 @@
      <if test = "name != null and name !=''">
        AND mtb.name LIKE CONCAT('%',#{name},'%')
      </if>
      <if test = "timeStart != null and timeStop != null">
      <if test = "timeStart != null and timeStart !='' and timeStop != null and timeStop != ''">
        AND ltb.dt BETWEEN #{timeStart} AND #{timeStop}
      </if>
    </where>
pipIrr-platform/pipIrr-global/src/main/resources/mapper/RmWeatherHistoryMapper.xml
@@ -20,6 +20,13 @@
    id, weather_id, dt, air_temperature, air_humidity, ultraviolet, light_intensity, 
    rainfall, wind_speed, wind_direction
  </sql>
  <sql id="Base_Column_List_with_alias">
    <!--@mbg.generated-->
    ${alias}.id, ${alias}.weather_id, ${alias}.dt, ${alias}.air_temperature,
    ${alias}.air_humidity, ${alias}.ultraviolet, ${alias}.light_intensity,
    ${alias}.rainfall, ${alias}.wind_speed, ${alias}.wind_direction
  </sql>
  <select id="selectByPrimaryKey" parameterType="java.lang.Long" resultMap="BaseResultMap">
    <!--@mbg.generated-->
    select 
@@ -43,7 +50,7 @@
      <if test = "name != null and name !=''">
        AND mtb.name LIKE CONCAT('%',#{name},'%')
      </if>
      <if test = "timeStart != null and timeStop != null">
      <if test = "timeStart != null and timeStart !='' and timeStop != null and timeStop != ''">
        AND htb.dt BETWEEN #{timeStart} AND #{timeStop}
      </if>
    </where>
@@ -52,7 +59,9 @@
  <!--根据指定条件查询历史记录-->
  <select id="selectSome" resultType="com.dy.pipIrrGlobal.voRm.VoWeather">
    SELECT
    <include refid="Base_Column_List" />,
    <include refid="Base_Column_List_with_alias" >
      <property name="alias" value="htb"/>
    </include>,
    mtb.`name` AS weatherName
    FROM rm_weather_history htb
    INNER JOIN pr_st_weather mtb ON mtb.id = htb.weather_id
@@ -66,7 +75,7 @@
      <if test = "name != null and name !=''">
        AND mtb.name LIKE CONCAT('%',#{name},'%')
      </if>
      <if test = "timeStart != null and timeStop != null">
      <if test = "timeStart != null and timeStart !='' and timeStop != null and timeStop != ''">
        AND htb.dt BETWEEN #{timeStart} AND #{timeStop}
      </if>
    </where>
pipIrr-platform/pipIrr-global/src/main/resources/mapper/RmWeatherLastMapper.xml
@@ -21,6 +21,13 @@
    id, last_history_id, weather_id, dt, air_temperature, air_humidity, ultraviolet, 
    light_intensity, rainfall, wind_speed, wind_direction
  </sql>
  <sql id="Base_Column_List_with_alias">
    <!--@mbg.generated-->
    ${alias}.id, ${alias}.last_history_id, ${alias}.weather_id, ${alias}.dt, ${alias}.air_temperature,
    ${alias}.air_humidity, ${alias}.ultraviolet, ${alias}.light_intensity,
    ${alias}.rainfall, ${alias}.wind_speed, ${alias}.wind_direction
  </sql>
  <select id="selectByPrimaryKey" parameterType="java.lang.Long" resultMap="BaseResultMap">
    <!--@mbg.generated-->
    select 
@@ -60,7 +67,7 @@
      <if test = "name != null and name !=''">
        AND mtb.name LIKE CONCAT('%',#{name},'%')
      </if>
      <if test = "timeStart != null and timeStop != null">
      <if test = "timeStart != null and timeStart !='' and timeStop != null and timeStop != ''">
        AND ltb.dt BETWEEN #{timeStart} AND #{timeStop}
      </if>
    </where>
@@ -69,7 +76,9 @@
  <!--根据指定条件查询记录-->
  <select id="selectSome" resultType="com.dy.pipIrrGlobal.voRm.VoWeather">
    SELECT
    <include refid="Base_Column_List" />,
    <include refid="Base_Column_List_with_alias" >
      <property name="alias" value="ltb"/>
    </include>,
    mtb.`name` AS weatherName
    FROM rm_weather_last ltb
    INNER JOIN pr_st_weather mtb ON mtb.id = ltb.weather_id
@@ -83,7 +92,7 @@
      <if test = "name != null and name !=''">
        AND mtb.name LIKE CONCAT('%',#{name},'%')
      </if>
      <if test = "timeStart != null and timeStop != null">
      <if test = "timeStart != null and timeStart !='' and timeStop != null and timeStop != ''">
        AND ltb.dt BETWEEN #{timeStart} AND #{timeStop}
      </if>
    </where>
pipIrr-platform/pipIrr-mw/pipIrr-mw-rtu/src/main/java/com/dy/rtuMw/resource/rtuLog/RtuLogManager.java
@@ -172,7 +172,9 @@
                                return new Object[]{null, 3} ;
                            }
                            if(!oldLog.delete()){
                                return new Object[]{null, 4} ;
                                //2025-06-28 对于水肥机FBox上报数据比较频繁,实测老文件常有删除不了的情况发生,
                                //一次删除不了,下次再可删除,所以下面return去除
                                //return new Object[]{null, 4} ;
                            }
                        }
                    }
pipIrr-platform/pipIrr-mw/pipIrr-mw-rtu/src/main/resources/config.properties
@@ -41,13 +41,13 @@
#   测试: mqtt.enable=false  mqtt.protocolAndDeviceIds= mqtt.topicAndQos=
#   梅江: mqtt.enable=false  mqtt.protocolAndDeviceIds= mqtt.topicAndQos=
# 121服务器:
#   民勤: mqtt.enable=true  mqtt.protocolAndDeviceIds=? mqtt.topicAndQos=weather/1,1;soil/1,1;manure/1,1;state/1,1
#   民勤: mqtt.enable=true  mqtt.protocolAndDeviceIds=? mqtt.topicAndQos=weather/1,1;soil/1,1;manure/1,1
#   延庆: mqtt.enable=false  mqtt.protocolAndDeviceIds= mqtt.topicAndQos=
#   黑龙江: mqtt.enable=false  mqtt.protocolAndDeviceIds= mqtt.topicAndQos=
#   甘州: mqtt.enable=false  mqtt.protocolAndDeviceIds= mqtt.topicAndQos=
#   凉州: mqtt.enable=false  mqtt.protocolAndDeviceIds= mqtt.topicAndQos=
#   金川: mqtt.enable=true  mqtt.protocolAndDeviceIds=? mqtt.topicAndQos=weather/1,1;soil/1,1;manure/1,1;state/1,1
#   嘉峪关: mqtt.enable=true  mqtt.protocolAndDeviceIds=? mqtt.topicAndQos=weather/1,1;soil/1,1;manure/1,1;state/1,1
#   金川: mqtt.enable=true  mqtt.protocolAndDeviceIds=? mqtt.topicAndQos=weather/1,1;soil/1,1;manure/1,1
#   嘉峪关: mqtt.enable=true  mqtt.protocolAndDeviceIds=? mqtt.topicAndQos=weather/1,1;soil/1,1;manure/1,1
mqtt.enable=false
mqtt.ip=127.0.0.1
mqtt.port=1883
pipIrr-platform/pipIrr-mw/pipIrr-param-set/src/main/java/com/dy/pipIrrParamSet/console/Command.java
@@ -21,8 +21,8 @@
    static{
        commands = new String[]{
                "config 查看配置信息",    
                "mw 121 [tag] 命令含义:通信中间件在云服务器(121.199.41.121)上的[tag](元谋ym,沙盘sp测试test,梅江mj,民勤mq,延庆yq,黑龙江hlj,甘州gz,凉州lz,金川jc,嘉峪关jyg)系统配置",
                "mw 233 [tag] 命令含义:通信中间件在云服务器(8.130.130.233)上的[tag](元谋ym,沙盘sp测试test,梅江mj,民勤mq,延庆yq,黑龙江hlj,甘州gz,凉州lz,金川jc,嘉峪关jyg)系统配置",
                "mw 121 [tag] 命令含义:通信中间件在云服务器(121.199.41.121)上的[tag](民勤mq,延庆yq,黑龙江hlj,甘州gz,凉州lz,金川jc,嘉峪关jyg)系统配置",
                "mw 233 [tag] 命令含义:通信中间件在云服务器(8.130.130.233)上的[tag](元谋ym,沙盘sp,测试test,梅江mj)系统配置",
                "web 121 命令含义:web模块在云服务器(121.199.41.121)上的配置",
                "web 233 命令含义:web模块在云服务器(8.130.130.233)上的配置",
                "exit 退出",
pipIrr-platform/pipIrr-web/pipIrr-web-project/src/main/java/com/dy/pipIrrProject/mqtt/manure/ManureDto.java
@@ -21,6 +21,12 @@
    public String id;
    /**
     * 水肥机FBox序列号
     */
    @NotEmpty(message = "水肥机FBox序列号") //不能为空也不能为null
    public String fboxId;
    /**
     * 水肥机名称
     */
    @NotEmpty(message = "水肥机名称不能为空") //不能为空也不能为null
@@ -49,6 +55,7 @@
    public PrStManure toNewPo(){
        PrStManure po = new PrStManure();
        po.fboxId = this.fboxId;
        po.name = this.name;
        po.no = this.no;
        po.lng = this.lng;
pipIrr-platform/pipIrr-web/pipIrr-web-project/src/main/java/com/dy/pipIrrProject/mqtt/soil/SoilDto.java
@@ -21,6 +21,12 @@
    public String id;
    /**
     * 墒情站FBox序列号
     */
    @NotEmpty(message = "墒情站FBox序列号") //不能为空也不能为null
    public String fboxId;
    /**
     * 墒情站名称
     */
    @NotEmpty(message = "墒情站名称不能为空") //不能为空也不能为null
@@ -49,6 +55,7 @@
    public PrStSoil toNewPo(){
        PrStSoil po = new PrStSoil();
        po.fboxId = this.fboxId;
        po.name = this.name;
        po.no = this.no;
        po.lng = this.lng;
pipIrr-platform/pipIrr-web/pipIrr-web-project/src/main/java/com/dy/pipIrrProject/mqtt/weather/WeatherDto.java
@@ -21,6 +21,12 @@
    public String id;
    /**
     * 气象站FBox序列号
     */
    @NotEmpty(message = "气象站FBox序列号") //不能为空也不能为null
    public String fboxId;
    /**
     * 气象站名称
     */
    @NotEmpty(message = "气象站名称不能为空") //不能为空也不能为null
@@ -49,6 +55,7 @@
    public PrStWeather toNewPo(){
        PrStWeather po = new PrStWeather();
        po.fboxId = this.fboxId;
        po.name = this.name;
        po.no = this.no;
        po.lng = this.lng;
pipIrr-platform/pipIrr-web/pipIrr-web-remote/src/main/java/com/dy/pipIrrRemote/monitor/common/ComSv.java
@@ -62,6 +62,7 @@
     * @param intakeId
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public PrCommonIntakes addOrUpdateOftenUseIntake(Long operatorId, Long intakeId) {
        PrCommonIntakes po = prCommonIntakesDao.selectByOperatorAndIntake(operatorId, intakeId);
        if(po == null) {
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
@@ -8,6 +8,7 @@
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;
@@ -25,6 +26,8 @@
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.Date;
/**
 * @Author: liurunyu
 * @Date: 2025/5/13 08:33
@@ -41,6 +44,8 @@
    private static final String RtuSuccessMsg = "控制器接收并执行命令成功,无返回数据";
    private static final String ComCode = "92" ;
    public static final Double MaxRemainMoney = 9999.9999D ;//协议支持的剩余金额最大值
    @Autowired
    private CdSv sv ;
@@ -78,17 +83,21 @@
                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(RandomStringUtils.randomNumeric(16))//订单号(16位数字)
                        .orderNo(orderNo)//订单号(16位数字)
                        .build();
                //发送命令前-3:保存命令日志
                res = super.pre3(sv, dto.getIntakeId(), dto.getOperator(), ComCode, comParam);
@@ -113,6 +122,15 @@
                                        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
@@ -152,7 +170,7 @@
                DataCd92_A2Vo cvo = JSON.parseObject(json, DataCd92_A2Vo.class) ;
                if(cvo != null){
                    if(callback != null){
                        if(cvo.opResult != null && cvo.opResult.byteValue() == (byte)0){
                        if(cvo.opResult != null && cvo.opResult.byteValue() == (byte)1){
                            callback.call(true);//开阀成功
                        }else{
                            callback.call(false);//开阀失败
@@ -168,4 +186,39 @@
        }
        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/cd92/CdSv.java
@@ -2,15 +2,19 @@
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
@@ -26,6 +30,8 @@
    protected PrWaterPriceMapper prWaterPriceDao ;
    @Autowired
    protected PrIntakeVcMapper prIntakeVcDao ;
    @Autowired
    protected RmCommandOpenMapper rmCommandOpenDao ;
    public VoVirtualCard selectClientVtCardById(Long id){
        return seVirtualCardDao.getVcById(id) ;
@@ -44,6 +50,7 @@
    /**
     * 设置虚拟卡被占用
     */
    @Transactional(rollbackFor = Exception.class)
    public void setVcUsed(Long id, Long intakeId){
        SeVirtualCard po = new SeVirtualCard() ;
        po.setId(id);
@@ -52,4 +59,22 @@
        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/cd93/CdCtrl.java
@@ -4,11 +4,11 @@
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.DataCd93_A3Vo;
import com.dy.common.mw.protocol.p206V202404.upVos.DataCd93_9D_A3Vo;
import com.dy.common.util.Callback;
import com.dy.common.webUtil.BaseResponse;
import com.dy.common.webUtil.BaseResponseUtils;
import com.dy.pipIrrGlobal.voRm.VoUnclosedParam;
import com.dy.pipIrrGlobal.pojoRm.RmCommandOpen;
import com.dy.pipIrrRemote.common.dto.DtoBase;
import com.dy.pipIrrRemote.monitor.common.ComCtrl;
import io.swagger.v3.oas.annotations.tags.Tag;
@@ -60,6 +60,8 @@
            res = super.pre2(sv, ComCode, dto, bindingResult);
            if (res == null) {
                //获取开阀命令参数
                /*
                2025-06-27原来的实现,原来没有设计RmCommandOpen对象及其对应的数据库表
                VoUnclosedParam opPa = sv.selectUncloseParam(dto.getIntakeId(), ctrlPo.getRtuAddr());
                if(opPa == null) {
                    return BaseResponseUtils.buildFail("该取水口上无您最近的开阀操作");
@@ -72,6 +74,20 @@
                CdParam comParam = CdParam.builder().commandCode(ComCode).projectNo(projectNo).controllerType(controllerType)
                        .icCardNo(opPa.getVcNum())//用户卡序列号(17位数字)(6字节BCD,2字节HEX)
                        .orderNo(opPa.getOrderNo())//订单号(16位数字)
                        .build();
                */
                RmCommandOpen comOpen = sv.getCommandOpen(dto.getIntakeId()) ;
                if(comOpen == null) {
                    return BaseResponseUtils.buildFail("该取水口上无您最近的开阀操作");
                }
                Long vcId = sv.getVcIdByNum("" + comOpen.vcNum) ;
                if(vcId == null) {
                    return BaseResponseUtils.buildFail("服务端出错,未得到虚拟卡ID");
                }
                //发送命令前-3:保存命令日志
                CdParam comParam = CdParam.builder().commandCode(ComCode).projectNo(projectNo).controllerType(controllerType)
                        .icCardNo("" + comOpen.vcNum)//用户卡序列号(17位数字)(6字节BCD,2字节HEX)
                        .orderNo(comOpen.orderNo)//订单号(16位数字)
                        .build();
                res = super.pre3(sv, dto.getIntakeId(), dto.getOperator(), ComCode, comParam);
                if (res == null) {
@@ -129,7 +145,7 @@
                msg = RtuSuccessMsg ;
            }else {
                String json = codeData.toJSONString();
                DataCd93_A3Vo cvo = JSON.parseObject(json, DataCd93_A3Vo.class) ;
                DataCd93_9D_A3Vo cvo = JSON.parseObject(json, DataCd93_9D_A3Vo.class) ;
                if(cvo != null){
                    if(callback != null){
                        if(cvo.clResult != null && cvo.clResult == 0){
pipIrr-platform/pipIrr-web/pipIrr-web-remote/src/main/java/com/dy/pipIrrRemote/monitor/p202404V201/cd93/CdSv.java
@@ -1,13 +1,18 @@
package com.dy.pipIrrRemote.monitor.p202404V201.cd93;
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.List;
/**
 * @Author: liurunyu
@@ -20,13 +25,14 @@
    @Autowired
    protected SeVirtualCardMapper seVirtualCardDao ;
    @Autowired
    protected PrWaterPriceMapper prWaterPriceDao ;
    @Autowired
    protected RmCommandOpenMapper rmCommandOpenDao ;
    /**
     * 解除虚拟卡被占用
     */
    @Transactional(rollbackFor = Exception.class)
    public void setVcNoUsed(Long id){
        SeVirtualCard po = new SeVirtualCard() ;
        po.setId(id);
@@ -44,4 +50,13 @@
    public Long getVcIdByNum(String vcNum){
        return seVirtualCardDao.getVcIdByNum(vcNum) ;
    }
    public RmCommandOpen getCommandOpen(Long intakeId){
        List<RmCommandOpen> list = rmCommandOpenDao.selectByIntakeId(intakeId) ;
        if(list != null && list.size() > 0){
            return list.get(0) ;
        }
        return null ;
    }
}
pipIrr-platform/pipIrr-web/pipIrr-web-remote/src/main/java/com/dy/pipIrrRemote/monitor/p202404V201/cd9D/CdCtrl.java
New file
@@ -0,0 +1,150 @@
package com.dy.pipIrrRemote.monitor.p202404V201.cd9D;
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.DataCd93_9D_A3Vo;
import com.dy.common.util.Callback;
import com.dy.common.webUtil.BaseResponse;
import com.dy.common.webUtil.BaseResponseUtils;
import com.dy.pipIrrGlobal.pojoRm.RmOpenCloseValveLast;
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/28 11:30
 * @Description
 */
@Slf4j
@Tag(name = "远程命令", description = "平台远程关阀")
@RestController("p202404V201Cd9DCtrl")
@RequestMapping(path = "p202404V201/cd9D")
@RequiredArgsConstructor
@Scope("prototype") //因为有对象类属性,所以采用原型模式,每次请求新建一个实例对象
public class CdCtrl extends ComCtrl {
    private static final String RtuSuccessMsg = "控制器接收并执行命令成功,无返回数据";
    private static final String ComCode = "9D" ;
    @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) {
                //获取开阀命令参数
                RmOpenCloseValveLast lastOpPo = sv.getLastOpenValve(dto.getIntakeId()) ;
                if(lastOpPo == null || lastOpPo.opType == null) {
                    return BaseResponseUtils.buildFail("该取水口上无最近的开阀操作");
                }
                if(lastOpPo.clType != null) {
                    return BaseResponseUtils.buildFail("该取水口上无最近的开阀操作");
                }
                //发送命令前-3:保存命令日志
                CdParam comParam = CdParam.builder().commandCode(ComCode).projectNo(projectNo).controllerType(controllerType)
                        .icCardAddr(lastOpPo.opIcCardAddr)//开阀ic卡地址
                        .icCardNo(lastOpPo.opIcCardNo)//开阀IC卡编号
                        .orderNo(lastOpPo.opOrderNo)//订单号
                        .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, new Callback() {
                                @Override
                                public void call(Object obj) {
                                    //Boolean success = (Boolean) obj;
                                    //if(success){
                                    //    //关阀成功
                                    //}
                                }
                                @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();
                DataCd93_9D_A3Vo cvo = JSON.parseObject(json, DataCd93_9D_A3Vo.class) ;
                if(cvo != null){
                    if(callback != null){
                        if(cvo.clResult != null && cvo.clResult == 0){
                            callback.call(true);//关阀成功
                        }else{
                            callback.call(false);//关阀失败
                        }
                    }
                    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/cd9D/CdDto.java
New file
@@ -0,0 +1,17 @@
package com.dy.pipIrrRemote.monitor.p202404V201.cd9D;
import com.dy.pipIrrRemote.common.dto.DtoBase;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
 * @Author: liurunyu
 * @Date: 2025/5/28 11:30
 * @Description
 */
@Data
@EqualsAndHashCode(callSuper=true)
public class CdDto extends DtoBase {
    public static final long serialVersionUID = 202506281131001L;
}
pipIrr-platform/pipIrr-web/pipIrr-web-remote/src/main/java/com/dy/pipIrrRemote/monitor/p202404V201/cd9D/CdParam.java
New file
@@ -0,0 +1,22 @@
package com.dy.pipIrrRemote.monitor.p202404V201.cd9D;
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/28 11:30
 * @Description
 */
@Data
@ToString(callSuper = true)
@EqualsAndHashCode(callSuper = true)
@SuperBuilder
public class CdParam extends CdParameter {
    public String icCardAddr ;//用户卡地址(4字节HEX)
    public String icCardNo ;//用户卡序列号(17位数字)(6字节BCD,2字节HEX)
    public String orderNo ;//订单号(16位数字)
}
pipIrr-platform/pipIrr-web/pipIrr-web-remote/src/main/java/com/dy/pipIrrRemote/monitor/p202404V201/cd9D/CdSv.java
New file
@@ -0,0 +1,38 @@
package com.dy.pipIrrRemote.monitor.p202404V201.cd9D;
import com.dy.pipIrrGlobal.daoPr.PrWaterPriceMapper;
import com.dy.pipIrrGlobal.daoRm.RmOpenCloseValveLastMapper;
import com.dy.pipIrrGlobal.daoSe.SeVirtualCardMapper;
import com.dy.pipIrrGlobal.pojoRm.RmOpenCloseValveLast;
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 java.util.List;
/**
 * @Author: liurunyu
 * @Date: 2025/5/28 11:30
 * @Description
 */
@Slf4j
@Service("cd9DSv")
public class CdSv extends ComSv {
    @Autowired
    protected SeVirtualCardMapper seVirtualCardDao ;
    @Autowired
    protected PrWaterPriceMapper prWaterPriceDao ;
    @Autowired
    protected RmOpenCloseValveLastMapper rmOpenCloseValveLastDao ;
    public RmOpenCloseValveLast getLastOpenValve(Long intakeId){
        List<RmOpenCloseValveLast> list = rmOpenCloseValveLastDao.selectByIntakeId(intakeId) ;
        if(list != null && list.size() > 0){
            return list.get(0) ;
        }
        return null ;
    }
}
pipIrr-platform/pipIrr-web/pipIrr-web-remote/src/main/java/com/dy/pipIrrRemote/monitor/p202404V201/cdA2/CdCtrl.java
@@ -8,6 +8,7 @@
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;
@@ -25,6 +26,8 @@
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.Date;
/**
 * @Author: liurunyu
 * @Date: 2025/5/15 09:21
@@ -41,6 +44,8 @@
    private static final String RtuSuccessMsg = "控制器接收并执行命令成功,无返回数据";
    private static final String ComCode = "A2" ;
    private static final Double MaxRemainMoney = com.dy.pipIrrRemote.monitor.p202404V201.cd92.CdCtrl.MaxRemainMoney;//协议支持的剩余金额最大值
    @Autowired
    private CdSv sv ;
@@ -78,17 +83,21 @@
                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(RandomStringUtils.randomNumeric(16))//订单号(16位数字)
                        .orderNo(orderNo)//订单号(16位数字)
                        .build();
                //发送命令前-3:保存命令日志
                res = super.pre3(sv, dto.getIntakeId(), dto.getOperator(), ComCode, comParam);
@@ -113,6 +122,15 @@
                                        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
@@ -152,7 +170,7 @@
                DataCd92_A2Vo cvo = JSON.parseObject(json, DataCd92_A2Vo.class) ;
                if(cvo != null){
                    if(callback != null){
                        if(cvo.opResult != null && cvo.opResult.byteValue() == (byte)0){
                        if(cvo.opResult != null && cvo.opResult.byteValue() == (byte)1){
                            callback.call(true);//开阀成功
                        }else{
                            callback.call(false);//开阀失败
@@ -168,4 +186,39 @@
        }
        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/cdA2/CdSv.java
@@ -2,15 +2,19 @@
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
@@ -26,6 +30,8 @@
    protected PrWaterPriceMapper prWaterPriceDao ;
    @Autowired
    protected PrIntakeVcMapper prIntakeVcDao ;
    @Autowired
    protected RmCommandOpenMapper rmCommandOpenDao ;
    public VoVirtualCard selectClientVtCardById(Long id){
        return seVirtualCardDao.getVcById(id) ;
@@ -52,4 +58,23 @@
        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/cdA3/CdCtrl.java
@@ -4,13 +4,14 @@
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.DataCd93_A3Vo;
import com.dy.common.mw.protocol.p206V202404.upVos.DataCd93_9D_A3Vo;
import com.dy.common.util.Callback;
import com.dy.common.webUtil.BaseResponse;
import com.dy.common.webUtil.BaseResponseUtils;
import com.dy.pipIrrGlobal.voRm.VoUnclosedParam;
import com.dy.pipIrrGlobal.pojoRm.RmCommandOpen;
import com.dy.pipIrrRemote.common.dto.DtoBase;
import com.dy.pipIrrRemote.monitor.common.ComCtrl;
import com.dy.pipIrrRemote.monitor.p202404V201.cd93.CdParam;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
@@ -60,6 +61,8 @@
            res = super.pre2(sv, ComCode, dto, bindingResult);
            if (res == null) {
                //获取开阀命令参数
                /*
                2025-06-27原来的实现,原来没有设计RmCommandOpen对象及其对应的数据库表
                VoUnclosedParam opPa = sv.selectUncloseParam(dto.getIntakeId(), ctrlPo.getRtuAddr());
                if(opPa == null) {
                    return BaseResponseUtils.buildFail("该取水口上无您最近的开阀操作");
@@ -72,6 +75,20 @@
                CdParam comParam = CdParam.builder().commandCode(ComCode).projectNo(projectNo).controllerType(controllerType)
                        .icCardNo(opPa.getVcNum())//用户卡序列号(17位数字)(6字节BCD,2字节HEX)
                        .orderNo(opPa.getOrderNo())//订单号(16位数字)
                        .build();
                */
                RmCommandOpen comOpen = sv.getCommandOpen(dto.getIntakeId()) ;
                if(comOpen == null) {
                    return BaseResponseUtils.buildFail("该取水口上无您最近的开阀操作");
                }
                Long vcId = sv.getVcIdByNum("" + comOpen.vcNum) ;
                if(vcId == null) {
                    return BaseResponseUtils.buildFail("服务端出错,未得到虚拟卡ID");
                }
                //发送命令前-3:保存命令日志
                com.dy.pipIrrRemote.monitor.p202404V201.cd93.CdParam comParam = CdParam.builder().commandCode(ComCode).projectNo(projectNo).controllerType(controllerType)
                        .icCardNo("" + comOpen.vcNum)//用户卡序列号(17位数字)(6字节BCD,2字节HEX)
                        .orderNo(comOpen.orderNo)//订单号(16位数字)
                        .build();
                res = super.pre3(sv, dto.getIntakeId(), dto.getOperator(), ComCode, comParam);
                if (res == null) {
@@ -129,7 +146,7 @@
                msg = RtuSuccessMsg ;
            }else {
                String json = codeData.toJSONString();
                DataCd93_A3Vo cvo = JSON.parseObject(json, DataCd93_A3Vo.class) ;
                DataCd93_9D_A3Vo cvo = JSON.parseObject(json, DataCd93_9D_A3Vo.class) ;
                if(cvo != null){
                    if(callback != null){
                        if(cvo.clResult != null && cvo.clResult == 0){
pipIrr-platform/pipIrr-web/pipIrr-web-remote/src/main/java/com/dy/pipIrrRemote/monitor/p202404V201/cdA3/CdSv.java
@@ -1,13 +1,17 @@
package com.dy.pipIrrRemote.monitor.p202404V201.cdA3;
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 java.util.List;
/**
 * @Author: liurunyu
@@ -20,10 +24,10 @@
    @Autowired
    protected SeVirtualCardMapper seVirtualCardDao ;
    @Autowired
    protected PrWaterPriceMapper prWaterPriceDao ;
    @Autowired
    protected RmCommandOpenMapper rmCommandOpenDao ;
    /**
     * 解除虚拟卡被占用
     */
@@ -44,4 +48,13 @@
    public Long getVcIdByNum(String vcNum){
        return seVirtualCardDao.getVcIdByNum(vcNum) ;
    }
    public RmCommandOpen getCommandOpen(Long intakeId){
        List<RmCommandOpen> list = rmCommandOpenDao.selectByIntakeId(intakeId) ;
        if(list != null && list.size() > 0){
            return list.get(0) ;
        }
        return null ;
    }
}
pipIrr-platform/pipIrr-web/pipIrr-web-remote/src/main/java/com/dy/pipIrrRemote/mqttSd1/soil/SoilCtrl.java
@@ -63,6 +63,36 @@
    }
    /**
     * 根据指定条件查询某气象站某一日记录
     * @param soilId
     * @param yyyy_MM
     * @return
     */
    @GetMapping(path = "oneDayByMonth")
    @SsoAop()
    public BaseResponse<List<VoSoilDay>> oneDayByMonth(Long soilId, String yyyy_MM){
        try {
            if(soilId == null){
                return BaseResponseUtils.buildFail("墒情站id不能为空") ;
            }
            if(yyyy_MM == null || yyyy_MM.trim().equals("")){
                return BaseResponseUtils.buildFail("查询月份不能为空") ;
            }
            String ymdStr = yyyy_MM.replaceAll("-", "") ;
            if(!NumUtil.isPlusIntNumber(ymdStr)){
                return BaseResponseUtils.buildFail("查询日期格式不正确,格式规定为yyyy-MM-dd") ;
            }
            Integer ymStart = Integer.parseInt(ymdStr) * 100;
            Integer ymEnd = Integer.parseInt(ymdStr) * 100 + 31;
            return BaseResponseUtils.buildSuccess(sv.oneDayByMonth(soilId, ymStart, ymEnd));
        } catch (Exception e) {
            return BaseResponseUtils.buildException(e.getMessage()) ;
        }
    }
    /**
     * 根据指定条件查询某气象站一些日记录
     * @param qo
     * @return
pipIrr-platform/pipIrr-web/pipIrr-web-remote/src/main/java/com/dy/pipIrrRemote/mqttSd1/soil/SoilSv.java
@@ -41,6 +41,10 @@
        return null ;
    }
    public List<VoSoilDay> oneDayByMonth(Long soilId, Integer yyyyMMddStart, Integer yyyyMMddEnd) {
        return this.rmSoilDayDao.selectOneMonthBySoilId(soilId, yyyyMMddStart, yyyyMMddEnd) ;
    }
    public QueryResultVo<List<VoSoilDay>> someDay(SoilQo qo) {
        Map<String, Object> params = (Map<String, Object>) PojoUtils.generalize(qo);