wuzeyu
2023-12-02 120448e8c6826b453d5b96e9076d61479a987677
Merge branch 'master' of http://8.140.179.55:20000/r/pipIrr-SV

 Conflicts:
 pipIrr-platform/pipIrr-common/src/main/java/com/dy/common/mw/protocol/p206V1_0_0/CommonV1_0_1.java
 pipIrr-platform/pipIrr-common/src/main/java/com/dy/common/mw/protocol/p206V1_0_0/DataCdC0Vo.java
 pipIrr-platform/pipIrr-common/src/main/java/com/dy/common/mw/protocol/p206V1_0_0/DataV1_0_1.java
 pipIrr-platform/pipIrr-common/src/main/java/com/dy/common/mw/protocol/p206V1_0_0/DriverV1_0_1.java
 pipIrr-platform/pipIrr-common/src/main/java/com/dy/common/mw/protocol/p206V1_0_0/PrefixedDataAvailableV1_0_1.java
 pipIrr-platform/pipIrr-common/src/main/java/com/dy/common/mw/protocol/p206V1_0_0/ProtocolConstantV206V1_0_0.java
 pipIrr-platform/pipIrr-common/src/main/java/com/dy/common/mw/protocol/p206V1_0_0/parse/Cd_02_Down.java
 pipIrr-platform/pipIrr-common/src/main/java/com/dy/common/mw/protocol/p206V1_0_0/parse/Cd_71_Down.java
 pipIrr-platform/pipIrr-common/src/main/java/com/dy/common/mw/protocol/p206V1_0_0/parse/Cd_83_Down.java
 pipIrr-platform/pipIrr-common/src/main/java/com/dy/common/mw/protocol/p206V1_0_0/parse/Cd_84_Down.java
 pipIrr-platform/pipIrr-common/src/main/java/com/dy/common/mw/protocol/p206V1_0_0/parse/Cd_C0_Down.java
 pipIrr-platform/pipIrr-common/src/main/java/com/dy/common/mw/protocol/p206V1_0_0/parse/global/GlCreate.java
 pipIrr-platform/pipIrr-common/src/main/java/com/dy/common/mw/protocol/p206V1_0_0/parse/global/GlParse.java
 pipIrr-platform/pipIrr-mw/pipIrr-mw-accept/pom.xml
 pipIrr-platform/pipIrr-mw/pipIrr-mw-accept/src/main/java/com/dy/aceMw/Server.java
 pipIrr-platform/pipIrr-mw/pipIrr-mw-accept/src/main/java/com/dy/aceMw/server/forTcp/MidResultActionFromRtu.java
 pipIrr-platform/pipIrr-mw/pipIrr-mw-accept/src/main/java/com/dy/aceMw/server/rtuData/RtuDataCache.java
 pipIrr-platform/pipIrr-mw/pipIrr-mw-accept/src/main/java/com/dy/aceMw/server/rtuData/RtuDataNode.java
 pipIrr-platform/pipIrr-mw/pipIrr-mw-accept/src/main/java/com/dy/aceMw/server/rtuData/Task.java
 pipIrr-platform/pipIrr-mw/pipIrr-mw-accept/src/main/java/com/dy/aceMw/server/rtuData/TaskConfig.java
 pipIrr-platform/pipIrr-mw/pipIrr-mw-accept/src/main/java/com/dy/aceMw/server/rtuData/TaskPool.java
 pipIrr-platform/pipIrr-mw/pipIrr-mw-accept/src/main/java/com/dy/aceMw/server/rtuData/TaskSurpport.java
 pipIrr-platform/pipIrr-mw/pipIrr-mw-accept/src/main/java/com/dy/aceMw/server/rtuData/TkReceive.java
 pipIrr-platform/pipIrr-mw/pipIrr-mw-accept/src/main/java/com/dy/aceMw/server/rtuData/TkRtuData.java
 pipIrr-platform/pipIrr-mw/pipIrr-mw-accept/src/main/java/com/dy/aceMw/server/rtuData/TreeConfig.java
 pipIrr-platform/pipIrr-mw/pipIrr-mw-accept/src/main/java/com/dy/aceMw/server/rtuData/TreeParse.java
 pipIrr-platform/pipIrr-mw/pipIrr-mw-accept/src/main/java/com/dy/aceMw/server/rtuData/dbSv/RtuSv.java
 pipIrr-platform/pipIrr-mw/pipIrr-mw-accept/src/main/java/com/dy/aceMw/server/rtuData/dbSv/说明.txt
 pipIrr-platform/pipIrr-mw/pipIrr-mw-accept/src/main/java/com/dy/aceMw/server/rtuData/p206V1_0_0/TkFindP206V1_0_0.java
 pipIrr-platform/pipIrr-mw/pipIrr-mw-accept/src/main/java/com/dy/aceMw/server/tasks/FromRtuConstantTask.java
 pipIrr-platform/pipIrr-mw/pipIrr-mwTest-server/src/main/java/com/dy/testServer/forRmi/RmiRequestVo.java
1 文件已重命名
34个文件已添加
14个文件已修改
2782 ■■■■■ 已修改文件
pipIrr-platform/pipIrr-common/src/main/java/com/dy/common/mw/protocol/p206V1_0_0/CommonV1_0_1.java 172 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pipIrr-platform/pipIrr-common/src/main/java/com/dy/common/mw/protocol/p206V1_0_0/DataCdC0Vo.java 56 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pipIrr-platform/pipIrr-common/src/main/java/com/dy/common/mw/protocol/p206V1_0_0/DataV1_0_1.java 45 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pipIrr-platform/pipIrr-common/src/main/java/com/dy/common/mw/protocol/p206V1_0_0/DriverV1_0_1.java 149 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pipIrr-platform/pipIrr-common/src/main/java/com/dy/common/mw/protocol/p206V1_0_0/PrefixedDataAvailableV1_0_1.java 130 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pipIrr-platform/pipIrr-common/src/main/java/com/dy/common/mw/protocol/p206V1_0_0/ProtocolConstantV206V1_0_0.java 53 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pipIrr-platform/pipIrr-common/src/main/java/com/dy/common/mw/protocol/p206V1_0_0/parse/Cd_02_Down.java 82 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pipIrr-platform/pipIrr-common/src/main/java/com/dy/common/mw/protocol/p206V1_0_0/parse/Cd_71_Down.java 87 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pipIrr-platform/pipIrr-common/src/main/java/com/dy/common/mw/protocol/p206V1_0_0/parse/Cd_83_Down.java 89 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pipIrr-platform/pipIrr-common/src/main/java/com/dy/common/mw/protocol/p206V1_0_0/parse/Cd_84_Down.java 89 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pipIrr-platform/pipIrr-common/src/main/java/com/dy/common/mw/protocol/p206V1_0_0/parse/Cd_C0_Down.java 89 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pipIrr-platform/pipIrr-common/src/main/java/com/dy/common/mw/protocol/p206V1_0_0/parse/global/GlCreate.java 38 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pipIrr-platform/pipIrr-common/src/main/java/com/dy/common/mw/protocol/p206V1_0_0/parse/global/GlParse.java 56 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pipIrr-platform/pipIrr-global/src/main/java/com/dy/pipIrrGlobal/test/TestConflict.java 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pipIrr-platform/pipIrr-mw/pipIrr-mw-accept/pom.xml 122 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pipIrr-platform/pipIrr-mw/pipIrr-mw-accept/src/main/java/com/dy/aceMw/PipIrrMwAcceptApplication.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
pipIrr-platform/pipIrr-mw/pipIrr-mw-accept/src/main/java/com/dy/aceMw/Server.java 106 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pipIrr-platform/pipIrr-mw/pipIrr-mw-accept/src/main/java/com/dy/aceMw/server/AdapterImp_RtuDataUnit.java 19 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pipIrr-platform/pipIrr-mw/pipIrr-mw-accept/src/main/java/com/dy/aceMw/server/forTcp/MidResultActionFromRtu.java 26 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pipIrr-platform/pipIrr-mw/pipIrr-mw-accept/src/main/java/com/dy/aceMw/server/rtuData/RtuDataCache.java 70 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pipIrr-platform/pipIrr-mw/pipIrr-mw-accept/src/main/java/com/dy/aceMw/server/rtuData/RtuDataNode.java 60 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pipIrr-platform/pipIrr-mw/pipIrr-mw-accept/src/main/java/com/dy/aceMw/server/rtuData/RtuDataUnit.java 47 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pipIrr-platform/pipIrr-mw/pipIrr-mw-accept/src/main/java/com/dy/aceMw/server/rtuData/RtuDataUnitAdapter.java 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pipIrr-platform/pipIrr-mw/pipIrr-mw-accept/src/main/java/com/dy/aceMw/server/rtuData/RtuDataUnitConfigVo.java 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pipIrr-platform/pipIrr-mw/pipIrr-mw-accept/src/main/java/com/dy/aceMw/server/rtuData/Task.java 46 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pipIrr-platform/pipIrr-mw/pipIrr-mw-accept/src/main/java/com/dy/aceMw/server/rtuData/TaskConfig.java 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pipIrr-platform/pipIrr-mw/pipIrr-mw-accept/src/main/java/com/dy/aceMw/server/rtuData/TaskPool.java 116 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pipIrr-platform/pipIrr-mw/pipIrr-mw-accept/src/main/java/com/dy/aceMw/server/rtuData/TaskSurpport.java 132 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pipIrr-platform/pipIrr-mw/pipIrr-mw-accept/src/main/java/com/dy/aceMw/server/rtuData/TkReceive.java 31 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pipIrr-platform/pipIrr-mw/pipIrr-mw-accept/src/main/java/com/dy/aceMw/server/rtuData/TkRtuData.java 29 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pipIrr-platform/pipIrr-mw/pipIrr-mw-accept/src/main/java/com/dy/aceMw/server/rtuData/TreeConfig.java 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pipIrr-platform/pipIrr-mw/pipIrr-mw-accept/src/main/java/com/dy/aceMw/server/rtuData/TreeParse.java 173 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pipIrr-platform/pipIrr-mw/pipIrr-mw-accept/src/main/java/com/dy/aceMw/server/rtuData/dbSv/RtuSv.java 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pipIrr-platform/pipIrr-mw/pipIrr-mw-accept/src/main/java/com/dy/aceMw/server/rtuData/dbSv/说明.txt 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pipIrr-platform/pipIrr-mw/pipIrr-mw-accept/src/main/java/com/dy/aceMw/server/rtuData/p206V1_0_0/TkFindP206V1_0_0.java 27 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pipIrr-platform/pipIrr-mw/pipIrr-mw-accept/src/main/java/com/dy/aceMw/server/rtuData/p206V1_0_0/TkPreGenObjs.java 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pipIrr-platform/pipIrr-mw/pipIrr-mw-accept/src/main/java/com/dy/aceMw/server/tasks/FromRtuConstantTask.java 74 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pipIrr-platform/pipIrr-mw/pipIrr-mw-accept/src/main/resources/RtuDataDealTree.xml 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pipIrr-platform/pipIrr-mw/pipIrr-mw-accept/src/main/resources/Tree_.xml 95 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pipIrr-platform/pipIrr-mw/pipIrr-mwTest-client/pom.xml 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pipIrr-platform/pipIrr-mw/pipIrr-mwTest-client/src/main/java/com/dy/testClient/rmiClient/RmiClUnit.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
pipIrr-platform/pipIrr-mw/pipIrr-mwTest-client/src/main/java/com/dy/testClient/rmiClient/RmiRequestVo.java 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pipIrr-platform/pipIrr-mw/pipIrr-mwTest-client/src/main/java/com/dy/testClient/tcpClient/LocalDecoder.java 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pipIrr-platform/pipIrr-mw/pipIrr-mwTest-client/src/main/java/com/dy/testClient/tcpClient/MyThreadJob.java 118 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pipIrr-platform/pipIrr-mw/pipIrr-mwTest-client/src/main/java/com/dy/testClient/tcpClient/TcpClUnit.java 142 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pipIrr-platform/pipIrr-mw/pipIrr-mwTest-client/src/main/java/com/dy/testClient/tcpClient/TcpConnect.java 14 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pipIrr-platform/pipIrr-mw/pipIrr-mwTest-server/src/main/java/com/dy/testServer/console/Command.java 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pipIrr-platform/pipIrr-mw/pipIrr-mwTest-server/src/main/java/com/dy/testServer/forRmi/Manager.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pipIrr-platform/pipIrr-mw/pipIrr-mwTest-server/src/main/java/com/dy/testServer/forRmi/RmiRequestVo.java 96 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pipIrr-platform/pipIrr-common/src/main/java/com/dy/common/mw/protocol/p206V1_0_0/CommonV1_0_1.java
New file
@@ -0,0 +1,172 @@
package com.dy.common.mw.protocol.p206V1_0_0;
import com.dy.common.util.ByteUtil;
import com.dy.common.util.ByteUtilUnsigned;
import com.dy.common.util.CRC8_for_2_0;
public class CommonV1_0_1 {
    /**
     * æ£€æŸ¥å¤´
     * @param bs ä¸Šè¡Œå­—节数组
     * @return true是,false否
     * @throws Exception  å¼‚常
     */
    public Boolean isThisProtocolHead(byte[] bs) throws Exception{
        if(bs == null){
            return null ;
        }else if(bs.length >= (ProtocolConstantV206V1_0_0.ctrlIndex - 1)
                && bs[0] == ProtocolConstantV206V1_0_0.P_Head_Byte
                && bs[2] == ProtocolConstantV206V1_0_0.P_Head_Byte){
            //String vs = this.parseVersion(bs) ;
            //return vs.equals(ProtocolConstantV206V1_0_0.version);
            return true ;
        }else{
            return false ;
        }
    }
    /**
     * æ£€æŸ¥å¤´
     * @param bs ä¸Šè¡Œå­—节数组
     * @throws Exception å¼‚常
     */
    public void checkHead(byte[] bs) throws Exception{
        if(bs.length < 13 || bs[0] != ProtocolConstantV206V1_0_0.P_Head_Byte || bs[2] != ProtocolConstantV206V1_0_0.P_Head_Byte){
            throw new Exception("上行数据帧头不正确!") ;
        }
    }
    /**
     * æ£€æŸ¥å°¾
     * @param bs ä¸Šè¡Œå­—节数组
     * @throws Exception å¼‚常
     */
    public void checkTail(byte[] bs) throws Exception{
        if(bs.length < 1 || bs[bs.length - 1] != ProtocolConstantV206V1_0_0.P_Tail_Byte){
            throw new Exception("上行数据尾不正确!") ;
        }
    }
    /**
     * åˆ†æžå¸§é•¿åº¦
     * @param bs ä¸Šè¡Œå­—节数组
     * @return æ•°æ®é•¿åº¦
     * @throws Exception å¼‚常
     */
    public int parseFrameLen(byte[] bs)throws Exception{
        int len = ByteUtilUnsigned.byte2Byte(bs, ProtocolConstantV206V1_0_0.dataLenIndex) ;
        return len + ProtocolConstantV206V1_0_0.lenHead2ctrl + ProtocolConstantV206V1_0_0.lenTail ;
    }
    /**
     * åˆ†æžç”¨æˆ·æ•°æ®åŸŸå­—节数
     * @param bs ä¸Šè¡Œå­—节数组
     * @return æ•°æ®é•¿åº¦
     * @throws Exception å¼‚常
     */
    public int parseDataLen(byte[] bs)throws Exception{
        int len = ByteUtilUnsigned.byte2Byte(bs, ProtocolConstantV206V1_0_0.dataLenIndex) ;
        return len + ProtocolConstantV206V1_0_0.lenHead2ctrl + ProtocolConstantV206V1_0_0.lenTail ;
    }
    /**
     * åˆ†æžRtu地址
     * @param bs ä¸Šè¡Œå­—节数组
     * @return æŽ§åˆ¶å™¨åœ°å€
     * @throws Exception å¼‚常
     */
    public String parseRtuAddr(byte[] bs)throws Exception{
        String rtuAddrBCD = "" + ByteUtil.BCD2Long_BE(bs, ProtocolConstantV206V1_0_0.rtuAddr1Index_start, ProtocolConstantV206V1_0_0.rtuAddr1Index_end) ;
        String rtuAddrStr = "" + ByteUtilUnsigned.bytes2Short_BE(bs, ProtocolConstantV206V1_0_0.rtuAddr2Index_start) ;
        while(rtuAddrStr.length() < 4){
            rtuAddrStr = "0" + rtuAddrStr ;
        }
        return rtuAddrBCD + rtuAddrStr ;
    }
    /**
     * åˆ†æžåŠŸèƒ½ç 
     * @param bs ä¸Šè¡Œå­—节数组
     * @return åŠŸèƒ½ç 
     */
    public String parseCode(byte[] bs){
        return ByteUtil.bytes2Hex(bs, false, ProtocolConstantV206V1_0_0.codeIndex, 1) ;
    }
    /**
     * æ ¡éªŒå’Œæ£€æŸ¥
     * @param bs  ä¸Šè¡Œå­—节数组
     * @return é€šè¿‡null,未通过返回原因
     * @throws Exception å¼‚常
     */
    public String checkCrc_str(byte[] bs) throws Exception {
        byte crcCompute = (byte)new CRC8_for_2_0().CRC8(bs, ProtocolConstantV206V1_0_0.ctrlIndex, bs.length - 3) ;
        byte crcInBs = bs[bs.length - 2] ;
        if(crcCompute == crcInBs){
            return null ;
        }else{
            return "计算CRC是:" + crcCompute + ",上传CRC是" + crcInBs ;
        }
    }
    /*
    æž„造控制域
    D7                  D6                  D5~D4            D3~D0
    ä¼ è¾“方向位 DIR        æ‹†åˆ†æ ‡å¿—位 DIV       å¸§è®¡æ•°ä½ FCB       åŠŸèƒ½ç 
    */
    public byte createCtrl(byte dir, byte funcCode){
        byte b = dir;//(byte)0x80//控制域:DIR=1,表示此帧报文是由终端发出的上行报文;
        b = (byte)(b | funcCode) ;
        //FCB == 3
        b = (byte)(b | (byte)0x18) ;
        //DIV = 0
        //DIR = 0
        return b ;
    }
    /**
     * å¾—到关开阀类型名称
     * @param type å­—节
     * @return åç§°
     */
    public static String openCloseValveType(byte type){
        return switch (type) {
            case 1 -> "刷卡开阀";
            case 2 -> "刷卡关阀";
            case 3 -> "中心站开阀";
            case 4 -> "中心站关阀";
            case 5 -> "欠费关阀";
            case 6 -> "流量计故障关阀";
            case 7 -> "紧急关阀";
            case 8 -> "用户远程开阀";
            case 9 -> "用户远程关阀";
            default -> "未知";
        };
    }
    /*
     * åˆ†æžç‰ˆæœ¬å·
     * @param bs  ä¸Šè¡Œå­—节数组
     * @return ç‰ˆæœ¬å·
     * @throws Exception å¼‚常
    public String parseVersion(byte[] bs)throws Exception{
        short ver = ByteUtilUnsigned.byte2Byte(bs, ProtocolConstantV206V1_0_0.versionIndex) ;
        char[] cs = ("" + ver).toCharArray() ;
        StringBuilder vs = new StringBuilder() ;
        for(byte i = 0 ; i < cs.length; i++){
            if(i == 0){
                vs.append(cs[i]) ;
            }else{
                vs.append(".").append(cs[i]) ;
            }
        }
        return vs.toString() ;
    }
    */
}
pipIrr-platform/pipIrr-common/src/main/java/com/dy/common/mw/protocol/p206V1_0_0/DataCdC0Vo.java
New file
@@ -0,0 +1,56 @@
package com.dy.common.mw.protocol.p206V1_0_0;
import lombok.Data;
@Data
public class DataCdC0Vo {
    public Double instantAmount; //瞬时流量:5字节BCD码,取值范围0~9999999.999,单位为m3/h。
    public Double totalAmount; //累计流量:5字节BCD码,取值范围0~9999999999,单位为m3。
    public Double lossAmount; //损失流量:5字节BCD码,取值范围0~9999999999,单位为m3。
    public Double waterPress; //水压:4字节BCD码,取值范围0~999999.99,单位为KPa。
    public Double batteryVolt;//蓄电池电压:4字节BCD码,取值范围0~99.99,单位为V。
    public Double sunVolt ;//太阳能电压:4字节BCD码,取值范围0~99.99,单位为V。
    public Integer signal; //信号强度:1字节BCD码,取值范围0~99。
    public String rtuDt ;//控制器时钟
    public DataAlarmVo alarmVo ;//报警
    public DataStateVo stateVo ;//状态
    public String toString(){
        StringBuilder sb = new StringBuilder() ;
        sb.append("   ç»ˆç«¯è‡ªæŠ¥å®žæ—¶æ•°æ®:\n");
        sb.append("      çž¬æ—¶æµé‡ï¼š");
        sb.append(instantAmount==null?"":instantAmount);
        sb.append("\n");
        sb.append("      ç´¯è®¡æµé‡ï¼š");
        sb.append(totalAmount==null?"":totalAmount);
        sb.append("\n");
        sb.append("      æŸå¤±æµé‡ï¼š");
        sb.append(lossAmount==null?"":lossAmount);
        sb.append("\n");
        sb.append("      æ°´åŽ‹ï¼š");
        sb.append(waterPress==null?"":waterPress);
        sb.append("\n");
        sb.append("      è“„电池电压:");
        sb.append(batteryVolt==null?"":batteryVolt);
        sb.append("\n");
        sb.append("      å¤ªé˜³èƒ½ç”µåŽ‹ï¼š");
        sb.append(sunVolt==null?"":sunVolt);
        sb.append("\n");
        sb.append("      ä¿¡å·å¼ºåº¦ï¼š");
        sb.append(signal==null?"":signal);
        sb.append("\n");
        sb.append("      æŽ§åˆ¶å™¨æ—¶é’Ÿï¼š");
        sb.append(rtuDt==null?"":rtuDt);
        sb.append("\n");
        if(alarmVo != null){
            sb.append(alarmVo.toString());
            sb.append("\n");
        }
        if(stateVo != null){
            sb.append(stateVo.toString());
            sb.append("\n");
        }
        return sb.toString() ;
    }
}
pipIrr-platform/pipIrr-common/src/main/java/com/dy/common/mw/protocol/p206V1_0_0/DataV1_0_1.java
New file
@@ -0,0 +1,45 @@
package com.dy.common.mw.protocol.p206V1_0_0;
import lombok.Data;
@Data
public class DataV1_0_1 implements java.io.Serializable{
    private static final long serialVersionUID = 202211271110001L;
    public String rtuAddr ;//RtuAddr
    public DataCd02Vo dataCd02Vo;//链路检测
    public DataCdC0Vo dataCdC0Vo;//终端自报实时数据
    public DataCd83OpenVo dataCd83OpenVo;//开阀自报
    public DataCd83CloseVo dataCd83CloseVo;//关阀自报
    public DataCd84Vo dataCd84Vo;//开阀工作报
    public DataCd71Vo dataCd71Vo;//查询阀门状态
    public String dt ;//通信中间件产生发报时间(yyyy-MM-dd hh:mm:ss)
    public String toString(){
        StringBuffer sb = new StringBuffer() ;
        sb.append("   æŽ§åˆ¶å™¨åœ°å€ : " + (rtuAddr==null?"":rtuAddr) + "\n") ;
        sb.append("   ç»ˆç«¯æ•°æ®:\n") ;
        if(dataCd02Vo != null){
            sb.append(dataCd02Vo.toString()) ;
        }
        if(dataCdC0Vo != null){
            sb.append(dataCdC0Vo.toString()) ;
        }
        if(dataCd83OpenVo != null){
            sb.append(dataCd83OpenVo.toString()) ;
        }
        if(dataCd83CloseVo != null){
            sb.append(dataCd83CloseVo.toString()) ;
        }
        if(dataCd84Vo != null){
            sb.append(dataCd84Vo.toString()) ;
        }
        if(dataCd71Vo != null){
            sb.append(dataCd71Vo.toString()) ;
        }
        return sb.toString() ;
    }
}
pipIrr-platform/pipIrr-common/src/main/java/com/dy/common/mw/protocol/p206V1_0_0/DriverV1_0_1.java
New file
@@ -0,0 +1,149 @@
package com.dy.common.mw.protocol.p206V1_0_0;
import com.dy.common.mw.protocol.*;
import com.dy.common.util.DateTime;
import java.net.URI;
import java.net.URL;
@AnnotationDriver(name= ProtocolConstantV206V1_0_0.protocolName)
public class DriverV1_0_1 extends Driver {
    private static String scanRootPackage = "com.dy.common.mw.protocol.p206V1_0_0." ;
    //在Driver中是单例,随Driver的单例对象在单线程中运行
    private ParseParamsForUpV1_0_1 upCpParams ;
    private ParseParamsForDownV1_0_1 downCpParams ;
    private Boolean reportOrResponse_trueOrFalse = null ;
    private String rtuAddrInData = null ;
    public DriverV1_0_1(){
        upCpParams = new ParseParamsForUpV1_0_1() ;
        downCpParams = new ParseParamsForDownV1_0_1() ;
    }
    /**
     * æ‰«æè¯†åˆ«åŠŸèƒ½ç æ³¨è§£ç±»
     */
    @Override
    public void scanAnnotationCode() throws Exception{
        if(!scanRootPackage.endsWith(".")){
            scanRootPackage += "." ;
        }
        URL url = this.getClass().getResource("/" + scanRootPackage.replace('.', '/'));
        URI uri = new URI(url.toString());
        super.doScanAnnotationCode(this, ProtocolConstantV206V1_0_0.protocolName, uri, scanRootPackage) ;
    }
    /**
     * è§£æžä¸Šè¡Œæ•°æ®
     * @param isLowPower æ˜¯å¦åœ¨ä½ŽåŠŸè€—çŽ¯å¢ƒä¸‹è¿è¡Œ
     * @param rtuAddr
     * @param upBuffer
     * @param callback
     * @param upHex
     * @return
     */
    @Override
    public MidResult[] parseData(Boolean isLowPower, String rtuAddr, byte[] upBuffer, String upHex, DriverParserDataCallback callback, Object... params) {
        reportOrResponse_trueOrFalse = null ;
        boolean isFail = false ;
        String upCode = null ;
        try{
            CommonV1_0_1 cp = new CommonV1_0_1() ;
            cp.checkHead(upBuffer) ;
            cp.checkTail(upBuffer) ;
            String crcStr = cp.checkCrc_str(upBuffer) ;
            if(crcStr != null){
                return new MidResult[]{(new MidResultError(ProtocolConstantV206V1_0_0.protocolName, rtuAddr, "严重错误,上行数据CRC检查失败," + crcStr, null))} ;
            }
            rtuAddr = cp.parseRtuAddr(upBuffer) ;
            upCode = cp.parseCode(upBuffer) ;
            if(upCode == null){
                return new MidResult[]{(new MidResultError(ProtocolConstantV206V1_0_0.protocolName, rtuAddr, "严重错误,未能从上行数据中解析出功能码!", null))} ;
            }
            //Integer dataLen = cp.parseFrameLen(upBuffer) ;
            Data upData = new Data() ;
            upData.setRtuAddr(rtuAddr) ;
            upData.setProtocol(ProtocolConstantV206V1_0_0.protocolName);
            upData.setCode(upCode) ;
            upData.setHex(upHex) ;
            DataV1_0_1 dV1_0_1 = new DataV1_0_1() ;
            //dV1_0_1.version = cp.parseVersion(upBuffer) ;
            dV1_0_1.rtuAddr = rtuAddr ;
            dV1_0_1.dt = DateTime.yyyy_MM_dd_HH_mm_ss() ;
            upData.setSubData(dV1_0_1) ;
            this.upCpParams.clear();
            this.upCpParams.setValue(ProtocolConstantV206V1_0_0.protocolName,
                    rtuAddr,
                    upCode,
                    upHex,
                    upBuffer,
                    upData);
            CodeParse codeParse = this.getUpCodeParser(upCode) ;
            if(codeParse == null){
                return new MidResult[]{(new MidResultError(ProtocolConstantV206V1_0_0.protocolName, rtuAddr, "严重错误,未能得到上行数据功能码" + upCode + "处理类!", null))} ;
            }else{
                return codeParse.parse(isLowPower, this.upCpParams, new CodeParseCallback(){
                    @Override
                    public void callback(Boolean flag) {
                        reportOrResponse_trueOrFalse = flag ;
                        rtuAddrInData = dV1_0_1.getRtuAddr() ;
                    }
                });
            }
        } catch (Exception e) {
            isFail = true ;
            return new MidResult[]{(new MidResultError(ProtocolConstantV206V1_0_0.protocolName, rtuAddr, "严重错误,分析Rtu数据出错!数据为:" + upHex + (e.getMessage() == null?"":(",出错信息:" + e.getMessage())), e))} ;
        } finally{
            callback.callback(rtuAddr, upCode, upHex, reportOrResponse_trueOrFalse, isFail, rtuAddrInData);
        }
    }
    /**
     * æž„造下行数据(命令)
     * @param isLowPower æ˜¯å¦åœ¨ä½ŽåŠŸè€—çŽ¯å¢ƒä¸‹è¿è¡Œ
     * @param command å‘½ä»¤
     * @return
     */
    @Override
    public MidResult[] createCommand(Boolean isLowPower, Command command, Object... params) {
        String rtuAddr = command.getRtuAddr() ;
        if(rtuAddr == null){
            return new MidResult[]{(new MidResultError(ProtocolConstantV206V1_0_0.protocolName, null, "严重错误,命令中Rtu地址为空,不能构建任何命令!", null))} ;
        }
        try {
            String commandCode = command.getCode() ;
            this.downCpParams.clear();
            this.downCpParams.setValue(
                    ProtocolConstantV206V1_0_0.protocolName,
                    rtuAddr,
                    command.getId(),
                    commandCode,
                    command.getParam(),
                    command.getAttachment());
            if(commandCode == null){
                return new MidResult[]{(new MidResultError(ProtocolConstantV206V1_0_0.protocolName, rtuAddr,  "严重错误,命令中功能码为空,不能构建任何命令!", null))} ;
            }else{
                CodeParse codeParse = this.getDownCodeParser(commandCode) ;
                if(codeParse == null){
                    return new MidResult[]{(new MidResultError(ProtocolConstantV206V1_0_0.protocolName, rtuAddr,  "严重错误,未能得到下行数据功能码" + commandCode + "处理类!", null))} ;
                }else{
                    return codeParse.parse(isLowPower, this.downCpParams, null);
                }
            }
        } catch (Exception e) {
            return new MidResult[]{(new MidResultError(ProtocolConstantV206V1_0_0.protocolName, rtuAddr,  "严重错误,构造下行数据出错!命令为:" + command.toString(), e))} ;
        }
    }
}
pipIrr-platform/pipIrr-common/src/main/java/com/dy/common/mw/protocol/p206V1_0_0/PrefixedDataAvailableV1_0_1.java
New file
@@ -0,0 +1,130 @@
package com.dy.common.mw.protocol.p206V1_0_0;
import com.dy.common.mw.channel.tcp.PrefixedDataAvailableStatus;
import com.dy.common.mw.protocol.AnnotationPrefixedDataAvailable;
import com.dy.common.mw.protocol.PrefixedDataAvailable;
import com.dy.common.util.ByteUtil;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.mina.core.buffer.BufferDataException;
import org.apache.mina.core.buffer.IoBuffer;
@AnnotationPrefixedDataAvailable(
        protocolName = ProtocolConstantV206V1_0_0.protocolName,
        priority = ProtocolConstantV206V1_0_0.priority,
        onLineDataMinLength = ProtocolConstantV206V1_0_0.onLineDataMinLength,
        headMinLength = ProtocolConstantV206V1_0_0.headMinLength)
@SuppressWarnings("unused")
public class PrefixedDataAvailableV1_0_1 implements PrefixedDataAvailable {
    private static final Logger log = LogManager.getLogger(PrefixedDataAvailableV1_0_1.class) ;
    private static final String protocolName = ProtocolConstantV206V1_0_0.protocolName ;
    /**
     * åˆ†æžä¸Šçº¿æ•°æ®(网络连接后第一包数据)是否可获得
     * @param in IoBuffer
     * @param remain ä¸€å®šæ—¶å¤§äºŽ0的数据
     * @param minDataLength æœ€å°æ•°æ®é•¿åº¦
     * @param maxDataLength æœ€å¤§æ•°æ®é•¿åº¦ï¼Œè¾¾åˆ°æˆ–超过此长度,认为是垃圾数据。例如:数据头部是正确的,但合法数据结尾总不出现,认为此数据垃圾数据
     * @return ä¸æ˜¯æœ¬åè®®æ•°æ®æ—¶è¿”回空
     * @throws Exception å¼‚常
     */
    public PrefixedDataAvailableStatus forOnLine(IoBuffer in,
            int remain,
            int minDataLength, //对应ProtocolConstantV2_0.onLineDataMinLength
            int maxDataLength //对应ProtocolConstant.errorMaxLength
            ) throws Exception {
        int oldPosition = in.position() ;
        byte[] preByte = new byte[remain];
        in.get(preByte) ;
        //in.position(0) ;//错误用法,如果发生粘包数据,将会死循环
        in.position(oldPosition) ;
        return this.doForData(preByte, minDataLength, maxDataLength) ;
    }
    /**
     * åˆ†æžä¸Šçº¿åŽ(网络连接后非第一包数据)是否可获得
     * @param in IoBuffer
     * @param remain  å‰©ä½™
     * @param minDataLength æœ€å°æ•°æ®é•¿åº¦
     * @param maxDataLength æœ€å¤§æ•°æ®é•¿åº¦
     * @return PrefixedDataAvailableStatus
     * @throws Exception å¼‚常
     */
    @Override
    public PrefixedDataAvailableStatus forUpData(IoBuffer in,
            int remain,
            int minDataLength,
            int maxDataLength) throws Exception {
        int oldPosition = in.position() ;
        byte[] preByte = new byte[remain];
        in.get(preByte) ;
        //in.position(0) ;//错误用法,如果发生粘包数据,将会死循环
        in.position(oldPosition) ;
        return this.doForData(preByte, minDataLength, maxDataLength) ;
    }
    /**
     * è¿›è¡Œåˆ¤æ–­
     * @param preByte byte[]
     * @param minDataLength æœ€å°æ•°æ®é•¿åº¦
     * @param maxDataLength æœ€å¤§æ•°æ®é•¿åº¦
     * @return PrefixedDataAvailableStatus
     * @throws Exception å¼‚常
     */
    private PrefixedDataAvailableStatus doForData(byte[] preByte, int minDataLength, int maxDataLength) throws Exception{
        int remain = preByte.length ;
        if (remain < minDataLength) {
            log.warn("基于协议(" + protocolName + ")判断数据头部发生断包现象。") ;
            return new PrefixedDataAvailableStatus().breaked() ;
        }
        if(remain >= maxDataLength){
            //超出了最大长度限制,例如:数据头部是正确的,但合法数据结尾总不出现,认为此数据垃圾数据
            return new PrefixedDataAvailableStatus().rubbish(remain) ;
        }
        CommonV1_0_1 parseCommon = new CommonV1_0_1();
        boolean isThisProtocolData = parseCommon.isThisProtocolHead(preByte) ;
        if(!isThisProtocolData){
            //不是本协议数据
            return null ;
        }
        Integer dataLen = parseCommon.parseFrameLen(preByte) ;
        if(dataLen == null){
            String headHex = ByteUtil.bytes2Hex(preByte, true) ;
            throw new BufferDataException("收到数据之帧前部:" + headHex + ",但严重错误,在进行断包与粘包检查时,未能得到数据帧的长度。");
        }
        if (dataLen <= 0 || dataLen > maxDataLength) {
            String headHex = ByteUtil.bytes2Hex(preByte, true) ;
            throw new BufferDataException("收到数据之帧前部:" + headHex + ",但严重错误,在进行断包与粘包检查时,数据帧的长度(" + dataLen + ")超出合法范围。");
        }
        if(remain == dataLen){
            //不断不粘
            return new PrefixedDataAvailableStatus().completed(dataLen) ;
        }else if(remain > dataLen){
            String headHex = ByteUtil.bytes2Hex(preByte, true) ;
            log.warn("收到数据之帧前部:" + headHex + ",但发生粘包现象。") ;
            return new PrefixedDataAvailableStatus().adjoined(dataLen) ;
        }else{
            // remain < dataLen
            String headHex = ByteUtil.bytes2Hex(preByte, true) ;
            log.warn("收到数据之帧前部:" + headHex + ",但发生断包现象。") ;
            return new PrefixedDataAvailableStatus().breaked() ;
        }
    }
}
pipIrr-platform/pipIrr-common/src/main/java/com/dy/common/mw/protocol/p206V1_0_0/ProtocolConstantV206V1_0_0.java
New file
@@ -0,0 +1,53 @@
package com.dy.common.mw.protocol.p206V1_0_0;
public class ProtocolConstantV206V1_0_0 {
    public static final String version = "1.0.1" ;
    public static final Byte versionByte = 101 ;
    /**
     * æ³¨è§£ç›¸å…³
     */
    public static final String protocolName = "p206V1_0_1" ;
    public static final int priority = 1 ;//优先级
    /**
     * RTU上线数据(上线后第一包数据)最小长度,设置该属性以备进行完整性检查,
     * å³æ–­åŒ…检查,使尽可能收全上线数据(取值范围1-100)
     */
    public static final int onLineDataMinLength = 13 ;//采用心跳上行数据长度
    /**
     * RTU上报数据的头部最小长度,上报数据中,取这个最小长度的部分数据中,
     * è¦ä¸€å®šåŒ…含数据帧长度,以备取出数据帧长度来,进行完整性检查,
     * å³æ–­åŒ…与粘包检查(取值范围0-100,其中取值为0时,表示headMinLength数据无作用,由协议实现来控制)
     */
    public static final int headMinLength = 3 ;
    //帧起始
    public static final byte P_Head_Byte = (byte)0x68 ;
    public static final byte P_Tail_Byte = (byte)0x16 ;
    public static final byte P_Default_mode = (byte)0x0F ;//默认工作模式
    public static final String P_Head_Hex = "68" ;
    public static final String P_Tail_Hex = "16" ;
    public static final byte lenHead2ctrl = 3 ; //从头到控制域(不包括)字节数组长度
    public static final byte lenHead2Code = 10 ; //从头到功能码(包括)字节数组长度
    public static final byte lenTail = 2 ; //帧尾部字节数组长度
    /**
     * æ‰€åœ¨å­—节数组的位置(下标)
     */
    public static final int dataLenIndex = 1 ;//帧长度所在 å­—节数组起始下标
    public static final int ctrlIndex = 3 ;//控制域所在 å­—节数组起始下标
    public static final int rtuAddr1Index_start = 4 ;//控制器地址 å­—节数组开始下标
    public static final int rtuAddr1Index_end = 6 ;//控制器地址 å­—节数组开始下标
    public static final int rtuAddr2Index_start = 7 ;//控制器地址 å­—节数组截止下标
    public static final int rtuAddr2Index_end = 8 ;//控制器地址 å­—节数组截止下标
    public static final int codeIndex = 9 ;//功能码字节数组下标
    public static final int dataIndex = 10 ;//具体数据字节数组下标
}
pipIrr-platform/pipIrr-common/src/main/java/com/dy/common/mw/protocol/p206V1_0_0/parse/Cd_02_Down.java
New file
@@ -0,0 +1,82 @@
package com.dy.common.mw.protocol.p206V1_0_0.parse;
import com.dy.common.mw.protocol.*;
import com.dy.common.mw.protocol.p206V1_0_0.*;
import com.dy.common.mw.protocol.p206V1_0_0.parse.global.GlCreate;
import com.dy.common.util.ByteUtil;
@AnnotationCodeDown(ifAny={
        CodeV1_0_1.cd_02
})
public class Cd_02_Down  implements CodeParse {
    //private static Logger log = LogManager.getLogger(Cd_02_Down.class);
    @Override
    public MidResult[] parse(Boolean isLowPower, CodeParseParams params, CodeParseCallback callback) throws Exception {
        ParseParamsForDownV1_0_1 para = (ParseParamsForDownV1_0_1) params ;
        byte[] bs = this.doParse(para) ;
        MidResultToRtu midRs = new MidResultToRtu() ;
        midRs.protocolName = para.protocolName ;//协议名称
        midRs.rtuAddr = para.rtuAddr ;//Rtu地址(电信平台设备IMEI)
        midRs.commandId = para.commandId ;//命令ID,发起命令的客户端(web端)生成,以匹配命令结果
        midRs.downCode = para.commandCode ;//下行命令功能码;
        midRs.downBuffer = bs ;//下行命令数据
        midRs.downBufHex = ByteUtil.bytes2Hex(bs, true) ;//下行命令数据十六进制形式
        midRs.hasResponse = false ;//是否有应答
        midRs.maxSendTimes = 1 ;//命令最大发送次数(当收不到应答时,将重发),如果不设置,命令缓存器进行补充设置
        midRs.isCachForOffLine = false ;//RTU不在线,命令是否缓存,低功耗时为true
        midRs.isSendFirst = true ;//命令应答,首先发送,防止RTU重新上报
        if(isLowPower != null && isLowPower.booleanValue()){
            //低功耗时,尽快发送
            midRs.isQuickSend = true ;
        }
        return new MidResult[]{midRs} ;
    }
    /**
     * æž„造下行数据
     * @param para å‚æ•°
     * @return å­—节数组
     * @throws Exception å¼‚常
     */
    public byte[] doParse(ParseParamsForDownV1_0_1 para) throws Exception {
        CommonV1_0_1 commonV1_0_1 = new CommonV1_0_1() ;
        byte[] bytes ;
        byte[] bsHead = new byte[ProtocolConstantV206V1_0_0.lenHead2Code] ;
        byte index = 0 ;
        bsHead[index] = ProtocolConstantV206V1_0_0.P_Head_Byte ;
        index++ ;
        bsHead[index] = 0 ;//帧长度
        index++ ;
        bsHead[index] = ProtocolConstantV206V1_0_0.P_Head_Byte ;
        index++ ;
        bsHead[index] = commonV1_0_1.createCtrl((byte)0, (byte)0) ;
        index++ ;
        GlCreate.createRtuAddr(para.rtuAddr, bsHead, index);
        index += 5 ;
        ByteUtil.hex2Bytes(para.commandCode, bsHead, index) ;
        byte[] bs = new byte[7] ;
        bs[0] = (byte)0xF2 ;//数据域: 1 ä¸ªå­—节,F0 ç™»å½•, F1 é€€å‡ºç™»å½•,F2 åœ¨çº¿ä¿æŒã€‚
        GlCreate.createTp(bs, 1);
        bytes = ByteUtil.bytesMerge(bsHead, bs) ;
        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/p206V1_0_0/parse/Cd_71_Down.java
New file
@@ -0,0 +1,87 @@
package com.dy.common.mw.protocol.p206V1_0_0.parse;
import com.dy.common.mw.protocol.*;
import com.dy.common.mw.protocol.p206V1_0_0.CodeV1_0_1;
import com.dy.common.mw.protocol.p206V1_0_0.CommonV1_0_1;
import com.dy.common.mw.protocol.p206V1_0_0.ParseParamsForDownV1_0_1;
import com.dy.common.mw.protocol.p206V1_0_0.ProtocolConstantV206V1_0_0;
import com.dy.common.mw.protocol.p206V1_0_0.parse.global.GlCreate;
import com.dy.common.util.ByteUtil;
@AnnotationCodeDown(ifAny={
        CodeV1_0_1.cd_71
})
public class Cd_71_Down implements CodeParse {
    //private static Logger log = LogManager.getLogger(Cd_71_Down.class);
    @Override
    public MidResult[] parse(Boolean isLowPower, CodeParseParams params, CodeParseCallback callback) throws Exception {
        ParseParamsForDownV1_0_1 para = (ParseParamsForDownV1_0_1) params ;
        byte[] bs = this.doParse(para) ;
        MidResultToRtu midRs = new MidResultToRtu() ;
        midRs.protocolName = para.protocolName ;//协议名称
        midRs.rtuAddr = para.rtuAddr ;//Rtu地址(电信平台设备IMEI)
        midRs.commandId = para.commandId ;//命令ID,发起命令的客户端(web端)生成,以匹配命令结果
        midRs.downCode = para.commandCode ;//下行命令功能码;
        midRs.downBuffer = bs ;//下行命令数据
        midRs.downBufHex = ByteUtil.bytes2Hex(bs, true) ;//下行命令数据十六进制形式
        midRs.hasResponse = true ;//是否有应答
        midRs.maxSendTimes = null ;//命令最大发送次数(当收不到应答时,将重发),如果不设置,命令缓存器进行补充设置
        midRs.isCachForOffLine = false ;//RTU不在线,命令是否缓存,低功耗时为true
        if(isLowPower != null && isLowPower.booleanValue()){
            //低功耗时,尽快发送
            midRs.isQuickSend = true ;
        }
        return new MidResult[]{midRs} ;
    }
    /**
     * æž„造下行数据
     * @param para å‚æ•°
     * @return å­—节数组
     * @throws Exception å¼‚常
     */
    public byte[] doParse(ParseParamsForDownV1_0_1 para) throws Exception {
        CommonV1_0_1 commonV1_0_1 = new CommonV1_0_1() ;
        byte[] bytes ;
        byte[] bsHead = new byte[ProtocolConstantV206V1_0_0.lenHead2Code] ;
        byte index = 0 ;
        bsHead[index] = ProtocolConstantV206V1_0_0.P_Head_Byte ;
        index++ ;
        bsHead[index] = 0 ;//帧长度
        index++ ;
        bsHead[index] = ProtocolConstantV206V1_0_0.P_Head_Byte ;
        index++ ;
        bsHead[index] = commonV1_0_1.createCtrl((byte)0, (byte)0) ;
        index++ ;
        GlCreate.createRtuAddr(para.rtuAddr, bsHead, index);
        index += 5 ;
        ByteUtil.hex2Bytes(para.commandCode, bsHead, index) ;
        byte[] bs = new byte[0] ;
        //确认帧的数据域用于遥测终端工作模式的确认或转换。数据为 1 ä¸ªå­—节 HEX,00H æ—¶é¥æµ‹ç»ˆ
        //端在兼容工作状态; 01H æ—¶é¥æµ‹ç»ˆç«¯åœ¨è‡ªæŠ¥å·¥ä½œçŠ¶æ€ï¼› 02H æ—¶é¥æµ‹ç»ˆç«¯åœ¨æŸ¥è¯¢/应答工作
        //状态; 03H æ—¶é¥æµ‹ç»ˆç«¯åœ¨è°ƒè¯•/维修状态。
        bs[0] = (byte)0xF1;//数据域
        bytes = ByteUtil.bytesMerge(bsHead, bs) ;
        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/p206V1_0_0/parse/Cd_83_Down.java
New file
@@ -0,0 +1,89 @@
package com.dy.common.mw.protocol.p206V1_0_0.parse;
import com.dy.common.mw.protocol.*;
import com.dy.common.mw.protocol.p206V1_0_0.CodeV1_0_1;
import com.dy.common.mw.protocol.p206V1_0_0.CommonV1_0_1;
import com.dy.common.mw.protocol.p206V1_0_0.ParseParamsForDownV1_0_1;
import com.dy.common.mw.protocol.p206V1_0_0.ProtocolConstantV206V1_0_0;
import com.dy.common.mw.protocol.p206V1_0_0.parse.global.GlCreate;
import com.dy.common.util.ByteUtil;
@AnnotationCodeDown(ifAny={
        CodeV1_0_1.cd_83
})
public class Cd_83_Down implements CodeParse {
    //private static Logger log = LogManager.getLogger(Cd_C0_Down.class);
    @Override
    public MidResult[] parse(Boolean isLowPower, CodeParseParams params, CodeParseCallback callback) throws Exception {
        ParseParamsForDownV1_0_1 para = (ParseParamsForDownV1_0_1) params ;
        byte[] bs = this.doParse(para) ;
        MidResultToRtu midRs = new MidResultToRtu() ;
        midRs.protocolName = para.protocolName ;//协议名称
        midRs.rtuAddr = para.rtuAddr ;//Rtu地址(电信平台设备IMEI)
        midRs.commandId = para.commandId ;//命令ID,发起命令的客户端(web端)生成,以匹配命令结果
        midRs.downCode = para.commandCode ;//下行命令功能码;
        midRs.downBuffer = bs ;//下行命令数据
        midRs.downBufHex = ByteUtil.bytes2Hex(bs, true) ;//下行命令数据十六进制形式
        midRs.hasResponse = false ;//是否有应答
        midRs.maxSendTimes = 1 ;//命令最大发送次数(当收不到应答时,将重发),如果不设置,命令缓存器进行补充设置
        midRs.isCachForOffLine = false ;//RTU不在线,命令是否缓存,低功耗时为true
        midRs.isSendFirst = true ;//命令应答,首先发送,防止RTU重新上报
        if(isLowPower != null && isLowPower.booleanValue()){
            //低功耗时,尽快发送
            midRs.isQuickSend = true ;
        }
        return new MidResult[]{midRs} ;
    }
    /**
     * æž„造下行数据
     * @param para å‚æ•°
     * @return å­—节数组
     * @throws Exception å¼‚常
     */
    public byte[] doParse(ParseParamsForDownV1_0_1 para) throws Exception {
        CommonV1_0_1 commonV1_0_1 = new CommonV1_0_1() ;
        byte[] bytes ;
        byte[] bsHead = new byte[ProtocolConstantV206V1_0_0.lenHead2Code] ;
        byte index = 0 ;
        bsHead[index] = ProtocolConstantV206V1_0_0.P_Head_Byte ;
        index++ ;
        bsHead[index] = 0 ;//帧长度
        index++ ;
        bsHead[index] = ProtocolConstantV206V1_0_0.P_Head_Byte ;
        index++ ;
        bsHead[index] = commonV1_0_1.createCtrl((byte)0, (byte)0) ;
        index++ ;
        GlCreate.createRtuAddr(para.rtuAddr, bsHead, index);
        index += 5 ;
        ByteUtil.hex2Bytes(para.commandCode, bsHead, index) ;
        byte[] bs = new byte[7] ;
        //确认帧的数据域用于遥测终端工作模式的确认或转换。数据为 1 ä¸ªå­—节 HEX,00H æ—¶é¥æµ‹ç»ˆ
        //端在兼容工作状态; 01H æ—¶é¥æµ‹ç»ˆç«¯åœ¨è‡ªæŠ¥å·¥ä½œçŠ¶æ€ï¼› 02H æ—¶é¥æµ‹ç»ˆç«¯åœ¨æŸ¥è¯¢/应答工作
        //状态; 03H æ—¶é¥æµ‹ç»ˆç«¯åœ¨è°ƒè¯•/维修状态。
        bs[0] = ProtocolConstantV206V1_0_0.P_Default_mode;//数据域
        GlCreate.createTp(bs, 1);
        bytes = ByteUtil.bytesMerge(bsHead, bs) ;
        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/p206V1_0_0/parse/Cd_84_Down.java
New file
@@ -0,0 +1,89 @@
package com.dy.common.mw.protocol.p206V1_0_0.parse;
import com.dy.common.mw.protocol.*;
import com.dy.common.mw.protocol.p206V1_0_0.CodeV1_0_1;
import com.dy.common.mw.protocol.p206V1_0_0.CommonV1_0_1;
import com.dy.common.mw.protocol.p206V1_0_0.ParseParamsForDownV1_0_1;
import com.dy.common.mw.protocol.p206V1_0_0.ProtocolConstantV206V1_0_0;
import com.dy.common.mw.protocol.p206V1_0_0.parse.global.GlCreate;
import com.dy.common.util.ByteUtil;
@AnnotationCodeDown(ifAny={
        CodeV1_0_1.cd_84
})
public class Cd_84_Down implements CodeParse {
    //private static Logger log = LogManager.getLogger(Cd_C0_Down.class);
    @Override
    public MidResult[] parse(Boolean isLowPower, CodeParseParams params, CodeParseCallback callback) throws Exception {
        ParseParamsForDownV1_0_1 para = (ParseParamsForDownV1_0_1) params ;
        byte[] bs = this.doParse(para) ;
        MidResultToRtu midRs = new MidResultToRtu() ;
        midRs.protocolName = para.protocolName ;//协议名称
        midRs.rtuAddr = para.rtuAddr ;//Rtu地址(电信平台设备IMEI)
        midRs.commandId = para.commandId ;//命令ID,发起命令的客户端(web端)生成,以匹配命令结果
        midRs.downCode = para.commandCode ;//下行命令功能码;
        midRs.downBuffer = bs ;//下行命令数据
        midRs.downBufHex = ByteUtil.bytes2Hex(bs, true) ;//下行命令数据十六进制形式
        midRs.hasResponse = false ;//是否有应答
        midRs.maxSendTimes = 1 ;//命令最大发送次数(当收不到应答时,将重发),如果不设置,命令缓存器进行补充设置
        midRs.isCachForOffLine = false ;//RTU不在线,命令是否缓存,低功耗时为true
        midRs.isSendFirst = true ;//命令应答,首先发送,防止RTU重新上报
        if(isLowPower != null && isLowPower.booleanValue()){
            //低功耗时,尽快发送
            midRs.isQuickSend = true ;
        }
        return new MidResult[]{midRs} ;
    }
    /**
     * æž„造下行数据
     * @param para å‚æ•°
     * @return å­—节数组
     * @throws Exception å¼‚常
     */
    public byte[] doParse(ParseParamsForDownV1_0_1 para) throws Exception {
        CommonV1_0_1 commonV1_0_1 = new CommonV1_0_1() ;
        byte[] bytes ;
        byte[] bsHead = new byte[ProtocolConstantV206V1_0_0.lenHead2Code] ;
        byte index = 0 ;
        bsHead[index] = ProtocolConstantV206V1_0_0.P_Head_Byte ;
        index++ ;
        bsHead[index] = 0 ;//帧长度
        index++ ;
        bsHead[index] = ProtocolConstantV206V1_0_0.P_Head_Byte ;
        index++ ;
        bsHead[index] = commonV1_0_1.createCtrl((byte)0, (byte)0) ;
        index++ ;
        GlCreate.createRtuAddr(para.rtuAddr, bsHead, index);
        index += 5 ;
        ByteUtil.hex2Bytes(para.commandCode, bsHead, index) ;
        byte[] bs = new byte[7] ;
        //确认帧的数据域用于遥测终端工作模式的确认或转换。数据为 1 ä¸ªå­—节 HEX,00H æ—¶é¥æµ‹ç»ˆ
        //端在兼容工作状态; 01H æ—¶é¥æµ‹ç»ˆç«¯åœ¨è‡ªæŠ¥å·¥ä½œçŠ¶æ€ï¼› 02H æ—¶é¥æµ‹ç»ˆç«¯åœ¨æŸ¥è¯¢/应答工作
        //状态; 03H æ—¶é¥æµ‹ç»ˆç«¯åœ¨è°ƒè¯•/维修状态。
        bs[0] = ProtocolConstantV206V1_0_0.P_Default_mode;//数据域
        GlCreate.createTp(bs, 1);
        bytes = ByteUtil.bytesMerge(bsHead, bs) ;
        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/p206V1_0_0/parse/Cd_C0_Down.java
New file
@@ -0,0 +1,89 @@
package com.dy.common.mw.protocol.p206V1_0_0.parse;
import com.dy.common.mw.protocol.*;
import com.dy.common.mw.protocol.p206V1_0_0.CodeV1_0_1;
import com.dy.common.mw.protocol.p206V1_0_0.CommonV1_0_1;
import com.dy.common.mw.protocol.p206V1_0_0.ParseParamsForDownV1_0_1;
import com.dy.common.mw.protocol.p206V1_0_0.ProtocolConstantV206V1_0_0;
import com.dy.common.mw.protocol.p206V1_0_0.parse.global.GlCreate;
import com.dy.common.util.ByteUtil;
@AnnotationCodeDown(ifAny={
        CodeV1_0_1.cd_C0
})
public class Cd_C0_Down  implements CodeParse {
    //private static Logger log = LogManager.getLogger(Cd_C0_Down.class);
    @Override
    public MidResult[] parse(Boolean isLowPower, CodeParseParams params, CodeParseCallback callback) throws Exception {
        ParseParamsForDownV1_0_1 para = (ParseParamsForDownV1_0_1) params ;
        byte[] bs = this.doParse(para) ;
        MidResultToRtu midRs = new MidResultToRtu() ;
        midRs.protocolName = para.protocolName ;//协议名称
        midRs.rtuAddr = para.rtuAddr ;//Rtu地址(电信平台设备IMEI)
        midRs.commandId = para.commandId ;//命令ID,发起命令的客户端(web端)生成,以匹配命令结果
        midRs.downCode = para.commandCode ;//下行命令功能码;
        midRs.downBuffer = bs ;//下行命令数据
        midRs.downBufHex = ByteUtil.bytes2Hex(bs, true) ;//下行命令数据十六进制形式
        midRs.hasResponse = false ;//是否有应答
        midRs.maxSendTimes = 1 ;//命令最大发送次数(当收不到应答时,将重发),如果不设置,命令缓存器进行补充设置
        midRs.isCachForOffLine = false ;//RTU不在线,命令是否缓存,低功耗时为true
        midRs.isSendFirst = true ;//命令应答,首先发送,防止RTU重新上报
        if(isLowPower != null && isLowPower.booleanValue()){
            //低功耗时,尽快发送
            midRs.isQuickSend = true ;
        }
        return new MidResult[]{midRs} ;
    }
    /**
     * æž„造下行数据
     * @param para å‚æ•°
     * @return å­—节数组
     * @throws Exception å¼‚常
     */
    public byte[] doParse(ParseParamsForDownV1_0_1 para) throws Exception {
        CommonV1_0_1 commonV1_0_1 = new CommonV1_0_1() ;
        byte[] bytes ;
        byte[] bsHead = new byte[ProtocolConstantV206V1_0_0.lenHead2Code] ;
        byte index = 0 ;
        bsHead[index] = ProtocolConstantV206V1_0_0.P_Head_Byte ;
        index++ ;
        bsHead[index] = 0 ;//帧长度
        index++ ;
        bsHead[index] = ProtocolConstantV206V1_0_0.P_Head_Byte ;
        index++ ;
        bsHead[index] = commonV1_0_1.createCtrl((byte)0, (byte)0) ;
        index++ ;
        GlCreate.createRtuAddr(para.rtuAddr, bsHead, index);
        index += 5 ;
        ByteUtil.hex2Bytes(para.commandCode, bsHead, index) ;
        byte[] bs = new byte[7] ;
        //确认帧的数据域用于遥测终端工作模式的确认或转换。数据为 1 ä¸ªå­—节 HEX,00H æ—¶é¥æµ‹ç»ˆ
        //端在兼容工作状态; 01H æ—¶é¥æµ‹ç»ˆç«¯åœ¨è‡ªæŠ¥å·¥ä½œçŠ¶æ€ï¼› 02H æ—¶é¥æµ‹ç»ˆç«¯åœ¨æŸ¥è¯¢/应答工作
        //状态; 03H æ—¶é¥æµ‹ç»ˆç«¯åœ¨è°ƒè¯•/维修状态。
        bs[0] = ProtocolConstantV206V1_0_0.P_Default_mode;//数据域
        GlCreate.createTp(bs, 1);
        bytes = ByteUtil.bytesMerge(bsHead, bs) ;
        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/p206V1_0_0/parse/global/GlCreate.java
New file
@@ -0,0 +1,38 @@
package com.dy.common.mw.protocol.p206V1_0_0.parse.global;
import com.dy.common.mw.protocol.p206V1_0_0.ProtocolConstantV206V1_0_0;
import com.dy.common.util.ByteUtil;
import com.dy.common.util.ByteUtilUnsigned;
import com.dy.common.util.CRC8_for_2_0;
import com.dy.common.util.DateTime;
public class GlCreate {
    public static void createRtuAddr(String rtuAddr, byte[] bs, int index) throws Exception {
        String rtuAddr1 = rtuAddr.substring(0, 6) ;
        String rtuAddr2 = rtuAddr.substring(6) ;
        ByteUtil.string2BCD_BE(bs, rtuAddr1, index) ;
        index += 3 ;
        Integer rtuAddr2Int = Integer.parseInt(rtuAddr2) ;
        ByteUtilUnsigned.short2Bytes_BE(bs, rtuAddr2Int.shortValue(), index);
    }
    public static void createTp(byte[] bs, int index) throws Exception {
        ByteUtil.string2BCD_LE(bs, DateTime.yyMMddhhmmss(), index) ;
    }
    public static void createLen(byte[] bsNoTail) throws Exception {
        int len = bsNoTail.length - ProtocolConstantV206V1_0_0.lenHead2ctrl;
        bsNoTail[ProtocolConstantV206V1_0_0.dataLenIndex] = (byte)len ;
    }
    public static byte[] createCrcTail(byte[] bsNoTail) throws Exception {
        int crc = new CRC8_for_2_0().CRC8(bsNoTail, ProtocolConstantV206V1_0_0.ctrlIndex, bsNoTail.length -1) ;
        byte[] bytes = new byte[ProtocolConstantV206V1_0_0.lenTail] ;
        bytes[0] = (byte)crc ;
        bytes[1] = ProtocolConstantV206V1_0_0.P_Tail_Byte ;
        return bytes ;
    }
}
pipIrr-platform/pipIrr-common/src/main/java/com/dy/common/mw/protocol/p206V1_0_0/parse/global/GlParse.java
New file
@@ -0,0 +1,56 @@
package com.dy.common.mw.protocol.p206V1_0_0.parse.global;
import com.dy.common.mw.protocol.p206V1_0_0.DataAlarmVo;
import com.dy.common.mw.protocol.p206V1_0_0.DataStateVo;
import com.dy.common.util.ByteUtil;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
public class GlParse {
    private static final Logger log = LogManager.getLogger(GlParse.class);
    public static DataAlarmVo parseAlarm(byte[] bs, short index){
        DataAlarmVo avo = new DataAlarmVo() ;
        byte b = bs[index] ;
        index++ ;
        avo.batteryVolt = (byte)(b & 0x2) ;
        avo.loss = (byte)(b & 0x8) ;
        avo.meter = (byte)(b & 0x20) ;
        b = bs[index] ;
        avo.valve = (byte)(b & 0x20) ;
        return avo ;
    }
    public static DataStateVo parseState(byte[] bs, short index){
        DataStateVo avo = new DataStateVo() ;
        byte b = bs[index] ;
        index++ ;
        avo.idCard = (byte)(b & 0x4) ;
        avo.work = (byte)(b & 0x8) ;
        avo.valve = (byte)(b & 0x20) ;
        return avo ;
    }
    public static String parseTp(byte[] bs, short index){
        String dt = "" ;
        try{
            dt = dt + ByteUtil.BCD2String_BE(bs, index, index) ;//秒
            index++ ;
            dt = ByteUtil.BCD2String_BE(bs, index, index) + ":" + dt ;//分
            index++ ;
            dt = ByteUtil.BCD2String_BE(bs, index, index) + ":" + dt ;//时
            index++ ;
            dt = ByteUtil.BCD2String_BE(bs, index, index) + " " + dt ;//日
            index++ ;
            bs[index] = (byte)(bs[index] & 0x10);
            dt = ByteUtil.BCD2String_BE(bs, index, index) + "-" + dt ;//月
            index++ ;
            dt = "20" + ByteUtil.BCD2String_BE(bs, index, index) + "-" + dt ;//å¹´
        }catch (Exception e){
            log.error("解析控制器时钟时异常:" + e.getMessage(), e);
        }
        return dt ;
    }
}
pipIrr-platform/pipIrr-global/src/main/java/com/dy/pipIrrGlobal/test/TestConflict.java
@@ -7,4 +7,11 @@
    public void test2(){
        System.out.println("test2");
    }
    public void test3(){
        System.out.println("test31");
        System.out.println("test32");
        System.out.println("test33");
        System.out.println("test34");
        System.out.println("test33");
    }
}
pipIrr-platform/pipIrr-mw/pipIrr-mw-accept/pom.xml
@@ -132,4 +132,124 @@
            <scope>test</scope>
        </dependency>
    </dependencies>
</project>
    <build>
        <plugins>
            <!-- ç”Ÿæˆä¸åŒ…含依赖jar的可执行jar包
            <plugin>
                !- spring boot提供的maven打包插件 -
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <executions>
                    <execution>
                        !-
                        <goals>
                            <goal>repackage</goal>
                        </goals>
                        -
                        <configuration>
                            !- ä¸åŠ çš„è¯æœ€ç»ˆåŒ…åä¸º: ${artifactId}-${version}.jar, åŠ äº†çš„è¯æœ€ç»ˆåŒ…å: ${artifactId}-${version}-${classifier}.jar  -
                            <classifier>execute</classifier>
                            !- ä¸æŒ‡å®šç”Ÿæˆè·¯å¾„的话, é»˜è®¤ä¿å­˜åœ¨ ${build.directory} ä¸‹ -
                            <outputDirectory>${project.build.directory}/execute</outputDirectory>
                            <finalName>${artifactId}-${version}</finalName>
                            <layout>ZIP</layout>
                            <mainClass>com.dy.pipIrrBase.PipIrrBaseApplication</mainClass>
                            <includes>
                                <include>
                                    <groupId>com.dy</groupId>
                                    <artifactId>pipIrr-common</artifactId>
                                </include>
                                <include>
                                    <groupId>com.dy</groupId>
                                    <artifactId>pipIrr-global</artifactId>
                                </include>
                            </includes>
                            <excludes>
                                <exclude>
                                    <groupId>org.projectlombok</groupId>
                                    <artifactId>lombok</artifactId>
                                </exclude>
                            </excludes>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
            -->
            <!-- æ‹·è´ä¾èµ–çš„jar包到lib目录-->
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <executions>
                    <execution>
                        <configuration>
                            <!-- ä¸åŠ çš„è¯æœ€ç»ˆåŒ…åä¸º: ${artifactId}-${version}.jar, åŠ äº†çš„è¯æœ€ç»ˆåŒ…å: ${artifactId}-${version}-${classifier}.jar
                            <classifier>execute</classifier>
                            -->
                            <!-- ${project.build.directory}是maven变量,内置的,表示target目录,如果不写,将在根目录下创建/lib -->
                            <outputDirectory>${project.build.directory}/lib</outputDirectory>
                            <!-- excludeTransitive:是否不包含间接依赖包,比如我们依赖A,但是A又依赖了B,我们是否也要把B打进去 é»˜è®¤ä¸æ‰“-->
                            <excludeTransitive>false</excludeTransitive>
                            <!-- å¤åˆ¶çš„jar文件去掉版本信息 -->
                            <stripVersion>false</stripVersion>
                            <finalName>${project.artifactId}-${project.version}</finalName>
                            <layout>ZIP</layout>
                            <mainClass>com.dy.aceMw.PipIrrMwAcceptApplication</mainClass>
                            <includes>
                                <include>
                                    <groupId>com.dy</groupId>
                                    <artifactId>pipIrr-common</artifactId>
                                </include>
                                <include>
                                    <groupId>com.dy</groupId>
                                    <artifactId>pipIrr-global</artifactId>
                                </include>
                            </includes>
                            <excludes>
                                <exclude>
                                    <groupId>org.projectlombok</groupId>
                                    <artifactId>lombok</artifactId>
                                </exclude>
                            </excludes>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
            <plugin>
                <!-- è®¾ç½®java编译版本,运行环境版本 -->
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <!-- source: æºä»£ç ç¼–译版本;target: ç›®æ ‡å¹³å°ç¼–译版本;encoding: å­—符集编码。 -->
                <configuration>
                    <source>${java.version}</source>
                    <target>${java.version}</target>
                    <encoding>${encoding}</encoding>
                </configuration>
            </plugin>
            <plugin>
                <!-- è§£å†³èµ„源文件的编码问题 -->
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-resources-plugin</artifactId>
                <configuration>
                    <encoding>${encoding}</encoding>
                </configuration>
            </plugin>
            <plugin>
                <!-- maven里执行测试用例的插件 -->
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-surefire-plugin</artifactId>
                <configuration>
                    <skipTests>true</skipTests>
                </configuration>
            </plugin>
            <plugin>
                <!-- ä¸‹é¢è§£å†³ï¼šå½“进行Maven Lifecycle package时报错:Could not find artifact org.apache.mina:mina-core:bundle:2.2.1 in maven (https://repo1.maven.org/maven2/)-->
                <groupId>org.apache.felix</groupId>
                <artifactId>maven-bundle-plugin</artifactId>
                <extensions>true</extensions>
            </plugin>
        </plugins>
    </build>
</project>
pipIrr-platform/pipIrr-mw/pipIrr-mw-accept/src/main/java/com/dy/aceMw/PipIrrMwAcceptApplication.java
@@ -14,7 +14,7 @@
@EnableAspectJAutoProxy
@EnableMultiDataSource
@ComponentScan(basePackages = {"com.dy.common", "com.dy.pipIrrGlobal", "com.dy.aceMw"})
@MapperScan(basePackages={"com.dy.pipIrrGlobal.daoBa"})
@MapperScan(basePackages={"com.dy.pipIrrGlobal.daoRm"})
public class PipIrrMwAcceptApplication implements CommandLineRunner {
    public static void main(String[] args) {
pipIrr-platform/pipIrr-mw/pipIrr-mw-accept/src/main/java/com/dy/aceMw/Server.java
@@ -3,6 +3,10 @@
import java.util.ArrayList;
import java.util.List;
import com.dy.aceMw.server.*;
import com.dy.aceMw.server.rtuData.RtuDataUnit;
import com.dy.aceMw.server.rtuData.RtuDataUnitConfigVo;
import com.dy.aceMw.server.tasks.FromRtuConstantTask;
import com.dy.common.mw.UnitInterface;
import com.dy.common.mw.UnitStartedCallbackInterface;
import com.dy.common.mw.channel.rmi.RmiConfigVo;
@@ -15,16 +19,9 @@
import com.dy.common.mw.protocol.ProtocolUnit;
import com.dy.common.mw.support.SupportUnit;
import com.dy.common.mw.support.SupportUnitConfigVo;
import com.dy.aceMw.server.AdapterImp_CoreUnit;
import com.dy.aceMw.server.AdapterImp_ProtocolUnit;
import com.dy.aceMw.server.AdapterImp_RmiUnit;
import com.dy.aceMw.server.AdapterImp_TcpUnit;
import com.dy.aceMw.server.ServerProperties;
import com.dy.aceMw.server.tasks.ToRtuConstantTask;
import com.dy.aceMw.server.AdapterImp_SupportUnit;
import com.dy.aceMw.resource.ResourceUnit;
import com.dy.aceMw.resource.ResourceUnitConfigVo;
import com.dy.aceMw.server.AdapterImp_ResourceUnit;
import com.dy.common.springUtil.SpringContextUtil;
import com.dy.common.util.ConfigXml;
import com.dy.common.util.IDLongGenerator;
@@ -146,8 +143,15 @@
            //TCP上行数据时刻缓存时长,当达到时长时,TCP上行数据时刻被清空,采用TCP上行数据时刻目的是,阻止上数据同时下发数据,因为RTU处理不过来
            ServerProperties.lastUpDataTimeLive = conf.getSetAttrPlusInt(doc, "config.base", "lastUpDataTimeLive", null, 0, 5, null) * 1000L ;
            //数据库数据id生成器的id后缀,0是默认的后缀,一般web系统应用,数据中间件id后缀大于等于1
            ServerProperties.dbDataIdSuffix = conf.getSetAttrInt(doc, "config.base", "dbDataIdSuffix", null, 1, 9, null);
            ServerProperties.dbDataIdSuffix = conf.getSetAttrInt(doc, "config.base", "dbDataIdSuffix", null, 0, 99, null);
            //上下行数据缓存队列中缓存数据个数的报警量,这个与现实项目所接水表数相关
            ServerProperties.cacheUpDownDataWarnCount = conf.getSetAttrPlusInt(doc, "config.base", "cacheUpDownDataWarnCount", null, 1, null, null) ;
            //上下行数据缓存队列中缓存数据个数的最大值,这个与现实项目所接水表数相关
            ServerProperties.cacheUpDownDataMaxCount = conf.getSetAttrPlusInt(doc, "config.base", "cacheUpDownDataMaxCount", null, 1, null, null) ;
            if(ServerProperties.cacheUpDownDataMaxCount <= ServerProperties.cacheUpDownDataWarnCount){
                throw new Exception("cacheUpDownDataMaxCount必须大于cacheUpDownDataWarnCount") ;
            }
            //设置ID生成器的后缀
            IDLongGenerator.setSuffix(ServerProperties.dbDataIdSuffix.intValue());
@@ -164,10 +168,7 @@
            protoAdap.setConfig(protoVo);
            ProtocolUnit protoUnit = ProtocolUnit.getInstance();
            protoUnit.setAdapter(protoAdap);
            protoUnit.start(new UnitStartedCallbackInterface(){
                @Override
                public void call(Object obj) {
                }
            protoUnit.start(obj -> {
            });
            units.add(protoUnit) ;
            
@@ -175,39 +176,49 @@
            //支持模块: springHibernate和 çº¿ç¨‹æ± 
            SupportUnitConfigVo supVo = new SupportUnitConfigVo() ;
            //短工作时长线程池,线程负责用时较短的工作任务
            supVo.short_maxThread = conf.getSetAttrPlusInt(doc, "config.support", "short_maxThread", null, 1, 1000, null) ;//池中最大线程数为所有CPU核数+1
            supVo.short_minThread = conf.getSetAttrPlusInt(doc, "config.support", "short_minThread", null, 1, 5, null) ;//池中最小线程数
            supVo.short_maxThread = conf.getSetAttrPlusInt(doc, "config.support", "short_maxThread", null, -1, 1000, null) ;//池中最大线程数为所有CPU核数+1
            if(supVo.short_maxThread < 0){
                supVo.short_maxThread = -1 ;
            }
            supVo.short_minThread = conf.getSetAttrPlusInt(doc, "config.support", "short_minThread", null, -1, 100, null) ;//池中最小线程数
            if(supVo.short_minThread < 0){
                supVo.short_minThread = -1 ;
            }
            supVo.short_freeTimeout = conf.getSetAttrPlusInt(doc, "config.support", "short_freeTimeout", null, 1, 90, null) * 1000 ;//线程数空闲时长,若池中线程数量大于minThread,且有的线程空闲时长超过freeTimeout,则清除该线程,为了不清除,把minThread与maxThread设置相等
            supVo.short_busyTimeout = conf.getSetAttrPlusInt(doc, "config.support", "short_busyTimeout", null, 1, 10, null) * 1000 ;//线程不间断工作时长(单位为秒)超时限,认为线程已经了崩溃,将强制清除,短工作时长设置为5秒
            if(supVo.short_maxThread == 0 || supVo.short_minThread == 0){
                supVo.enableShortThreadPool = false ;
            }else{
                supVo.enableShortThreadPool = true ;
            }
            //长工作时长线程池,线程负责用时较长的工作任务
            supVo.long_maxThread = conf.getSetAttrInt(doc, "config.support", "long_maxThread", null, -1, 1000, null)  ;//池中最大线程数,若为-1,不受限制
            if(supVo.long_maxThread < 0){
                supVo.long_maxThread = -1 ;
            }
            supVo.long_minThread = conf.getSetAttrPlusInt(doc, "config.support", "long_minThread", null, 0, 5, null) ;//池中最小线程数
            supVo.long_minThread = conf.getSetAttrPlusInt(doc, "config.support", "long_minThread", null, -1, 100, null) ;//池中最小线程数
            if(supVo.long_minThread < 0){
                supVo.long_minThread = -1 ;
            }
            supVo.long_freeTimeout = conf.getSetAttrPlusInt(doc, "config.support", "long_freeTimeout", null, 1, 90, null) * 1000 ;//线程数空闲时长,若池中线程数量大于minThread,且有的线程空闲时长超过freeTimeout,则清除该线程
            supVo.long_busyTimeout = conf.getSetAttrInt(doc, "config.support", "long_busyTimeout", null, -1, 10, null) ;//线程不间断工作时长(单位为秒)超时限,若为-1,不受限制
            if(supVo.long_busyTimeout < 0){
                supVo.long_busyTimeout = -1 ;
            }
            supVo.enableThreadPool = conf.getSetAttrBoolean(doc, "config.support", "enableThreadPool", null, null) ;
//            supVo.enableSpringHibernate = conf.getSetAttrBoolean(doc, "config.support", "enableSpringHibernate", null, null) ;
//            if(supVo.enableSpringHibernate){
//                supVo.springXmlFile = conf.getSetAttrTxt(doc, "config.support", "springXmlFile", null, false, null) ;
//            }
            if(supVo.long_maxThread == 0 || supVo.long_minThread == 0){
                supVo.enableLongThreadPool = false ;
            }else{
                supVo.enableLongThreadPool = true ;
            }
            supVo.showStartInfo = showStartInfo ;
            
            AdapterImp_SupportUnit supAdap = new AdapterImp_SupportUnit() ;
            supAdap.setConfig(supVo);
            SupportUnit supUnit = SupportUnit.getInstance() ;
            supUnit.setAdapter(supAdap);
            supUnit.start(new UnitStartedCallbackInterface(){
                @Override
                public void call(Object obj) {
                }
            supUnit.start(obj -> {
            });
            units.add(supUnit) ;
            
@@ -236,10 +247,7 @@
            //当前支持spring + hibernate
            resUnit.setSpringContext(SpringContextUtil.getApplicationContext());
            resUnit.start(new UnitStartedCallbackInterface(){
                @Override
                public void call(Object obj) {
                }
            resUnit.start(obj -> {
            });
            units.add(resUnit) ;
@@ -256,32 +264,41 @@
                rmiAdap.setConfig(rmiVo);
                RmiUnit rmiUnit = RmiUnit.getInstance();
                rmiUnit.setAdapter(rmiAdap);
                rmiUnit.start(new UnitStartedCallbackInterface(){
                    @Override
                    public void call(Object obj) {
                    }
                rmiUnit.start(obj -> {
                });
                RmiSvUrl = "[ip]:" + rmiVo.port + "/" + rmiVo.context ;
                units.add(rmiUnit) ;
            }
            /////////////////
            //RTU上行数据处理模块
            RtuDataUnitConfigVo rducVo = new RtuDataUnitConfigVo();
            AdapterImp_RtuDataUnit rducAdap = new AdapterImp_RtuDataUnit();
            rducAdap.setConfig(rducVo);
            RtuDataUnit rducUnit = RtuDataUnit.getInstance();
            rducUnit.setAdapter(rducAdap);
            rducUnit.start(obj -> {
            });
            units.add(rducUnit) ;
            // ///////////////
            // æ ¸å¿ƒ
            CoreUnitConfigVo coreConfVo = new CoreUnitConfigVo();
            coreConfVo.sleepBigBusy = conf.getSetAttrPlusInt(doc, "config.core", "sleepBigBusy", null, 1, 200, null).longValue() ;
            coreConfVo.sleepSmallBusy = conf.getSetAttrPlusInt(doc, "config.core", "sleepSmallBusy", null, 2, 1000, null).longValue();
            coreConfVo.queueWarnSize = conf.getSetAttrPlusInt(doc, "config.core", "queueWarnSize", null, 500, 1000000, null) ;
            coreConfVo.queueMaxSize = conf.getSetAttrPlusInt(doc, "config.core", "queueMaxSize", null, 5000, 3000000, null)  ;
            coreConfVo.queueWarnSize = ServerProperties.cacheUpDownDataWarnCount ;
            coreConfVo.queueMaxSize = ServerProperties.cacheUpDownDataMaxCount ;
            coreConfVo.showStartInfo = showStartInfo ;
            AdapterImp_CoreUnit coreAdap = new AdapterImp_CoreUnit();
            coreAdap.setConfig(coreConfVo);
            CoreUnit coreUnit = CoreUnit.getInstance();
            coreUnit.setAdapter(coreAdap);
            CoreUnit.addConstantTask(new ToRtuConstantTask());
            coreUnit.start(new UnitStartedCallbackInterface(){
                @Override
                public void call(Object obj) {
                }
            CoreUnit.addConstantTask(new FromRtuConstantTask());
            coreUnit.start(obj -> {
            });
            units.add(coreUnit) ;
@@ -299,10 +316,7 @@
                tcpAdap.setConfig(tcpVo);
                TcpUnit tcpUnit = TcpUnit.getInstance();
                tcpUnit.setAdapter(tcpAdap);
                tcpUnit.start(new UnitStartedCallbackInterface(){
                    @Override
                    public void call(Object obj) {
                    }
                tcpUnit.start(obj -> {
                });
                TcpSvUrl = "[ip]:" + tcpVo.port ;
                units.add(tcpUnit) ;
pipIrr-platform/pipIrr-mw/pipIrr-mw-accept/src/main/java/com/dy/aceMw/server/AdapterImp_RtuDataUnit.java
New file
@@ -0,0 +1,19 @@
package com.dy.aceMw.server;
import com.dy.aceMw.server.rtuData.RtuDataUnitAdapter;
import com.dy.aceMw.server.rtuData.RtuDataUnitConfigVo;
public class AdapterImp_RtuDataUnit implements RtuDataUnitAdapter {
    private RtuDataUnitConfigVo configVo ;
    public RtuDataUnitConfigVo getConfig() {
        return configVo;
    }
    public void setConfig(RtuDataUnitConfigVo configVo){
        this.configVo = configVo ;
    }
}
pipIrr-platform/pipIrr-mw/pipIrr-mw-accept/src/main/java/com/dy/aceMw/server/forTcp/MidResultActionFromRtu.java
@@ -1,5 +1,7 @@
package com.dy.aceMw.server.forTcp;
import com.dy.aceMw.server.rtuData.RtuDataNode;
import com.dy.aceMw.server.rtuData.RtuDataCache;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
@@ -23,33 +25,33 @@
                //此处实现,与以前不一样,
                //以前实现:匹配命令是从后向前匹配,
                //当前实现,匹配命令是从前向后匹配,原因:举例,当批量下发补召命令,如果从后匹配,则前面命令会下发多次,即一个上报次数据会补召多次
                MidResultToRtu resToRtu = TcpDownCommandCach.matchFromHead(resFromRtu) ;
                MidResultToRtu resToRtu = TcpDownCommandCache.matchFromHead(resFromRtu) ;
                if(resToRtu != null){
                    //匹配到下发的命令
                    resFromRtu.setCommandId(resToRtu.commandId) ;
                    this.sendResult(false, resFromRtu);
                    this.nextDeal(false, resFromRtu);
                }else{
                    this.sendResult(false, resFromRtu);
                    this.nextDeal(false, resFromRtu);
                    //未匹配到下发的命令,命令在缓存因超时被清除了
                    RtuStatusDealer.commandFail2Success(resFromRtu.rtuAddr) ;
                }
            }else{
                //主动上报数据
                this.sendResult(true, resFromRtu);
                this.nextDeal(true, resFromRtu);
            }
        }
    }
    private void sendResult(boolean reportOrResponse_trueOrFalse, MidResultFromRtu resFromRtu){
    /**
     * è¿›å…¥å¤šçº¿ç¨‹çŽ¯å¢ƒä¸­è¿è¡Œ
     * @param reportOrResponse_trueOrFalse
     * @param resFromRtu
     */
    private void nextDeal(boolean reportOrResponse_trueOrFalse, MidResultFromRtu resFromRtu){
        try{
            String json = resFromRtu.data.toJson() ;
//            if(reportOrResponse_trueOrFalse){
//                ToMqMessageCach.cachObj(MessageType.RtuAutoReport, json);
//            }else{
//                ToMqMessageCach.cachObj(MessageType.RtuCmdResponse, json);
//            }
            RtuDataCache.cacheRtuUpData(reportOrResponse_trueOrFalse, new RtuDataNode(resFromRtu.data));
        }catch(Exception e){
            log.error(e.getMessage(), e);
        }
    }
}
pipIrr-platform/pipIrr-mw/pipIrr-mw-accept/src/main/java/com/dy/aceMw/server/rtuData/RtuDataCache.java
New file
@@ -0,0 +1,70 @@
package com.dy.aceMw.server.rtuData;
import com.dy.aceMw.server.ServerProperties;
import com.dy.common.queue.Node;
import com.dy.common.queue.Queue;
public class RtuDataCache {
    //TCP下行命令缓存队列
    private static Queue cacheQueue = new Queue("tcpUpDataQueue") ;
    private static RtuDataCache instance = new RtuDataCache() ;
    private RtuDataCache(){
        cacheQueue.setLimit(ServerProperties.cacheUpDownDataWarnCount, ServerProperties.cacheUpDownDataMaxCount);
    }
    public static RtuDataCache getInstance(){
        return instance ;
    }
    /**
     * ç¼“存节点
     * @param reportOrResponse_trueOrFalse reportOrResponse_trueOrFalse
     * @param node node
     * @throws Exception å¼‚常
     */
    public static void cacheRtuUpData(boolean reportOrResponse_trueOrFalse, RtuDataNode node) throws Exception{
        if(node != null && node.obj != null){
            if(reportOrResponse_trueOrFalse){
                cacheQueue.pushHead(node);
            }else{
                cacheQueue.pushTail(node);
            }
        }
    }
    /**
     * å¾—到第一个节点
     * @return Node
     */
    public static Node getFirstQueueNode(){
        return cacheQueue.getFirstNode() ;
    }
    /**
     * å¾—到最后一个节点
     * @return Node
     */
    public static Node getLastQueueNode(){
        return cacheQueue.getLastNode() ;
    }
    /**
     * ç§»é™¤èŠ‚ç‚¹
     * @param node
     */
    public static void removeNode(Node node){
        cacheQueue.remove(node);
    }
    /**
     * ç¼“存的节点数
     * @Return ç¼“存节点数
     */
    public static Integer size(){
        return cacheQueue.size() ;
    }
}
pipIrr-platform/pipIrr-mw/pipIrr-mw-accept/src/main/java/com/dy/aceMw/server/rtuData/RtuDataNode.java
New file
@@ -0,0 +1,60 @@
package com.dy.aceMw.server.rtuData;
import com.dy.common.queue.NodeObj;
import com.dy.common.threadPool.ThreadPool;
import com.dy.common.threadPool.TreadPoolFactory;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
public class RtuDataNode implements NodeObj {
    private static final Logger log = LogManager.getLogger(RtuDataNode.class.getName());
    public Object obj ;//数据
    public RtuDataNode(Object obj){
        this.obj = obj ;
    }
    /**
     * è‡ªå·±å¤„理自己
     * @return
     */
    public boolean dealSelf(){
        try {
            ThreadPool.Pool pool = TreadPoolFactory.getThreadPoolLong() ;
            pool.putJob(new ThreadPool.Job() {
                public void execute() {
                    if(obj != null){
                        TaskSurpport t = null ;
                        try{
                            t = TaskPool.popTask() ;
                            if(t != null){
                                t.execute(obj);
                            }else{
                                log.error("未得到RTU主动上报数据处理任务!");
                            }
                        }catch(Exception e){
                            if(t != null){
                                //当有异常时,try catch中的代码可没有执行freeAndCleanTask
                                TaskPool.freeAndCleanTask(t);
                            }
                        }
                    }
                }
                @Override
                public void destroy(){
                }
                @Override
                public boolean isDestroy(){
                    return false ;
                }
            });
        } catch (Exception e) {
            log.error("在RtuDataNode内发生异常", e);
        }
        return true ;
    }
}
pipIrr-platform/pipIrr-mw/pipIrr-mw-accept/src/main/java/com/dy/aceMw/server/rtuData/RtuDataUnit.java
New file
@@ -0,0 +1,47 @@
package com.dy.aceMw.server.rtuData;
import com.dy.common.mw.UnitAdapterInterface;
import com.dy.common.mw.UnitInterface;
import com.dy.common.mw.UnitStartedCallbackInterface;
public class RtuDataUnit  implements UnitInterface {
    private static RtuDataUnit instance = new RtuDataUnit() ;
    public static RtuDataUnitAdapter adapter ;
    public static RtuDataUnitConfigVo confVo ;
    private RtuDataUnit(){} ;
    public static RtuDataUnit getInstance(){
        return instance ;
    }
    @Override
    public void setAdapter(UnitAdapterInterface adapter) throws Exception {
        if(adapter == null){
            throw new Exception("RTU数据处理模块适配器对象不能为空!") ;
        }
        RtuDataUnit.adapter = (RtuDataUnitAdapter)adapter ;
        RtuDataUnit.confVo = RtuDataUnit.adapter.getConfig() ;
        if(RtuDataUnit.confVo == null){
            throw new Exception("RTU数据处理模块配置对象不能为空!") ;
        }
    }
    /**
     * åˆå§‹åŒ–上行数据处理任务池
     */
    @Override
    public void start(UnitStartedCallbackInterface callback) throws Exception {
        TaskPool.setTaskTreeCofig(new TreeParse().parseConfig());
        callback.call(null) ;
        System.out.println("RTU数据处理模块成功启动");
    }
    @Override
    public void stop(UnitStartedCallbackInterface callback) throws Exception {
    }
}
pipIrr-platform/pipIrr-mw/pipIrr-mw-accept/src/main/java/com/dy/aceMw/server/rtuData/RtuDataUnitAdapter.java
New file
@@ -0,0 +1,10 @@
package com.dy.aceMw.server.rtuData;
import com.dy.common.mw.UnitAdapterInterface;
public interface RtuDataUnitAdapter extends UnitAdapterInterface {
    public RtuDataUnitConfigVo getConfig() ;
}
pipIrr-platform/pipIrr-mw/pipIrr-mw-accept/src/main/java/com/dy/aceMw/server/rtuData/RtuDataUnitConfigVo.java
New file
@@ -0,0 +1,5 @@
package com.dy.aceMw.server.rtuData;
public class RtuDataUnitConfigVo {
}
pipIrr-platform/pipIrr-mw/pipIrr-mw-accept/src/main/java/com/dy/aceMw/server/rtuData/Task.java
New file
@@ -0,0 +1,46 @@
package com.dy.aceMw.server.rtuData;
public interface Task {
    /**
     * ä»»åŠ¡é‡‡ç”¨å¯¹è±¡æ± ï¼Œä»¥ä¾¿é‡ç”¨ä»»åŠ¡å¯¹è±¡ï¼Œ
     * é‡ç”¨å‰è¦è¿›è¡Œå¯¹è±¡åˆå§‹åŒ–,清除上次执行任务时遗留的对象属性数据
     * åˆå§‹åŒ–本任务及所有子任务
     */
    public void cleanMeAndSubs() ;
    /**
     * æ‰§è¡ŒèŠ‚ç‚¹ä»»åŠ¡
     * @param data éœ€è¦å¤„理的数据
     */
    public void execute(Object data) ;
    /**
     * å¾—到本任务节点处理产生的中间结果,以供本节点所在树枝的下级任务节点及本树枝的左侧(根在上)所有树枝的节点应用本结果
     * @return
     */
    public Object[] getMyResults() ;
    /**
     * å¾—到指定任务节点处理产生的中间结果,以供本节点所在树枝的下级任务节点及本树枝的左侧(根在上)所有树枝的节点应用本结果
     * @param id æŒ‡å®šä»»åŠ¡ID
     * @return
     */
    public Object[] getTaskResults(String id);
    /**
     * è½¬ä¸‹çº§ä»»åŠ¡èŠ‚ç‚¹å¤„ç†ï¼Œé¦–å…ˆè¦å®žä½“åŒ–æ‰€æœ‰å­èŠ‚ç‚¹ã€‚
     * @param data éœ€è¦å¤„理的数据
     */
    public void toNextTasks(Object data) ;
    /**
     * è½¬ä¸‹çº§æŸä¸ªä»»åŠ¡èŠ‚ç‚¹å¤„ç†
     * @param data éœ€è¦å¤„理的数据
     * @param id æŒ‡å®šä»»åŠ¡ID
     */
    public void toNextOneTask(Object data, String id);
}
pipIrr-platform/pipIrr-mw/pipIrr-mw-accept/src/main/java/com/dy/aceMw/server/rtuData/TaskConfig.java
New file
@@ -0,0 +1,9 @@
package com.dy.aceMw.server.rtuData;
public class TaskConfig {
    public String id ;
    public String name ;
    public Boolean enable ;//是否执行节点的数据处理任务任务
    public String clazz ;
}
pipIrr-platform/pipIrr-mw/pipIrr-mw-accept/src/main/java/com/dy/aceMw/server/rtuData/TaskPool.java
New file
@@ -0,0 +1,116 @@
package com.dy.aceMw.server.rtuData;
import java.util.ArrayList;
import java.util.List;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
public class TaskPool {
    private static Logger log = LogManager.getLogger(TaskPool.class.getName()) ;
    private static List<TaskSurpport> tasks = new ArrayList<TaskSurpport>() ;
    private static TreeConfig taskTreeConf ;
    public static void setTaskTreeCofig(TreeConfig conf){
        taskTreeConf = conf ;
    }
    /**
     * å¾—到任务
     * å¤šçº¿ç¨‹çŽ¯å¢ƒä¸‹è¿è¡Œ
     * @return
     */
    public static synchronized TaskSurpport popTask(){
        TaskSurpport t = (tasks.size() > 0)?tasks.get(0):null ;
        if(t != null){
            tasks.remove(0) ;
        }else{
            try {
                t = newTaskTree() ;
            } catch (Exception e) {
                log.error(e.getMessage() == null?"实例化上行数据处理任务对象树失败!" : e.getMessage(), e);
            } finally {
                if(t == null){
                    log.error("实例化上行数据处理任务对象失败!" );
                }
            }
        }
        return t ;
    }
    /**
     * æ”¾å›žä»»åŠ¡
     * å¤šçº¿ç¨‹çŽ¯å¢ƒä¸‹è¿è¡Œ
     * è¿™é‡Œéœ€è¦åŒæ­¥é”ï¼Œå› ä¸ºä¸Šé¢æ–¹æ³•中执行完tasks.get(0)且未执行tasks.remove(0)期间,本方法执行并且执行完,那么后期就会出乱子
     * @param t
     */
    public static synchronized void freeAndCleanTask(TaskSurpport t){
        if(t != null){
            boolean find = false ;
            for(TaskSurpport tin : tasks){
                if(tin == t){
                    find = true ;
                    break ;
                }
            }
            if(!find){
                t.cleanMeAndSubs();
                tasks.add(0, t) ;
            }
        }
    }
    /**
     * å®žä¾‹åŒ–任务对象树
     * @return
     * @throws Exception
     */
    private static TaskSurpport newTaskTree() throws Exception{
        TaskSurpport t = null ;
        if(taskTreeConf != null){
            t = newTask(null, taskTreeConf.taskConf, taskTreeConf.subTreeConfs) ;
        }
        return t ;
    }
    private static TaskSurpport newTask(TaskSurpport root, TaskConfig taskConf, TreeConfig[] subTreeConfs) throws Exception{
        TaskSurpport t = null ;
        if(taskConf != null){
            t = instanceTask(taskConf.clazz) ;
            if(t != null){
                t.conf = taskConf ;
                t.root = root ;
                if(root == null){
                    root = t ;
                }
                newSubTask(root, t, subTreeConfs);
            }
        }
        return t ;
    }
    private static void newSubTask(TaskSurpport root, TaskSurpport parent, TreeConfig[] treeConfs)throws Exception{
        if(parent != null && treeConfs != null && treeConfs.length > 0){
            parent.subTasks = new TaskSurpport[treeConfs.length] ;
            for(int i = 0 ; i < treeConfs.length; i++){
                parent.subTasks[i] = newTask(root, treeConfs[i].taskConf, treeConfs[i].subTreeConfs) ;
            }
        }
    }
    private static TaskSurpport instanceTask(String clazz)throws Exception{
        Class<?> c = Class.forName(clazz);
        if (c == null) {
            throw new Exception("实例化上行数据处理任务对象树失败!任务类为" + clazz + "!");
        }else{
            return (TaskSurpport)c.getDeclaredConstructor().newInstance();
            //return (TaskSurpport)c.newInstance();
        }
    }
}
pipIrr-platform/pipIrr-mw/pipIrr-mw-accept/src/main/java/com/dy/aceMw/server/rtuData/TaskSurpport.java
New file
@@ -0,0 +1,132 @@
package com.dy.aceMw.server.rtuData;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
/**
 * éƒ¨åˆ†å®žçްTask
 */
public abstract class TaskSurpport implements Task {
    private static final Logger log = LogManager.getLogger(TaskSurpport.class.getName()) ;
    //当前所处理的上行数据所属RTU的地址
    public String rtuAddr_inRootTk ;//只在根root任务对象上会付此值
    //本节点配置
    protected TaskConfig conf ;
    //根任务
    protected TaskSurpport root ;
    //本任务的子任务
    protected TaskSurpport[] subTasks ;
    //本任务的处理结果
    protected Object[] taskResult ;
    /**
     * æ‰§è¡ŒèŠ‚ç‚¹ä»»åŠ¡
     * @param data éœ€è¦å¤„理的数据
     */
    @Override
    public abstract void execute(Object data) ;
    /**
     * ä»»åŠ¡é‡‡ç”¨å¯¹è±¡æ± ï¼Œä»¥ä¾¿é‡ç”¨ä»»åŠ¡å¯¹è±¡ï¼Œ
     * é‡ç”¨å‰è¦è¿›è¡Œå¯¹è±¡åˆå§‹åŒ–,清除上次执行任务时遗留的对象属性数据
     * åˆå§‹åŒ–本任务及所有子任务
     */
    @Override
    public void cleanMeAndSubs() {
        rtuAddr_inRootTk = null ;
        taskResult = null ;
        if(this.subTasks != null && this.subTasks.length > 0){
            for(int i = 0 ; i < this.subTasks.length; i++){
                this.subTasks[i].cleanMeAndSubs() ;
            }
        }
    }
    /**
     * å¾—到本任务节点处理产生的中间结果,以供本节点所在树枝的下级任务节点及本树枝的左侧(根在上)所有树枝的节点应用本结果
     * @return
     */
    @Override
    public Object[] getMyResults(){
        return taskResult ;
    }
    /**
     * å¾—到指定任务节点处理产生的中间结果,以供本节点所在树枝的下级任务节点及本树枝的左侧(根在上)所有树枝的节点应用本结果
     * @param id æŒ‡å®šä»»åŠ¡ID
     * @return
     */
    public Object[] getTaskResults(String id){
        if(root != null){
            return this.getTaskResults(root, id) ;
        }
        return null ;
    }
    private Object[] getTaskResults(TaskSurpport task, String id){
        if(task != null && task.conf != null && task.conf.id != null && task.conf.id.equals(id)){
            return task.getMyResults() ;
        }else{
            if(task.subTasks != null && task.subTasks.length > 0){
                Object[] rs = null ;
                for(int i = 0 ; i < task.subTasks.length; i++){
                    rs = getTaskResults(task.subTasks[i], id) ;
                    if(rs != null){
                        return rs ;
                    }
                }
            }
        }
        return null ;
    }
    /**
     * è½¬ä¸‹çº§ä»»åŠ¡èŠ‚ç‚¹å¤„ç†ï¼Œé¦–å…ˆè¦å®žä½“åŒ–æ‰€æœ‰å­èŠ‚ç‚¹ã€‚
     * @param data éœ€è¦å¤„理的数据
     */
    @Override
    public void toNextTasks(Object data) {
        try {
            if(subTasks != null && subTasks.length > 0){
                for(int i = 0 ; i < subTasks.length ; i++){
                    if(subTasks[i].conf.enable){
                        subTasks[i].execute(data) ;
                    }else{
                        //本节点不起作用,直接进入本节的子节点
                        subTasks[i].toNextTasks(data) ;
                    }
                }
            }
        } catch (Exception e) {
            log.error("向下级任务传递工作时出错," , e);
        }finally{
        }
    }
    /**
     * è½¬ä¸‹çº§æŸä¸ªä»»åŠ¡èŠ‚ç‚¹å¤„ç†
     * @param data éœ€è¦å¤„理的数据
     * @param id æŒ‡å®šä»»åŠ¡ID
     */
    public void toNextOneTask(Object data, String id){
        try {
            if(subTasks != null && subTasks.length > 0){
                for(int i = 0 ; i < subTasks.length ; i++){
                    if(subTasks[i].conf.id.equals(id)){
                        if(subTasks[i].conf.enable){
                            subTasks[i].execute(data) ;
                        }else{
                            //本节点不起作用,直接进入本节的子节点
                            subTasks[i].toNextTasks(data) ;
                        }
                    }
                }
            }
        } catch (Exception e) {
            log.error("向指定子任务(" + id + ")传递任务时出错," , e);
        }finally{
        }
    }
}
pipIrr-platform/pipIrr-mw/pipIrr-mw-accept/src/main/java/com/dy/aceMw/server/rtuData/TkReceive.java
New file
@@ -0,0 +1,31 @@
package com.dy.aceMw.server.rtuData;
import com.dy.common.mw.protocol.Data;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
public class TkReceive extends TaskSurpport {
    private static final Logger log = LogManager.getLogger(TkReceive.class.getName()) ;
    //ç±»ID,一定与Tree.xml配置文件中配置一致
    public static final String taskId = "TkReceive" ;
    /**
     * æ‰§è¡ŒèŠ‚ç‚¹ä»»åŠ¡
     * @param data éœ€è¦å¤„理的数据
     */
    @Override
    public void execute(Object data) {
        if(data == null){
            log.error("严重错误,RTU上行数据为空!" );
        }else{
            if(data instanceof Data){
                this.toNextTasks(data);
            }else{
                log.error("严重错误,该数据类型(" + data.getClass().getName() + "),接收数据任务还未实现!" );
            }
        }
    }
}
pipIrr-platform/pipIrr-mw/pipIrr-mw-accept/src/main/java/com/dy/aceMw/server/rtuData/TkRtuData.java
New file
@@ -0,0 +1,29 @@
package com.dy.aceMw.server.rtuData;
import com.dy.common.mw.protocol.Data;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
public class TkRtuData extends TaskSurpport {
    private static Logger log = LogManager.getLogger(TkRtuData.class.getName()) ;
    //ç±»ID,一定与Tree.xml配置文件中配置一致
    public static final String taskId = "TkRtuData" ;
    /**
     * æ‰§è¡ŒèŠ‚ç‚¹ä»»åŠ¡
     * @param data éœ€è¦å¤„理的数据
     */
    @Override
    public void execute(Object data) {
        Data d = (Data)data ;
        String rtuAddr = d.getRtuAddr() ;
        if(rtuAddr == null){
            log.error("严重错误,RTU上行数据中无RTU地址!" );
        }else{
            this.toNextTasks(data);
        }
    }
}
pipIrr-platform/pipIrr-mw/pipIrr-mw-accept/src/main/java/com/dy/aceMw/server/rtuData/TreeConfig.java
New file
@@ -0,0 +1,6 @@
package com.dy.aceMw.server.rtuData;
public class TreeConfig {
    public TaskConfig taskConf ;
    public TreeConfig[] subTreeConfs ;//所有子节点
}
pipIrr-platform/pipIrr-mw/pipIrr-mw-accept/src/main/java/com/dy/aceMw/server/rtuData/TreeParse.java
New file
@@ -0,0 +1,173 @@
package com.dy.aceMw.server.rtuData;
import java.net.URL;
import java.util.*;
import org.jdom2.Document;
import org.jdom2.Element;
import org.jdom2.input.SAXBuilder;
public class TreeParse {
    public List<String> ids ;
    public List<String> classes ;
//    public static void main(String args[]) {
//        TreeParse o = new TreeParse();
//        TreeConfig conf = o.parseConfig();
//    }
    public TreeParse(){
        ids = new ArrayList<String>() ;
        classes = new ArrayList<String>() ;
    }
    /**
     * è§£æžå¤„理器配置
     * @return
     */
    protected TreeConfig parseConfig() {
        try {
            ClassLoader classLoader = ClassLoader.getSystemClassLoader();
            URL configFileURL = classLoader.getResource("RtuDataDealTree.xml");
            return this.parse(this.createDom(configFileURL)) ;
        } catch (Exception e) {
            System.out.println("系统启动时,初始上行数据处理任务配置出错 !");
            System.out.println(e.getMessage());
            e.printStackTrace();
            return null;
        }
    }
    /**
     *
     * @return
     */
    private Document createDom(URL configFileURL) throws Exception {
        if (configFileURL == null) {
            throw new Exception("未得到上行数据处理任务配置文件!", null);
        }
        Document doc = null;
        try {
            SAXBuilder sb = new SAXBuilder();
            doc = sb.build(configFileURL);
            if (doc == null) {
                throw new Exception("未生成上行数据处理任务配置文件的DOM对象!", null);
            }
        } catch (Exception e) {
            throw new Exception("生成上行数据处理任务配置文件的DOM对象失败!", e);
        }
        return doc;
    }
    /**
     * åˆ†æž
     * @return ArrayList<String>
     * @throws Exception
     */
    private TreeConfig parse(Document doc) throws Exception {
        Element root = doc.getRootElement();
        if (root == null) {
            throw new Exception("未得到上行数据处理任务配置文件根元素project!");
        }
        List<Element> rootTasks = root.getChildren("task") ;
        if(rootTasks == null || rootTasks.size() == 0){
            throw new Exception("未得到上行数据处理任务配置文件根任务task!");
        }
        if(rootTasks.size() > 1){
            throw new Exception("未得到上行数据处理任务配置文件根任务task必须只有一个!");
        }
        TreeConfig tree = new TreeConfig() ;
        tree.taskConf = new TaskConfig() ;
        this.parseNode(rootTasks.get(0), tree, tree.taskConf) ;
        return tree ;
    }
    private void parseNode(Element taskEle, TreeConfig me, TaskConfig taskConf)throws Exception {
//        <task id="task2.1" name="构造数据" enable="true" class="" />
        if(taskEle == null){
            throw new Exception("分析上行数据处理任务配置文件出错!");
        }
        String id = taskEle.getAttributeValue("id") ;
        if(id == null || id.trim().equals("")){
            throw new Exception("上行数据处理任务配置文件中id必须配置!");
        }
        id = id.trim() ;
        if(ids.contains(id)){
            throw new Exception("上行数据处理任务配置文件中id=" + id + "重复配置!");
        }
        taskConf.id = id ;
        ids.add(id) ;
        String name = taskEle.getAttributeValue("name") ;
        if(name == null || name.trim().equals("")){
            throw new Exception("上行数据处理任务配置文件中name必须配置!");
        }
        name = name.trim() ;
        taskConf.name = name ;
        String enable = taskEle.getAttributeValue("enable") ;
        if(enable == null || !(enable.trim().equals("true") || enable.trim().equals("false"))){
            throw new Exception("上行数据处理任务配置文件中enable必须配置,并且值只能为true或false!");
        }
        if(enable.trim().equals("true")){
            taskConf.enable = true ;
        }
        if(enable.trim().equals("false")){
            taskConf.enable = false ;
        }
        String clazz = taskEle.getAttributeValue("class") ;
        if(clazz == null || clazz.trim().equals("")){
            throw new Exception("上行数据处理任务配置文件中class必须配置!");
        }
        clazz = clazz.trim() ;
        if(classes.contains(clazz)){
            throw new Exception("上行数据处理任务配置文件中class=" + clazz + "重复配置!");
        }
        taskConf.clazz = clazz ;
        classes.add(clazz) ;
        this.checkClass(taskConf.clazz) ;
        this.parseSubNode(taskEle, me) ;
    }
    private void parseSubNode(Element ele, TreeConfig parent)throws Exception {
        List<?> list = ele.getChildren("task") ;
        if(list != null && list.size() > 0){
            parent.subTreeConfs = new TreeConfig[list.size()] ;
            Iterator<?> it = list.iterator();
            Element e = null;
            int count = 0 ;
            TreeConfig me ;
            while(it.hasNext()){
                e = (Element) it.next();
                me = new TreeConfig() ;
                me.taskConf = new TaskConfig() ;
                parent.subTreeConfs[count++] = me ;
                parseNode(e, me, me.taskConf) ;
            }
        }
    }
    private void checkClass(String clazz)throws Exception {
        Class<?> c = Class.forName(clazz);
        if (c == null) {
            throw new Exception("上行数据处理任务配置文件中不能实例化class=" + clazz + "!");
        }else{
            Object o = c.newInstance();
            if(o instanceof Task){
            }else{
                throw new Exception("上行数据处理任务配置文件中class=" + clazz + "必须实现Task接口!");
            }
        }
    }
}
pipIrr-platform/pipIrr-mw/pipIrr-mw-accept/src/main/java/com/dy/aceMw/server/rtuData/dbSv/RtuSv.java
New file
@@ -0,0 +1,7 @@
package com.dy.aceMw.server.rtuData.dbSv;
import org.springframework.stereotype.Service;
@Service
public class RtuSv {
}
pipIrr-platform/pipIrr-mw/pipIrr-mw-accept/src/main/java/com/dy/aceMw/server/rtuData/dbSv/˵Ã÷.txt
New file
@@ -0,0 +1 @@
springboot容器中的Server bean
pipIrr-platform/pipIrr-mw/pipIrr-mw-accept/src/main/java/com/dy/aceMw/server/rtuData/p206V1_0_0/TkFindP206V1_0_0.java
New file
@@ -0,0 +1,27 @@
package com.dy.aceMw.server.rtuData.p206V1_0_0;
import com.dy.aceMw.server.rtuData.TaskSurpport;
import com.dy.common.mw.protocol.Data;
import com.dy.common.mw.protocol.p206V1_0_0.ProtocolConstantV206V1_0_0;
public class TkFindP206V1_0_0 extends TaskSurpport {
    //ç±»ID,一定与Tree.xml配置文件中配置一致
    public static final String taskId = "TkFindP206V1_0_0" ;
    /**
     * æ‰§è¡ŒèŠ‚ç‚¹ä»»åŠ¡
     * @param data éœ€è¦å¤„理的数据
     */
    @Override
    public void execute(Object data) {
        Data d = (Data)data ;
        if(d.getProtocol() != null && d.getProtocol().equals(ProtocolConstantV206V1_0_0.protocolName)){
            this.toNextTasks(data);
        }else{
            //不是本协议的数据
        }
    }
}
pipIrr-platform/pipIrr-mw/pipIrr-mw-accept/src/main/java/com/dy/aceMw/server/rtuData/p206V1_0_0/TkPreGenObjs.java
File was renamed from pipIrr-platform/pipIrr-mw/pipIrr-mw-accept/src/main/java/com/dy/aceMw/server/busi/deal/p206V1_0_0/TkPreGenObjs.java
@@ -1,6 +1,6 @@
package com.dy.aceMw.server.busi.deal.p206V1_0_0;
package com.dy.aceMw.server.rtuData.p206V1_0_0;
import com.dy.aceMw.server.busi.deal.TaskSurpport;
import com.dy.aceMw.server.rtuData.TaskSurpport;
import com.dy.common.mw.protocol.Data;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
@@ -20,6 +20,7 @@
    public void execute(Object data) {
        Data d = (Data)data ;
        String rtuAddr = d.getRtuAddr() ;
        log.info("RTU" + rtuAddr + "数据到此,还未实现处理:" + data.toString());
        //得到本地RTU æ•°æ®ï¼Œä»¥å¤‡åŽé¢èŠ‚ç‚¹åº”ç”¨
        /*
        BuziInterface baseBusi = BuziGeter.getBaseBusi() ;
pipIrr-platform/pipIrr-mw/pipIrr-mw-accept/src/main/java/com/dy/aceMw/server/tasks/FromRtuConstantTask.java
New file
@@ -0,0 +1,74 @@
package com.dy.aceMw.server.tasks;
import com.dy.aceMw.server.rtuData.RtuDataNode;
import com.dy.aceMw.server.rtuData.RtuDataCache;
import com.dy.common.mw.core.CoreTask;
import com.dy.common.queue.Node;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
/**
 * å¯¹RTU上行数据进行业务处理
 */
public class FromRtuConstantTask extends CoreTask {
    private static final Logger log = LogManager.getLogger(FromRtuConstantTask.class.getName());
    /**
     * åœ¨å•线程环境中运行
     */
    @Override
    public Integer excute() {
        try{
            return dealRtuUpData() ;
        }catch(Exception e){
            log.error(e);
        }
        return null ;
    }
    /**
     * å¤„理上行数据
     */
    public Integer dealRtuUpData() {
        Node first = RtuDataCache.getFirstQueueNode() ;
        if(first != null){
            Integer count = RtuDataCache.size() ;
            Node last = RtuDataCache.getLastQueueNode() ;
            this.doDealRtuUpData(first, last);
            return count ;
        }
        return null ;
    }
    /**
     * å¤„理缓存的上行数据节点
     * @param first ç¬¬ä¸€ä¸ªèŠ‚ç‚¹
     * @param last æœ€åŽä¸€ä¸ªèŠ‚ç‚¹
     */
    private void doDealRtuUpData(Node first, Node last){
        if(last != null){
            //在dealNode方法中,可能要把last从队列中移除,这时last.pre为空,所以提前把last.pre取出来
            Node pre = last.pre ;
            dealNode(last) ;
            if(first != null && first != last){
                doDealRtuUpData(first, pre) ;
            }else if(first != null && first == last){
                //停止
            }else if(first == null){
                //这种情况不会存在
                doDealRtuUpData(null, pre) ;
            }
        }
    }
    /**
     * å¤„理一个节点
     * @param node èŠ‚ç‚¹
     */
    private void dealNode(Node node){
        RtuDataNode obj = (RtuDataNode)node.obj ;
        obj.dealSelf() ;
        RtuDataCache.removeNode(node);
    }
}
pipIrr-platform/pipIrr-mw/pipIrr-mw-accept/src/main/resources/RtuDataDealTree.xml
New file
@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE project>
<project>
    <!--
    id:与对应类中的静态成员变量taskId一致
    enable:标识本节点是否执行,若本节点不执行,则直接进入其子节点
    -->
    <task id="TkReceive" name="接收数据" enable="true" class="com.dy.aceMw.server.rtuData.TkReceive">
        <task id="TkRtuData" name="接收RTU数据" enable="true" class="com.dy.aceMw.server.rtuData.TkRtuData">
            <task id="TkFindP206V1_0_0" name="识别P206V1_0_0数据" enable="true" class="com.dy.aceMw.server.rtuData.p206V1_0_0.TkFindP206V1_0_0">
                <task id="TkPreGenObjs" name="预先准备各对象" enable="true" class="com.dy.aceMw.server.rtuData.p206V1_0_0.TkPreGenObjs">
                </task>
            </task>
        </task>
    </task>
</project>
pipIrr-platform/pipIrr-mw/pipIrr-mw-accept/src/main/resources/Tree_.xml
New file
@@ -0,0 +1,95 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE project>
<project>
<!--
id:与对应类中的静态成员变量taskId一致
enable:标识本节点是否执行,若本节点不执行,则直接进入其子节点
-->
<task id="TkReceive" name="接收数据" enable="true" class="com.dy.aceMw.server.rtuData.TkReceive">
    <task id="TkRtuData" name="接收RTU数据" enable="true" class="com.dy.aceMw.server.rtuData.TkRtuData">
        <task id="TkFindP206V1_0_0" name="识别P206V1_0_0数据" enable="true" class="com.dy.aceMw.server.rtuData.p206V1_0_0.TkFindP206V1_0_0">
            <task id="TkPreGenObjs" name="预先准备各对象" enable="true" class="com.dy.aceMw.server.rtuData.p206V1_0_0.TkPreGenObjs">
                <!-- è¯†åˆ«æµæµªè€…RTU,数据库中没有或数据库存在但未分配置供水机构 -->
                <task id="TkDealRtuTramp" name="识别流浪者RTU" enable="true" class="com.dy.aceMw.server.rtuData.p206V1_0_0.TkDealRtuTramp" />
                <!-- éžæµæµªè€…RTU,必须放在TkDealRtuTramp后面 -->
                <task id="TkDealNoRtuTramp" name="非流浪者RTU" enable="true" class="com.dy.aceMw.server.rtuData.p206V1_0_0.TkDealNoRtuTramp">
                    <!-- è¯†åˆ«ä¸»åŠ¨ä¸ŠæŠ¥æ•°æ® -->
                    <task id="TkFindAutoReport" name="识别主动上报及触发上报数据" enable="true" class="com.dy.aceMw.server.rtuData.p206V1_0_0.TkFindAutoReport">
                        <!-- æ£€æŸ¥æ—¶é—´ç­‰ä¸æ­£ç¡®çš„上报数据 -->
                        <task id="TkCheckAutoReport" name="检查时间等不正确的上报数据" enable="true" class="com.dy.aceMw.server.rtuData.p206V1_0_0.autoReport.TkCheckAutoReport">
                            <!-- æ£€æŸ¥é‡å¤ä¸ŠæŠ¥æ•°æ® -->
                            <task id="TkCheckRepeatReport" name="检查重复上报数据" enable="true" class="com.dy.aceMw.server.rtuData.p206V1_0_0.autoReport.TkCheckRepeatReport">
                                <!-- Mn运维系统 -->
                                <task id="TkMnRtuDealAutoReportLastAlarm" name="运维RTU上报最新报警" enable="true" class="com.dy.aceMw.server.rtuData.p206V1_0_0.autoReport.TkMnRtuDealAutoReportLastAlarm" />
                                <!-- RTU主动上报数据必须在RTU主动上报报警任务的下面,以备主动上报数据中记录是否有报警-->
                                <task id="TkMnRtuDealAutoReportLastData" name="运维RTU主动上报最新数据" enable="true" class="com.dy.aceMw.server.rtuData.p206V1_0_0.autoReport.TkMnRtuDealAutoReportLastData" />
                                <!-- RTU实时(触发)上报数据必须在RTU主动上报报警任务的下面,以备主动上报数据中记录是否有报警-->
                                <task id="TkMnRtuDealRealReportLastData" name="运维RTU实时(触发)上报最新数据" enable="true" class="com.dy.aceMw.server.rtuData.p206V1_0_0.autoReport.TkMnRtuDealRealReportLastData" />
                                <!-- Org供水机构系统 -->
                                <task id="TkOrgRtuDealAutoReportLastAlarm" name="供水机构RTU主动上报最新报警" enable="true" class="com.dy.aceMw.server.rtuData.p206V1_0_0.autoReport.TkOrgRtuDealAutoReportLastAlarm">
                                    <task id="TkOrgRtuDealAutoReportAlarm" name="供水机构RTU主动上报报警" enable="true" class="com.dy.aceMw.server.rtuData.p206V1_0_0.autoReport.TkOrgRtuDealAutoReportAlarm" />
                                    <task id="TkOrgRtuDealReportValveOpResult" name="供水机构RTU主动上报开关阀结果" enable="true" class="com.dy.aceMw.server.rtuData.p206V1_0_0.autoReport.TkOrgRtuDealReportValveOpResult" />
                                </task>
                                <!-- RTU主动上报数据必须在RTU主动上报报警任务的下面,以备主动上报数据中记录是否有报警-->
                                <task id="TkOrgRtuDealDayAmountAlarm" name="供水机构RTU日结累计流量报警" enable="true" class="com.dy.aceMw.server.rtuData.p206V1_0_0.autoReport.TkOrgRtuDealDayAmountAlarm" >
                                    <task id="TkOrgRtuDeal48HourNoAmount" name="供水机构RTU48小时未用水" enable="true" class="com.dy.aceMw.server.rtuData.p206V1_0_0.autoReport.TkOrgRtuDeal48HourNoAmount" >
                                        <task id="TkOrgRtuDealAutoReportLastData" name="供水机构RTU主动上报最新数据" enable="true" class="com.dy.aceMw.server.rtuData.p206V1_0_0.autoReport.TkOrgRtuDealAutoReportLastData">
                                            <task id="TkOrgRtuDealAutoReportData" name="供水机构RTU主动上报数据" enable="true" class="com.dy.aceMw.server.rtuData.p206V1_0_0.autoReport.TkOrgRtuDealAutoReportData" />
                                            <task id="TkOrgRtuDealCycleData" name="供水机构RTU主动上报周期采集数据" enable="true" class="com.dy.aceMw.server.rtuData.p206V1_0_0.autoReport.TkOrgRtuDealCycleData">
                                                <task id="TkOrgRtuDealCycleLongSmallAmountAlarm" name="供水机构RTU主动上报周期采集数据长流水分析" enable="true" class="com.dy.aceMw.server.rtuData.p206V1_0_0.autoReport.TkOrgRtuDealCycleLongSmallAmountAlarm" />
                                            </task>
                                            <task id="TkOrgRtuDealAmountCost" name="供水机构RTU主动上报计算日水量、月水量、及水费" enable="true" class="com.dy.aceMw.server.rtuData.p206V1_0_0.autoReport.TkOrgRtuDealAmountCost" >
                                                <task id="TkOrgRtuDealPayCost" name="供水机构用水户水表电子钱包支付水费" enable="true" class="com.dy.aceMw.server.rtuData.p206V1_0_0.autoReport.TkOrgRtuDealPayCost" />
                                            </task>
                                        </task>
                                    </task>
                                </task>
                                <!-- RTU实时(触发)上报数据必须在RTU主动上报报警任务的下面,以备主动上报数据中记录是否有报警-->
                                <task id="TkOrgRtuDealRealReportLastData" name="供水机构RTU实时(触发)上报最新数据" enable="true" class="com.dy.aceMw.server.rtuData.p206V1_0_0.autoReport.TkOrgRtuDealRealReportLastData">
                                    <task id="TkOrgRtuDealRealReportData" name="供水机构RTU实时(触发)上报数据" enable="true" class="com.dy.aceMw.server.rtuData.p206V1_0_0.autoReport.TkOrgRtuDealRealReportData" />
                                </task>
                            </task>
                        </task>
                    </task>
                    <!-- è¯†åˆ«å‘½ä»¤å“åº”数据 -->
                    <task id="TkFindComResponse" name="识别响应命令数据" enable="true" class="com.dy.aceMw.server.rtuData.p206V1_0_0.TkFindComResponse">
                        <task id="TkRtuDealCommandResponse" name="RTU响应命令数据" enable="true" class="com.dy.aceMw.server.rtuData.p206V1_0_0.comResponse.TkRtuDealCommandResponse" >
                            <task id="TkRtuDealSetParamComResponse" name="RTU响应设置参数命令数据" enable="true" class="com.dy.aceMw.server.rtuData.p206V1_0_0.comResponse.TkRtuDealSetParamComResponse" />
                        </task>
                    </task>
                </task>
            </task>
        </task>
        <task id="TkFindHAC_NBhV2_5" name="识别HAC_NBhV2_5数据" enable="true" class="com.dy.busi.server.rtuData.HAC_NBhV2_5.TkFindHAC_NBhV2_5">
            <task id="TkPipPreGenObjs" name="预先准备各对象" enable="true" class="com.dy.busi.server.rtuData.HAC_NBhV2_5.TkPipPreGenObjs">
                <!-- è¯†åˆ«æµæµªè€…管网水表,数据库中没有或数据库存在但未分配置供水机构 -->
                <task id="TkPipDealRtuTramp" name="识别流浪者管网水表" enable="true" class="com.dy.busi.server.rtuData.HAC_NBhV2_5.TkPipDealRtuTramp" />
                <!-- éžæµæµªè€…管网水表,必须放在TkDealRtuTramp后面 -->
                <task id="TkPipDealNoRtuTramp" name="非流浪者管网水表" enable="true" class="com.dy.busi.server.rtuData.HAC_NBhV2_5.TkPipDealNoRtuTramp">
                    <!-- è¯†åˆ«ä¸»åŠ¨ä¸ŠæŠ¥æ•°æ® -->
                    <task id="TkPipFindAutoReport" name="识别主动上报及触发上报数据" enable="true" class="com.dy.busi.server.rtuData.HAC_NBhV2_5.TkPipFindAutoReport">
                        <!-- æ£€æŸ¥æ—¶é—´ç­‰ä¸æ­£ç¡®çš„上报数据 -->
                        <task id="TkPipCheckAutoReport" name="检查时间等不正确的上报数据" enable="true" class="com.dy.busi.server.rtuData.HAC_NBhV2_5.autoReport.TkPipCheckAutoReport">
                            <task id="TkPipCheckRepeatAutoReport" name="检查重复上报数据" enable="true" class="com.dy.busi.server.rtuData.HAC_NBhV2_5.autoReport.TkPipCheckRepeatAutoReport">
                                <!-- Mn运维系统 -->
                                <task id="TkPipMnRtuDealAutoReportLastAlarm" name="运维管网水表上报最新报警" enable="true" class="com.dy.busi.server.rtuData.HAC_NBhV2_5.autoReport.TkPipMnRtuDealAutoReportLastAlarm" />
                                <!-- RTU主动上报数据必须在RTU主动上报报警任务的下面,以备主动上报数据中记录是否有报警-->
                                <task id="TkPipMnRtuDealAutoReportLastData" name="运维管网水表主动上报最新数据" enable="true" class="com.dy.busi.server.rtuData.HAC_NBhV2_5.autoReport.TkPipMnRtuDealAutoReportLastData" />
                                <!-- Org供水机构系统 -->
                                <task id="TkPipOrgRtuDealAutoReportLastAlarm" name="供水机构管网水表主动上报最新报警" enable="true" class="com.dy.busi.server.rtuData.HAC_NBhV2_5.autoReport.TkPipOrgRtuDealAutoReportLastAlarm">
                                    <task id="TkPipOrgRtuDealAutoReportAlarm" name="供水机构管网水表主动上报报警" enable="true" class="com.dy.busi.server.rtuData.HAC_NBhV2_5.autoReport.TkPipOrgRtuDealAutoReportAlarm" />
                                </task>
                                <!-- RTU主动上报数据必须在RTU主动上报报警任务的下面,以备主动上报数据中记录是否有报警-->
                                <task id="TkPipOrgRtuDealAutoReportLastData" name="供水机构管网水表主动上报最新数据" enable="true" class="com.dy.busi.server.rtuData.HAC_NBhV2_5.autoReport.TkPipOrgRtuDealAutoReportLastData">
                                    <task id="TkPipOrgRtuDealAutoReportData" name="供水机构管网水表主动上报数据" enable="true" class="com.dy.busi.server.rtuData.HAC_NBhV2_5.autoReport.TkPipOrgRtuDealAutoReportData" />
                                    <task id="TkPipOrgRtuDealAmount" name="供水机构管网水表月流量统计" enable="true" class="com.dy.busi.server.rtuData.HAC_NBhV2_5.autoReport.TkPipOrgRtuDealAmount" />
                                </task>
                            </task>
                        </task>
                    </task>
                </task>
            </task>
        </task>
    </task>
</task>
</project>
pipIrr-platform/pipIrr-mw/pipIrr-mwTest-client/pom.xml
@@ -37,6 +37,21 @@
    </dependencies>
    <build>
        <resources>
            <resource>
                <directory>src/main/java</directory>
                <includes>
                    <include>**/*.xml</include>
                </includes>
            </resource>
            <resource>
                <directory>src/main/resources</directory>
                <includes>
                    <include>**/*.xml</include>
                    <include>**/*.yml</include>
                </includes>
            </resource>
        </resources>
        <plugins>
            <plugin>
                <!-- è¯¥æ’件不会将项目中引入的依赖打进最终的 Jar æ–‡ä»¶ -->
pipIrr-platform/pipIrr-mw/pipIrr-mwTest-client/src/main/java/com/dy/testClient/rmiClient/RmiClUnit.java
@@ -101,7 +101,7 @@
            rqVo.id = id ;
            rqVo.token = token ;
            rqVo.code = Code.cd5 ;
            rqVo.count = count ;
            rqVo.overCount = count ;
            String json = rqVo.toJson() ;
            frmWork.syncRequest(json) ;
        } catch (Exception e) {
pipIrr-platform/pipIrr-mw/pipIrr-mwTest-client/src/main/java/com/dy/testClient/rmiClient/RmiRequestVo.java
@@ -9,9 +9,11 @@
    public String token ;
    
    public String code ;
    public Integer count;//aepTest上报数据数量
    public Integer overCount;//aepTest结束上报数据数量
    public Boolean over ;//aepTest上报数据结束
    
    public Long seconds ;//aepTest上报数据用时(秒)
pipIrr-platform/pipIrr-mw/pipIrr-mwTest-client/src/main/java/com/dy/testClient/tcpClient/LocalDecoder.java
@@ -1,5 +1,8 @@
package com.dy.testClient.tcpClient;
import com.dy.common.util.ByteUtil;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.mina.core.buffer.IoBuffer;
import org.apache.mina.core.session.IoSession;
import org.apache.mina.filter.codec.CumulativeProtocolDecoder;
@@ -8,6 +11,8 @@
import java.io.IOException;
public class LocalDecoder extends CumulativeProtocolDecoder {
    private static final Logger log = LogManager.getLogger(LocalDecoder.class) ;
    private static final String DECODER_STATE_KEY = LocalDecoder.class.getName() + ".STATE";
@@ -23,6 +28,7 @@
            byte[] preByte = new byte[remain];
            in.get(preByte) ;
            in.position(0) ;
            log.info("收到中心应答数据:" + ByteUtil.bytes2Hex(preByte, true));
        }
        return true;
    }
pipIrr-platform/pipIrr-mw/pipIrr-mwTest-client/src/main/java/com/dy/testClient/tcpClient/MyThreadJob.java
@@ -6,16 +6,20 @@
import com.dy.common.threadPool.ThreadPool;
import com.dy.common.util.ByteUtil;
import com.dy.testClient.ServerProperties;
import org.apache.mina.core.future.CloseFuture;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.mina.core.session.IoSession;
public class MyThreadJob  implements ThreadPool.Job {
    private static final Logger log = LogManager.getLogger(MyThreadJob.class) ;
    public String rtuAddr;
    public String serverIp;
    public Integer serverPort;
    public IoSession session ;
    public boolean exceptionOnConnect = false ;
    public static final int connectTimeout = 3000 ;
@@ -34,12 +38,9 @@
    @Override
    public void execute() throws Exception {
        if(session == null){
            IoSession se = new TcpConnect().createSession(this.rtuAddr, this, this.serverIp, this.serverPort, connectTimeout, new TcpHandler()) ;
            if(se != null){
                this.session = se ;
            }
        }else{
        log.info("RTU" + rtuAddr + "开始任务");
        if(session != null){
            log.info("RTU" + rtuAddr + "将要执行" + ServerProperties.sendTimes + "轮次任务,当前轮次是" + sendTimes);
            if(sendTimes <= ServerProperties.sendTimes){
                sendDataOfP206V1_0_0() ;
            }else{
@@ -53,9 +54,11 @@
            if(heartbeatTimes >= ServerProperties.heartbeatTimes){
                heartbeatTimes = 0 ;
                this.sendReportData() ;
                TcpClUnit.clientSendData();
                sendTimes++ ;
            }else{
                this.sendHeartbeat() ;
                TcpClUnit.clientSendData();
                heartbeatTimes++ ;
            }
        }catch(Exception e){
@@ -66,23 +69,30 @@
        try{
            byte[] bs = this.createHeartbeat() ;
            this.session.write(bs) ;
            log.info("RTU" + rtuAddr + "发送了心跳数据:" + ByteUtil.bytes2Hex(bs, false));
        }catch (Exception e){
            e.printStackTrace();
        }
    }
    private void sendReportData(){
        TcpClUnit.clientSendData();
        try{
            byte[] bs = this.createReport() ;
            this.session.write(bs) ;
            log.info("RTU" + rtuAddr + "发送了上报数据:" + ByteUtil.bytes2Hex(bs, false));
        }catch (Exception e){
            e.printStackTrace();
        }
    }
    private void jobOver(){
        CloseFuture closeFuture = session.closeOnFlush() ;
        session.closeOnFlush() ;
        this.isOver = true ;
        TcpClUnit.clientOver() ;
    }
    /**
     * æž„造下行数据
     * æž„造心跳数据
     * @return å­—节数组
     * @throws Exception å¼‚常
     */
@@ -100,7 +110,7 @@
        bsHead[index] = ProtocolConstantV206V1_0_0.P_Head_Byte ;
        index++ ;
        bsHead[index] = commonV1_0_1.createCtrl((byte)0) ;
        bsHead[index] = commonV1_0_1.createCtrl((byte)0x80, (byte)0) ;//控制域功能码:确认 è®¤å¯
        index++ ;
        GlCreate.createRtuAddr(this.rtuAddr, bsHead, index);
@@ -115,7 +125,91 @@
        GlCreate.createLen(bytes);//长度放字节数组中
        bytes = GlCreate.createCrcTail(bytes) ;//CRC和尾叠加字节数组中
        byte[] bsTail = GlCreate.createCrcTail(bytes) ;//CRC和尾叠加字节数组中
        bytes = ByteUtil.bytesMerge(bytes, bsTail) ;
        return bytes ;
    }
    /**
     * æž„造上报数据
     * @return å­—节数组
     * @throws Exception å¼‚常
     */
    public byte[] createReport( ) throws Exception {
        CommonV1_0_1 commonV1_0_1 = new CommonV1_0_1() ;
        byte[] bytes ;
        byte[] bsHead = new byte[ProtocolConstantV206V1_0_0.lenHead2Code] ;
        byte index = 0 ;
        bsHead[index] = ProtocolConstantV206V1_0_0.P_Head_Byte ;
        index++ ;
        bsHead[index] = 0 ;//帧长度
        index++ ;
        bsHead[index] = ProtocolConstantV206V1_0_0.P_Head_Byte ;
        index++ ;
        bsHead[index] = commonV1_0_1.createCtrl((byte)0x80, (byte)3) ;//控制域功能码3:自报帧,流量(水量)参数
        index++ ;
        GlCreate.createRtuAddr(this.rtuAddr, bsHead, index);
        index += 5 ;
        ByteUtil.hex2Bytes("C0", bsHead, index) ;
        byte[] bs = new byte[2] ;
        bs[0] = (byte)0x04 ;//有流量数据
        bs[1] = (byte)0xE0 ;//有水压、电池电压、信号强度
        bytes = ByteUtil.bytesMerge(bsHead, bs) ;
        bs = new byte[5] ;//瞬时流量
        bs[0] = ByteUtil.int2BCD_LE (21)[0] ;
        bs[1] = ByteUtil.int2BCD_LE (43)[0] ;
        bs[2] = ByteUtil.int2BCD_LE (65)[0] ;
        bytes = ByteUtil.bytesMerge(bytes, bs) ;
        bs = new byte[5] ;//累计流量
        bs[0] = ByteUtil.int2BCD_LE (21)[0] ;
        bs[1] = ByteUtil.int2BCD_LE (43)[0] ;
        bs[2] = ByteUtil.int2BCD_LE (65)[0] ;
        bs[3] = ByteUtil.int2BCD_LE (87)[0] ;
        bytes = ByteUtil.bytesMerge(bytes, bs) ;
        bs = new byte[5] ;//损失流量
        bs[0] = ByteUtil.int2BCD_LE (10)[0] ;
        bs[1] = ByteUtil.int2BCD_LE (32)[0] ;
        bs[2] = ByteUtil.int2BCD_LE (54)[0] ;
        bytes = ByteUtil.bytesMerge(bytes, bs) ;
        bs = new byte[4] ;//水压
        bs[0] = ByteUtil.int2BCD_LE (10)[0] ;
        bs[1] = ByteUtil.int2BCD_LE (32)[0] ;
        bs[2] = ByteUtil.int2BCD_LE (4)[0] ;
        bytes = ByteUtil.bytesMerge(bytes, bs) ;
        bs = new byte[4] ;//电池电压
        bs[0] = ByteUtil.int2BCD_LE (10)[0] ;
        bs[1] = ByteUtil.int2BCD_LE (32)[0] ;
        bs[2] = ByteUtil.int2BCD_LE (10)[0] ;
        bs[3] = ByteUtil.int2BCD_LE (32)[0] ;
        bytes = ByteUtil.bytesMerge(bytes, bs) ;
        bs = new byte[1] ;//信号强度
        bs[0] = ByteUtil.int2BCD_LE (21)[0] ;
        bytes = ByteUtil.bytesMerge(bytes, bs) ;
        bs = new byte[6] ;//时钟
        GlCreate.createTp(bs, 0);
        bytes = ByteUtil.bytesMerge(bytes, bs) ;
        GlCreate.createLen(bytes);//长度放字节数组中
        byte[] bsTail = GlCreate.createCrcTail(bytes) ;//CRC和尾叠加字节数组中
        bytes = ByteUtil.bytesMerge(bytes, bsTail) ;
        return bytes ;
    }
pipIrr-platform/pipIrr-mw/pipIrr-mwTest-client/src/main/java/com/dy/testClient/tcpClient/TcpClUnit.java
@@ -5,10 +5,12 @@
import com.dy.common.mw.UnitStartedCallbackInterface;
import com.dy.common.threadPool.ThreadPool;
import com.dy.common.threadPool.TreadPoolFactory;
import com.dy.common.util.Callback;
import com.dy.testClient.ServerProperties;
import com.dy.testClient.rmiClient.RmiClUnit;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.mina.core.session.IoSession;
import java.util.Collection;
import java.util.HashMap;
@@ -26,7 +28,7 @@
    private static ThreadPool.Pool pool ;
    private static Map<String, MyThreadJob> jobMap = new HashMap<>() ;
    private static Integer totalRunedClientCount = 0;
    private static Integer totalRtuClientCount = 0;
    private static Integer totalSendDataCount = 0;
    private static Integer totalOverClientCount = 0;
@@ -72,23 +74,46 @@
                        if(!ServerProperties.startWork){
                            Thread.sleep(100L);
                        }else{
                            startTime = System.currentTimeMillis() ;
                            for(Long addr = ServerProperties.rtuAddrStart; addr <= ServerProperties.rtuAddrEnd; addr++){
                                totalRunedClientCount++ ;
                                createImitate(addr) ;
                            }
                            startJob() ;
                            while(true){
                                if(totalOverClientCount.longValue() >= totalRunedClientCount.longValue()){
                                    Long seconds = (System.currentTimeMillis() - startTime)/1000 ;
                                    RmiClUnit.getInstance().allOver(seconds) ;
                                    System.out.println("共用时" + seconds + "秒");
                                    break ;
                                }else{
                                    Thread.sleep(100L);
                            try{
                                startTime = System.currentTimeMillis() ;
                                for(Long addr = ServerProperties.rtuAddrStart; addr <= ServerProperties.rtuAddrEnd; addr++){
                                    totalRtuClientCount++ ;
                                    createImitate(addr) ;
                                }
                                log.info("共模拟了" + totalRtuClientCount + "台RTU");
                                Collection<MyThreadJob> collection = jobMap.values() ;
                                for(MyThreadJob job : collection){
                                    connectServer(job) ;
                                }
                                log.info("启动所有RTU连接通信中间件");
                                while (true){
                                    int noConnectedCount = checkConnected() ;
                                    if(noConnectedCount > 0){
                                        log.info("等待" + noConnectedCount + "台RTU连接网络");
                                        Thread.sleep(100L);
                                    }else{
                                        break ;
                                    }
                                }
                                startJob() ;
                                while(true){
                                    if(totalOverClientCount.longValue() >= totalRtuClientCount.longValue()){
                                        Long seconds = (System.currentTimeMillis() - startTime)/1000 ;
                                        RmiClUnit.getInstance().allOver(seconds) ;
                                        log.info("共用时" + seconds + "秒");
                                        break ;
                                    }else{
                                        Thread.sleep(100L);
                                    }
                                }
                            }catch (Exception e){
                                e.printStackTrace();
                            }finally {
                                break ;
                            }
                            break;
                        }
                    }
                } catch (Exception e) {
@@ -106,18 +131,71 @@
        jobMap.put("" + rtuAddr, new MyThreadJob("" + rtuAddr, ServerProperties.tcpServerIp, ServerProperties.tcpServerPort)) ;
    }
    private void connectServer(MyThreadJob job){
        if(job.session == null){
            try{
                new TcpConnect().createSession(job.rtuAddr,
                        job,
                        job.serverIp,
                        job.serverPort,
                        job.connectTimeout,
                        new TcpHandler(),
                        new Callback() {
                            @Override
                            public void call(Object obj) {
                                if(obj == null){
                                    log.error("创建网络会话返回为null");
                                }else{
                                    job.session = (IoSession)obj ;
                                }
                            }
                            @Override
                            public void call(Object... objs) {
                            }
                            @Override
                            public void exception(Exception e) {
                            }
                        }) ;
            }catch (Exception e){
                job.exceptionOnConnect = true ;
                e.printStackTrace();
            }
        }
    }
    private int checkConnected(){
        int noConnectedCount = 0 ;
        Collection<MyThreadJob> collection = jobMap.values() ;
        for(MyThreadJob job : collection){
            if(job.session == null && !job.exceptionOnConnect){
                noConnectedCount++ ;
            }
        }
        return noConnectedCount;
    }
    private void startJob(){
        new Thread(new Runnable(){
            @Override
            public void run() {
                try {
                    Thread.sleep(1000L);
                    int notOverCount;
                    while(true){
                        notOverCount = 0 ;
                        Collection<MyThreadJob> collection = jobMap.values() ;
                        for(MyThreadJob job : collection){
                            pool.putJob(job);
                            if(!job.isOver){
                                notOverCount++ ;
                                pool.putJob(job);
                            }
                        }
                        Thread.sleep(ServerProperties.sendInterval * 1000);
                        if(notOverCount > 0){
                            log.info("当前还有" + notOverCount + "台RTU未完成任务");
                            Thread.sleep(ServerProperties.sendInterval * 1000);
                        }else{
                            break ;
                        }
                    }
                } catch (Exception e) {
                    e.printStackTrace();
@@ -129,17 +207,37 @@
    public static synchronized void clientSendData(){
        totalSendDataCount++;
        if(totalSendDataCount % 100 == 0){
        if(totalOverClientCount.longValue() >= totalRtuClientCount.longValue()){
            RmiClUnit.getInstance().reportHadReportCount(totalSendDataCount);
            System.out.println("已经发送" + totalSendDataCount + "条数据");
        }else{
            if(totalRtuClientCount > 100){
                if(totalSendDataCount % 100 == 0){
                    RmiClUnit.getInstance().reportHadReportCount(totalSendDataCount);
                    System.out.println("已经发送" + totalSendDataCount + "条数据");
                }
            }else{
                RmiClUnit.getInstance().reportHadReportCount(totalSendDataCount);
                System.out.println("已经发送" + totalSendDataCount + "条数据");
            }
        }
    }
    public static synchronized void clientOver(){
        totalOverClientCount++;
        if(totalOverClientCount % 100 == 0){
        if(totalOverClientCount.longValue() >= totalRtuClientCount.longValue()){
            RmiClUnit.getInstance().reportHadReportOver(totalOverClientCount);
            System.out.println("已有" + totalOverClientCount + "完成了任务");
            System.out.println("已有" + totalOverClientCount + "个RTU完成了任务");
        }else{
            if(totalRtuClientCount > 100) {
                if (totalOverClientCount % 100 == 0) {
                    RmiClUnit.getInstance().reportHadReportOver(totalOverClientCount);
                    System.out.println("已有" + totalOverClientCount + "个RTU完成了任务");
                }
            }else{
                RmiClUnit.getInstance().reportHadReportOver(totalOverClientCount);
                System.out.println("已有" + totalOverClientCount + "个RTU完成了任务");
            }
        }
    }
}
pipIrr-platform/pipIrr-mw/pipIrr-mwTest-client/src/main/java/com/dy/testClient/tcpClient/TcpConnect.java
@@ -1,5 +1,6 @@
package com.dy.testClient.tcpClient;
import com.dy.common.util.Callback;
import org.apache.mina.core.future.ConnectFuture;
import org.apache.mina.core.session.IoSession;
import org.apache.mina.filter.codec.ProtocolCodecFilter;
@@ -28,9 +29,18 @@
     * @param job rtu工作类
     * @param host æœåС噍URI
     * @param port æœåŠ¡å™¨ç«¯å£
     * @param connectTimeout è¿žæŽ¥è¶…æ—¶æ—¶é•¿
     * @param handler æ•°æ®å¤„理者
     * @param callback å›žè°ƒ
     * @return ç½‘络会话
     */
    public IoSession createSession(String rtuAddr, MyThreadJob job, String host , int port , int connectTimeout , TcpHandler handler) throws Exception{
    public void createSession(String rtuAddr,
                                   MyThreadJob job,
                                   String host ,
                                   int port ,
                                   int connectTimeout ,
                                   TcpHandler handler,
                                   Callback callback) throws Exception{
        SocketConnector connector = new NioSocketConnector();
        connector.getFilterChain().addLast("codec", new ProtocolCodecFilter(new LocalCodecFactory()));
        connector.setHandler(handler);
@@ -39,7 +49,7 @@
        IoSession se = connectFuture.getSession();
        se.setAttribute(rtuAddrKey, rtuAddr) ;
        se.setAttribute(threadJobKey, job) ;
        return se ;
        callback.call(se) ;
    }
pipIrr-platform/pipIrr-mw/pipIrr-mwTest-server/src/main/java/com/dy/testServer/console/Command.java
@@ -108,6 +108,9 @@
                    if(sta.count != null){
                        prtWrt.println("    å·²ç»ä¸ŠæŠ¥æ•°æ®ï¼š" + sta.count + "条");
                    }
                    if(sta.overCount != null){
                        prtWrt.println("    å·²ç»å®Œæˆä¸ŠæŠ¥æ•°æ®ï¼š" + sta.overCount + "台RTU");
                    }
                    if(sta.over != null && sta.over){
                        prtWrt.println("    ä¸ŠæŠ¥æ•°æ®å·²ç»å®Œæˆï¼Œå…±ç”¨æ—¶ï¼š" + sta.seconds + "秒");
                    }
pipIrr-platform/pipIrr-mw/pipIrr-mwTest-server/src/main/java/com/dy/testServer/forRmi/Manager.java
@@ -161,10 +161,10 @@
        MwTestClientStatus sta = token2ClientMap.get("" + token);
        if(sta == null){
            sta = new MwTestClientStatus() ;
            sta.overCount = rqVo.count ;
            sta.overCount = rqVo.overCount ;
            token2ClientMap.put("" + token, sta);
        }else{
            sta.count = rqVo.count ;
            sta.overCount = rqVo.overCount ;
        }
    }
pipIrr-platform/pipIrr-mw/pipIrr-mwTest-server/src/main/java/com/dy/testServer/forRmi/RmiRequestVo.java
New file
@@ -0,0 +1,96 @@
package com.dy.testServer.forRmi;
import com.alibaba.fastjson2.JSON;
public class RmiRequestVo {
    public String id ;//客户端ID
    public String token ;//服务端分配的token
    public String code ;
    public Integer count;//mwTest上报数据数量
    public Integer overCount;//aepTest结束上报数据数量
    public Boolean over ;//mwTest上报数据结束
    public Long seconds ;//mwTest上报数据用时(秒)
    /**
     * å¯¹è±¡è½¬æˆjson
     * @return json
     * @throws Exception å¼‚常
     */
    public String toJson()throws Exception{
        try{
            return JSON.toJSONString(this) ;
            //return new JSONSerializer().exclude(new String[]{"class", "*.class"}).deepSerialize(this);
        }catch(Exception e){
            throw new Exception(e.getMessage() , e ) ;
        }
    }
    /**
     * json转成对象
     * @param json å‚æ•°
     * @return å¯¹è±¡
     * @throws Exception å¼‚常
     */
    public static RmiRequestVo jsonToObject(String json)throws Exception{
        try{
            return JSON.parseObject(json, RmiRequestVo.class) ;
            //JSONDeserializer<RmiRequestVo> jsonD = new JSONDeserializer<>() ;
            //RmiRequestVo rqVo = jsonD.deserialize(json, RmiRequestVo.class) ;
            //return rqVo ;
        }catch(Exception e){
            throw new Exception(e.getMessage() , e ) ;
        }
    }
    public String getId() {
        return id;
    }
    public void setId(String id) {
        this.id = id;
    }
    public String getToken() {
        return token;
    }
    public void setToken(String id) {
        this.token = id;
    }
    public String getCode() {
        return code;
    }
    public void setCode(String code) {
        this.code = code;
    }
    public Integer getCount() {
        return count;
    }
    public void setCount(Integer count) {
        this.count = count;
    }
    public Boolean getOver() {
        return over;
    }
    public void setOver(Boolean over) {
        this.over = over;
    }
    public Long getSeconds() {
        return seconds;
    }
    public void setSeconds(Long seconds) {
        this.seconds = seconds;
    }
    public Integer getOverCount() {
        return overCount;
    }
    public void setOverCount(Integer overCount) {
        this.overCount = overCount;
    }
}