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
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
package com.dy.common.mw.protocol.p206V2.parse;
 
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.dy.common.mw.protocol.*;
import com.dy.common.mw.protocol.p206V2.CodeV2;
import com.dy.common.mw.protocol.p206V2.CommonV2;
import com.dy.common.mw.protocol.p206V2.ParseParamsForDownV2;
import com.dy.common.mw.protocol.p206V2.ProtocolConstantV206V2;
import com.dy.common.mw.protocol.p206V2.downVos.ComA1Vo;
import com.dy.common.mw.protocol.p206V2.parse.global.GlCreate;
import com.dy.common.util.ByteUtil;
 
/**
 * @Author liurunyu
 * @Date 2024/06/12 9:30
 * @Description
 */
@AnnotationCodeDown(ifAny={
        CodeV2.cd_A1
})
public class Cd_A1_Down implements CodeParse {
 
    @Override
    public MidResult[] parse(Boolean isLowPower, CodeParseParams params, CodeParseCallback callback) throws Exception {
        ParseParamsForDownV2 para = (ParseParamsForDownV2) params ;
        MidResultToRtu midRs = new MidResultToRtu() ;
        byte[] bs = this.doParse(midRs, para) ;
 
        midRs.rtuResultSendWebUrl = para.rtuResultSendWebUrl ;//rtu返回命令结果 发向目的地web URL
        midRs.protocolName = para.protocolName ;//协议名称
        midRs.rtuAddr = para.rtuAddr ;//Rtu地址
        midRs.commandId = para.commandId ;//命令ID,发起命令的客户端(web端)生成,以匹配命令结果
        midRs.downCode = para.commandCode ;//下行命令功能码;
        midRs.downCodeName = CodeV2.getCodeName(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 midRs 参数
     * @param para 参数
     * @return 字节数组
     * @throws Exception 异常
     */
    public byte[] doParse(MidResultToRtu midRs, ParseParamsForDownV2 para) throws Exception {
        CommonV2 commonV_1 = new CommonV2() ;
        byte[] bytes ;
        byte[] bsHead = new byte[ProtocolConstantV206V2.lenHead2Code] ;
        byte index = GlCreate.createHead(bsHead);
 
        index++ ;
        bsHead[index] = commonV_1.createCtrl((byte)0, (byte)0) ;
 
        index++ ;
        GlCreate.createRtuAddr(para.rtuAddr, bsHead, index);
        index += 5 ;
 
        ByteUtil.hex2Bytes(para.commandCode, bsHead, index) ;
 
        JSONObject obj = (JSONObject)para.param;
        String json = obj.toJSONString();
        ComA1Vo cvo = JSON.parseObject(json, ComA1Vo.class) ;
        if(cvo == null){
            throw new Exception("json转Com99Vo为null") ;
        }
        if(cvo.icCardNo == null){
            throw new Exception("虚拟IC卡编号不能为空") ;
        }
        if(cvo.moneyRemain == null || cvo.moneyRemain == 0.0){
            throw new Exception("剩余金额不能为空或为0") ;
        }
        if(cvo.waterPrice == null || cvo.waterPrice == 0.0){
            throw new Exception("水价不能为空或为0") ;
        }
        if(cvo.minutes == null || cvo.minutes == 0.0){
            throw new Exception("用水时长不能为空或为0") ;
        }
        if(cvo.minutes < 0 || cvo.minutes > 9999){
            throw new Exception("用水时长取值范围是0~9999分钟") ;
        }
        if(cvo.year == null){
            throw new Exception("计划开阀时间---年不能为空") ;
        }
        if(cvo.year < 24 || cvo.year > 9999){
            throw new Exception("计划开阀时间---年不正确") ;
        }
        if(cvo.year > 99 && cvo.year < 2024){
            throw new Exception("计划开阀时间---年不正确") ;
        }
        if(cvo.month == null){
            throw new Exception("计划开阀时间---月不能为空") ;
        }
        if(cvo.month < 1 || cvo.month > 12){
            throw new Exception("计划开阀时间---月不正确") ;
        }
        if(cvo.day == null){
            throw new Exception("计划开阀时间---日不能为空") ;
        }
        if(cvo.day < 1 || cvo.day > 31){
            throw new Exception("计划开阀时间---日不正确") ;
        }
        if(cvo.hour == null){
            throw new Exception("计划开阀时间---时不能为空") ;
        }
        if(cvo.hour < 0 || cvo.hour > 23){
            throw new Exception("计划开阀时间---时不正确") ;
        }
        if(cvo.minute == null){
            throw new Exception("计划开阀时间---时不能为空") ;
        }
        if(cvo.minute < 0 || cvo.minute > 59){
            throw new Exception("计划开阀时间---分不正确") ;
        }
 
        byte[] bs = new byte[8] ;
        GlCreate.createIcCardNo(cvo.icCardNo, bs, 0);
        bytes = ByteUtil.bytesMerge(bsHead, bs) ;
 
        bs = new byte[4] ;
        index = 0 ;
        Integer money = Double.valueOf(cvo.moneyRemain * 100.0D).intValue() ;
        byte[] bTemp = ByteUtil.int2BCD_LE(money) ;
        int bTempLen = bTemp.length ;
        int count = 0 ;
        for(int i = 0 ; i < bTempLen; i++){
            bs[index++] = bTemp[i] ;
            count ++ ;
            if(count >= 4){
                break ;
            }
        }
        for(; count < 4; count++){
            bs[index++] = 0 ;
        }
        bytes = ByteUtil.bytesMerge(bytes, bs) ;
 
        bs = new byte[2] ;
        index = 0 ;
        Integer price = Double.valueOf(cvo.waterPrice * 100.0D).intValue() ;
        bTemp = ByteUtil.int2BCD_LE(price) ;
        bTempLen = bTemp.length ;
        count = 0 ;
        for(int i = 0 ; i < bTempLen; i++){
            bs[index++] = bTemp[i] ;
            count ++ ;
            if(count >= 2){
                break ;
            }
        }
        for(; count < 2; count++){
            bs[index++] = 0 ;
        }
        bytes = ByteUtil.bytesMerge(bytes, bs) ;
 
 
        bs = new byte[2] ;
        index = 0 ;
        bTemp = ByteUtil.int2BCD_LE(cvo.minutes) ;
        bTempLen = bTemp.length ;
        count = 0 ;
        for(int i = 0 ; i < bTempLen; i++){
            bs[index++] = bTemp[i] ;
            count ++ ;
            if(count >= 2){
                break ;
            }
        }
        for(; count < 2; count++){
            bs[index++] = 0 ;
        }
        bytes = ByteUtil.bytesMerge(bytes, bs) ;
 
        bs = new byte[5] ;
        if(cvo.year >= 2024){
            cvo.year = cvo.year - 2000 ;
        }
        bs[0] = ByteUtil.int2BCD_LE(cvo.minute)[0] ;
        bs[1] = ByteUtil.int2BCD_LE(cvo.hour)[0] ;
        bs[2] = ByteUtil.int2BCD_LE(cvo.day)[0] ;
        bs[3] = ByteUtil.int2BCD_LE(cvo.month)[0] ;
        bs[4] = ByteUtil.int2BCD_LE(cvo.year)[0] ;
 
        bytes = ByteUtil.bytesMerge(bytes, bs) ;
 
        GlCreate.createLen(bytes);//长度放字节数组中
 
        byte[] bsTail = GlCreate.createCrcTail(bytes) ;//CRC和尾叠加字节数组中
 
        bytes = ByteUtil.bytesMerge(bytes, bsTail) ;
 
        return bytes ;
    }
 
}