1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
package com.dy.common.mw.protocol.p206V202404.parse;
 
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.dy.common.mw.protocol.*;
import com.dy.common.mw.protocol.p206V202404.CodeV202404;
import com.dy.common.mw.protocol.p206V202404.ParseParamsForDownV202404;
import com.dy.common.mw.protocol.p206V202404.downVos.ComCd15Vo;
import com.dy.common.mw.protocol.p206V202404.parse.global.GlCreate;
import com.dy.common.util.ByteUtil;
import com.dy.common.util.NumUtil;
 
@AnnotationCodeDown(ifAny={
        CodeV202404.cd_15
})
public class Cd_15_Down implements CodeParse {
 
    @Override
    public MidResult[] parse(Boolean isLowPower, CodeParseParams params, CodeParseCallback callback) throws Exception {
        ParseParamsForDownV202404 para = (ParseParamsForDownV202404) params ;
        byte[] bs = this.doParse(para) ;
 
        MidResultToRtu midRs = new MidResultToRtu() ;
        midRs.protocolName = para.protocolName ;//协议名称
        midRs.protocolVersion = para.protocolVersion ;//协议版本号
        midRs.rtuResultSendWebUrl = para.rtuResultSendWebUrl ;
        midRs.rtuAddr = para.rtuAddr ;//Rtu地址
        midRs.commandId = para.commandId ;//命令ID,发起命令的客户端(web端)生成,以匹配命令结果
        midRs.downCode = para.commandCode ;//下行命令功能码;
        midRs.downCodeName = CodeV202404.getCodeName(para.commandCode) ;//下行命令功能码名称;
        midRs.downBuffer = bs ;//下行命令数据
        midRs.downBufHex = ByteUtil.bytes2Hex(bs, true) ;//下行命令数据十六进制形式
        midRs.hasResponse = true ;//是否有应答
        midRs.maxSendTimes = null ;//命令最大发送次数(当收不到应答时,将重发),如果不设置,命令缓存器进行补充设置
        midRs.isCachForOffLine = false ;//RTU不在线,命令是否缓存,低功耗时为true
 
        midRs.isSendFirst = false ;//命令应答,首先发送,防止RTU重新上报
        if(isLowPower != null && isLowPower.booleanValue()){
            //低功耗时,尽快发送
            midRs.isQuickSend = true ;
        }
 
        return new MidResult[]{midRs} ;
    }
    /**
     * 构造下行数据
     * @param para 参数
     * @return 字节数组
     * @throws Exception 异常
     */
    public byte[] doParse(ParseParamsForDownV202404 para) throws Exception {
        byte[] bytes = GlCreate.createStart2Cd(para.rtuAddr, para.commandCode);
        if(para.param != null){
            JSONObject obj = (JSONObject)para.param;
            String json = obj.toJSONString();
            ComCd15Vo cvo = JSON.parseObject(json, ComCd15Vo.class) ;
            if(cvo == null){
                throw new Exception("json转ComCd15Vo为null") ;
            }
            if(cvo.icCardAddr.length() != 8){
                throw new Exception("IC卡地址必须是8位数字或字母") ;
            }
           if(!NumUtil.isPlusIntNumber(cvo.flowNo)){
                throw new Exception("流水号必须是12位数字") ;
            }
            if(cvo.flowNo.length() != 12){
                throw new Exception("流水号必须是12位数字") ;
            }
            byte[] bs = new byte[43] ;
            int index = 0 ;
            bs[index] = (byte)(Integer.parseInt(cvo.controllerType, 16));
 
            index ++ ;
            bs[index] = cvo.projectNo.byteValue() ;
 
            index ++ ;
            GlCreate.createIcCardAddr(cvo.icCardAddr, bs, index);
 
            index += 4 ; ;
            GlCreate.createIcCardNo(cvo.icCardNo, bs, index);
 
            index += 8 ;
            if(cvo.chargeMoney != null){
                String chargeMoney = "" + (Double.valueOf(cvo.chargeMoney * 100)).longValue() ;
                byte[] bTemp = ByteUtil.string2BCD_LE(chargeMoney) ;
                int bTempLen = bTemp.length ;
                int count = 0 ;
                for(int i = 0 ; i < bTempLen; i++){
                    bs[index++] = bTemp[i] ;
                    count ++ ;
                    if(count >= 5){
                        break ;
                    }
                }
                for(; count < 5; count++){
                    bs[index++] = 0 ;
                }
            }else{
                for(int i = 0 ; i < 5; i++){
                    bs[index++] = 0 ;
                }
            }
            if(cvo.chargeWater != null){
                String chargeWater = "" + (Double.valueOf(cvo.chargeWater * 100)).longValue() ;
                byte[] bTemp = ByteUtil.string2BCD_LE(chargeWater) ;
                int bTempLen = bTemp.length ;
                int count = 0 ;
                for(int i = 0 ; i < bTempLen; i++){
                    bs[index++] = bTemp[i] ;
                    count ++ ;
                    if(count >= 5){
                        break ;
                    }
                }
                for(; count < 5; count++){
                    bs[index++] = 0 ;
                }
            }else{
                for(int i = 0 ; i < 5; i++){
                    bs[index++] = 0 ;
                }
            }
 
            ByteUtil.string2BCD_BE(bs, cvo.flowNo, index) ;
 
            index += 6 ;
            GlCreate.createDt(bs, index);
 
            index += 6 ;
            GlCreate.createPw(bs, index);
 
            index += 2 ;
            GlCreate.createS2D(bs, index) ;
 
            index += 4 ;
            bs[index] = 0 ; //时延
 
            bytes = ByteUtil.bytesMerge(bytes, bs) ;
        }else{
            throw new Exception("下行命令参数据为null") ;
        }
        GlCreate.createLen(bytes);//长度放字节数组中
 
        byte[] bsTail = GlCreate.createCrcTail(bytes) ;//CRC和尾
 
        bytes = ByteUtil.bytesMerge(bytes, bsTail) ;
 
        return bytes ;
    }
 
 
}