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
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
package com.dy.testClient.tcpClient;
 
import com.dy.common.mw.protocol.p206V1_0_0.CommonV1_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.threadPool.ThreadPool;
import com.dy.common.util.ByteUtil;
import com.dy.testClient.ServerProperties;
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 ;
 
    public int sendTimes = 0 ;//发送数据次数
    public int heartbeatTimes = 0 ;//上报心跳次数
 
    public boolean isOver = false ;
 
    public MyThreadJob(){
    }
    public MyThreadJob(String rtuAddr, String serverIp, Integer serverPort){
        this.rtuAddr = rtuAddr ;
        this.serverIp = serverIp ;
        this.serverPort = serverPort ;
    }
 
    @Override
    public void execute() throws Exception {
        log.info("RTU" + rtuAddr + "开始任务");
        if(session != null){
            log.info("RTU" + rtuAddr + "将要执行" + ServerProperties.sendTimes + "轮次任务,当前轮次是" + sendTimes);
            if(sendTimes <= ServerProperties.sendTimes){
                sendDataOfP206V1_0_0() ;
            }else{
                this.jobOver() ;
            }
        }
    }
 
    private void sendDataOfP206V1_0_0(){
        try{
            if(heartbeatTimes >= ServerProperties.heartbeatTimes){
                heartbeatTimes = 0 ;
                this.sendReportData() ;
                TcpClUnit.clientSendData();
                sendTimes++ ;
            }else{
                this.sendHeartbeat() ;
                TcpClUnit.clientSendData();
                heartbeatTimes++ ;
            }
        }catch(Exception e){
            e.printStackTrace();
        }
    }
    private void sendHeartbeat(){
        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(){
        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(){
        session.closeOnFlush() ;
        this.isOver = true ;
        TcpClUnit.clientOver() ;
    }
 
    /**
     * 构造心跳数据
     * @return 字节数组
     * @throws Exception 异常
     */
    public byte[] createHeartbeat( ) 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)0) ;//控制域功能码:确认 认可
 
        index++ ;
        GlCreate.createRtuAddr(this.rtuAddr, bsHead, index);
        index += 5 ;
 
        ByteUtil.hex2Bytes("02", bsHead, index) ;
 
        byte[] bs = new byte[1] ;
        bs[0] = (byte)0xF2 ;//数据域: 1 个字节,F0 登录, F1 退出登录,F2 在线保持。
 
        bytes = ByteUtil.bytesMerge(bsHead, bs) ;
 
        GlCreate.createLen(bytes);//长度放字节数组中
 
        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 ;
    }
 
 
 
    @Override
    public void destroy() {
    }
 
    @Override
    public boolean isDestroy() {
        return false;
    }
 
 
}