liurunyu
2023-11-18 c1ddfd71223c1a7d704b6f21b669fbfcb37adc82
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
package com.dy.common.mw.protocol.pMeterV1_0_1.parse;
 
import java.util.ArrayList;
 
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
 
import com.dy.common.mw.protocol.AnnotationCodeUp;
import com.dy.common.mw.protocol.CodeParse;
import com.dy.common.mw.protocol.CodeParseCallback;
import com.dy.common.mw.protocol.CodeParseParams;
import com.dy.common.mw.protocol.Command;
import com.dy.common.mw.protocol.Data;
import com.dy.common.mw.protocol.MidResult;
import com.dy.common.mw.protocol.MidResultFromRtu;
import com.dy.common.mw.protocol.MidResultToRtu;
import com.dy.common.mw.protocol.pMeterV1_0_1.*;
import com.dy.common.util.ByteUtil;
import com.dy.common.util.ByteUtilUnsigned;
import com.dy.common.util.DateTime;
 
@AnnotationCodeUp(ifAny={
        CodeV1_0_1.cd_01
})
public class Cd_01_Up implements CodeParse{
 
    private static Logger log = LogManager.getLogger(Cd_01_Up.class);
 
    /**
     * 分析上行数据
     */
    @Override
    public MidResult[] parse(Boolean isLowPower, CodeParseParams params, CodeParseCallback callback)throws Exception {
        ParseParamsForUpV1_0_1 para = (ParseParamsForUpV1_0_1)params ;
        int bsLen = new CommonV1_0_1().parseDataLen(para.upBuffer) ;
        if(bsLen > 0){
            this.doParse(para.upBuffer, 
                    bsLen,
                    para.upCode, 
                    para.data) ;
        }
        log.info("分析上行数据<" + CodeV1_0_1.getCodeName(para.upCode) + " 水表号=" + para.meterNo + ">:\n" + para.data.toString());
 
        MidResultFromRtu midRs = new MidResultFromRtu() ;
        midRs.protocolName = para.protocolName ;//协议名称
        midRs.rtuAddr = para.rtuAddr ;//IMEI号
        midRs.meterNo = para.meterNo ;//水表号
        midRs.productId = para.productId ;//电信平台产品ID,当不在电信平台运行时,为null
        midRs.deviceId = para.deviceId ;//电信平台设备ID,当不在电信平台运行时,为null
        midRs.upCode = para.upCode ;//上行数据中的功能码
        midRs.upHex = para.upHex ;//上行数据十六进制形式
        midRs.upBuffer = para.upBuffer ;//上行数据字节数组
        midRs.data = para.data ;//解析后的数据
        
        midRs.reportOrResponse_trueOrFalse = true ;//主动上报
        
        String confirmComCode = CodeV1_0_1.cd_01 ;
        ParseParamsForDownV1_0_1 downCpParams  = new ParseParamsForDownV1_0_1() ;
        downCpParams.setValue(
                ProtocolConstantV1_0_1.protocolName, 
                para.rtuAddr, 
                para.meterNo, 
                para.productId,
                para.deviceId,
                Command.defaultId,
                confirmComCode, 
                null, 
                null);
        //构造上报确认应答
        byte[] data = new Cd_XY_Down().doParse(downCpParams) ;
 
        MidResultToRtu confirmCommand = new MidResultToRtu() ;
        confirmCommand.protocolName = para.protocolName ;//协议名称
        confirmCommand.rtuAddr = para.rtuAddr ;//IMEI号
        confirmCommand.meterNo = para.meterNo ;//水表号
        confirmCommand.productId = para.productId ;//电信平台产品ID,当不在电信平台运行时,为null
        confirmCommand.deviceId = para.deviceId ;//电信平台设备ID,当不在电信平台运行时,为null
        confirmCommand.commandId = Command.defaultId ;//命令ID,发起命令的客户端(web端)生成,以匹配命令结果
        confirmCommand.downCode = confirmComCode ;//下行命令功能码;
        confirmCommand.downBuffer = data ;//下行命令数据
        confirmCommand.downBufHex = ByteUtil.bytes2Hex(data, true) ;//下行命令数据十六进制形式
        confirmCommand.hasResponse = false ;//是否有应答
        confirmCommand.maxSendTimes = 1 ;//命令最大发送次数(当收不到应答时,将重发2次),如果不设置,命令缓存器进行补充设置
        confirmCommand.isSendFirst = true ;//确认命令,优先发送
        confirmCommand.isCachForOffLine = false ;//RTU不在线,命令是否缓存
 
        callback.callback(midRs.reportOrResponse_trueOrFalse);
        return new MidResult[]{midRs, confirmCommand} ;
    }
    /**
     * 执行分析
     * @param bs 
     * @param bsLen字节长度(总包长,包括包头和包尾)
     * @param dataCode
     * @param index
     * @param contentDataEndIndex
     * @param data
     * @throws Exception
     */
    protected void doParse(byte[] bs, int bsLen, String dataCode, Data data) throws Exception {
        DataV1_0_1 dV1 = (DataV1_0_1)data.getSubData() ;
        DataCd01Vo cdData = new DataCd01Vo() ;
        dV1.dataCd01Vo = cdData ;
        
        int index = ProtocolConstantV1_0_1.codeIndex + 1 ;
        
        cdData.dt = "20" + ByteUtil.BCD2String_BE(bs, index, index++)
        + "-" + ByteUtil.BCD2String_BE(bs, index, index++)
        + "-" + ByteUtil.BCD2String_BE(bs, index, index++)
        + " " + ByteUtil.BCD2String_BE(bs, index, index++)
        + ":" + ByteUtil.BCD2String_BE(bs, index, index++)
        + ":" + ByteUtil.BCD2String_BE(bs, index, index) ;
        int[] ymdhms = DateTime.yyyy_MM_dd_HH_MM_SS_2_ymdhmsGroup(cdData.dt) ;
        String yesterday = DateTime.yesterday_yyyy_MM_dd(ymdhms[0], ymdhms[1], ymdhms[2]);
        cdData.dataDt = yesterday ;
        
        index++ ;
        if(!ByteUtilUnsigned.bytesIsAll0xFF(bs, index, 4)){
            //当RTU实次上报时,因未初始化上报的是 0xFFFF
            cdData.totalAmount = ByteUtilUnsigned.bytes2Int_BE(bs, index)/100.0f ;
        }else{
            cdData.totalAmount = 0.0f ;
        }
        
        index += 4 ;
        if(!ByteUtilUnsigned.bytesIsAll0xFF(bs, index, 4)){
            //当RTU实次上报时,因未初始化上报的是 0xFFFF
            cdData.totalAmountPerDay = ByteUtilUnsigned.bytes2Int_BE(bs, index)/100.0f ;
        }else{
            cdData.totalAmountPerDay = 0.0f ;
        }
        
        index += 4 ;
        cdData.volt = ByteUtilUnsigned.byte2Byte(bs, index)/10.0f ;
        
        index += 1 ;
        cdData.signal = 0.0f + ByteUtilUnsigned.bytes2Short_BE(bs, index) ;
        
        index += 2 ;
        byte staAlarm = bs[index] ;
        cdData.valveSta = (byte)(staAlarm & 1) ;
        staAlarm = (byte)(staAlarm >> 2) ;
        cdData.alarmValve = (byte)(staAlarm & 1) ;
        staAlarm = (byte)(staAlarm >> 1) ;
        cdData.alarmMagnetism = (byte)(staAlarm & 1) ;
        staAlarm = (byte)(staAlarm >> 1) ;
        cdData.alarmVolt = (byte)(staAlarm & 1) ;
        
        index++ ;
        cdData.values = new ArrayList<Float>() ;
        for(byte i = 0; (i < (byte)24 && index < (bsLen - 2)); i++){
            if(!ByteUtilUnsigned.bytesIsAll0xFF(bs, index, 2)){
                //当RTU实次上报时,因未初始化上报的是 0xFFFF
                Integer v = ByteUtilUnsigned.bytes2Short_BE(bs, index) ;
                if(v >= Integer.MAX_VALUE){
                    //根据协议,当终端没有记录数据,数据内容是ffff ffff
                    v = 0 ;
                }
                cdData.values.add(v/100.0f) ;
            }else{
                cdData.values.add(0.0f) ;
            }
            index += 2 ;
        }
        
        cdData.gap = 60 ;//根据当前水表实现,密采数据采集间隔是60分钟
    }
}