• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1% Modbus layer test campaign
2
3+ Syntax check
4= Import the modbus layer
5from scapy.contrib.modbus import *
6
7+ Test MBAP
8= MBAP default values
9raw(ModbusADURequest()) == b'\x00\x00\x00\x00\x00\x01\xff'
10
11= MBAP payload length calculation
12raw(ModbusADURequest() / b'\x00\x01\x02') == b'\x00\x00\x00\x00\x00\x04\xff\x00\x01\x02'
13
14= MBAP Guess Payload ModbusPDU01ReadCoilsRequest (simple case)
15p = ModbusADURequest(b'\x00\x00\x00\x00\x00\x06\xff\x01\x00\x00\x00\x01')
16assert isinstance(p.payload, ModbusPDU01ReadCoilsRequest)
17= MBAP Guess Payload ModbusPDU01ReadCoilsResponse
18p = ModbusADUResponse(b'\x00\x00\x00\x00\x00\x04\xff\x01\x01\x01')
19assert isinstance(p.payload, ModbusPDU01ReadCoilsResponse)
20= MBAP Guess Payload ModbusPDU01ReadCoilsError
21p = ModbusADUResponse(b'\x00\x00\x00\x00\x00\x03\xff\x81\x02')
22assert isinstance(p.payload, ModbusPDU01ReadCoilsError)
23
24= MBAP Guess Payload ModbusPDU02ReadDiscreteInputsRequest
25p = ModbusADURequest(b'\x00\x00\x00\x00\x00\x06\xff\x02\x00\x00\x00\x01')
26assert isinstance(p.payload, ModbusPDU02ReadDiscreteInputsRequest)
27= MBAP Guess Payload ModbusPDU02ReadDiscreteInputsResponse
28p = ModbusADUResponse(b'\x00\x00\x00\x00\x00\x04\xff\x02\x01\x00')
29assert isinstance(p.payload, ModbusPDU02ReadDiscreteInputsResponse)
30= MBAP Guess Payload ModbusPDU02ReadDiscreteInputsError
31p = ModbusADUResponse(b'\x00\x00\x00\x00\x00\x03\xff\x82\x01')
32assert isinstance(p.payload, ModbusPDU02ReadDiscreteInputsError)
33
34= MBAP Guess Payload ModbusPDU03ReadHoldingRegistersRequest
35p = ModbusADURequest(b'\x00\x00\x00\x00\x00\x06\xff\x03\x00\x00\x00\x01')
36assert isinstance(p.payload, ModbusPDU03ReadHoldingRegistersRequest)
37= MBAP Guess Payload ModbusPDU03ReadHoldingRegistersResponse
38p = ModbusADUResponse(b'\x00\x00\x00\x00\x00\x05\xff\x03\x02\x00\x00')
39assert isinstance(p.payload, ModbusPDU03ReadHoldingRegistersResponse)
40= MBAP Guess Payload ModbusPDU03ReadHoldingRegistersError
41p = ModbusADUResponse(b'\x00\x00\x00\x00\x00\x03\xff\x83\x01')
42assert isinstance(p.payload, ModbusPDU03ReadHoldingRegistersError)
43
44= MBAP Guess Payload ModbusPDU04ReadInputRegistersRequest
45p = ModbusADURequest(b'\x00\x00\x00\x00\x00\x06\xff\x04\x00\x00\x00\x01')
46assert isinstance(p.payload, ModbusPDU04ReadInputRegistersRequest)
47= MBAP Guess Payload ModbusPDU04ReadInputRegistersResponse
48p = ModbusADUResponse(b'\x00\x00\x00\x00\x00\x05\xff\x04\x02\x00\x00')
49assert isinstance(p.payload, ModbusPDU04ReadInputRegistersResponse)
50= MBAP Guess Payload ModbusPDU04ReadInputRegistersError
51p = ModbusADUResponse(b'\x00\x00\x00\x00\x00\x03\xff\x84\x01')
52assert isinstance(p.payload, ModbusPDU04ReadInputRegistersError)
53
54= MBAP Guess Payload ModbusPDU05WriteSingleCoilRequest
55p = ModbusADURequest(b'\x00\x00\x00\x00\x00\x06\xff\x05\x00\x00\x00\x00')
56assert isinstance(p.payload, ModbusPDU05WriteSingleCoilRequest)
57= MBAP Guess Payload ModbusPDU05WriteSingleCoilResponse
58p = ModbusADUResponse(b'\x00\x00\x00\x00\x00\x06\xff\x05\x00\x00\x00\x00')
59assert isinstance(p.payload, ModbusPDU05WriteSingleCoilResponse)
60= MBAP Guess Payload ModbusPDU05WriteSingleCoilError
61p = ModbusADUResponse(b'\x00\x00\x00\x00\x00\x03\xff\x85\x01')
62assert isinstance(p.payload, ModbusPDU05WriteSingleCoilError)
63
64= MBAP Guess Payload ModbusPDU06WriteSingleRegisterRequest
65p = ModbusADURequest(b'\x00\x00\x00\x00\x00\x06\xff\x06\x00\x00\x00\x00')
66assert isinstance(p.payload, ModbusPDU06WriteSingleRegisterRequest)
67= MBAP Guess Payload ModbusPDU06WriteSingleRegisterResponse
68p = ModbusADUResponse(b'\x00\x00\x00\x00\x00\x06\xff\x06\x00\x00\x00\x00')
69assert isinstance(p.payload, ModbusPDU06WriteSingleRegisterResponse)
70= MBAP Guess Payload ModbusPDU06WriteSingleRegisterError
71p = ModbusADUResponse(b'\x00\x00\x00\x00\x00\x03\xff\x86\x01')
72assert isinstance(p.payload, ModbusPDU06WriteSingleRegisterError)
73
74= MBAP Guess Payload ModbusPDU07ReadExceptionStatusRequest
75p = ModbusADURequest(b'\x00\x00\x00\x00\x00\x02\xff\x07')
76assert isinstance(p.payload, ModbusPDU07ReadExceptionStatusRequest)
77= MBAP Guess Payload ModbusPDU07ReadExceptionStatusResponse
78p = ModbusADUResponse(b'\x00\x00\x00\x00\x00\x03\xff\x07\x00')
79assert isinstance(p.payload, ModbusPDU07ReadExceptionStatusResponse)
80= MBAP Guess Payload ModbusPDU07ReadExceptionStatusError
81p = ModbusADUResponse(b'\x00\x00\x00\x00\x00\x03\xff\x87\x01')
82assert isinstance(p.payload, ModbusPDU07ReadExceptionStatusError)
83
84= MBAP Guess Payload ModbusPDU08DiagnosticsRequest
85p = ModbusADURequest(b'\x00\x00\x00\x00\x00\x06\xff\x08\x00\x00\x00\x00')
86assert isinstance(p.payload, ModbusPDU08DiagnosticsRequest)
87= MBAP Guess Payload ModbusPDU08DiagnosticsResponse
88p = ModbusADUResponse(b'\x00\x00\x00\x00\x00\x06\xff\x08\x00\x00\x00\x00')
89assert isinstance(p.payload, ModbusPDU08DiagnosticsResponse)
90= MBAP Guess Payload ModbusPDU08DiagnosticsError
91p = ModbusADUResponse(b'\x00\x00\x00\x00\x00\x03\xff\x88\x01')
92assert isinstance(p.payload, ModbusPDU08DiagnosticsError)
93
94= MBAP Guess Payload ModbusPDU0BGetCommEventCounterRequest
95p = ModbusADURequest(b'\x00\x00\x00\x00\x00\x02\xff\x0b')
96assert isinstance(p.payload, ModbusPDU0BGetCommEventCounterRequest)
97= MBAP Guess Payload ModbusPDU0BGetCommEventCounterResponse
98p = ModbusADUResponse(b'\x00\x00\x00\x00\x00\x06\xff\x0b\x00\x00\xff\xff')
99assert isinstance(p.payload, ModbusPDU0BGetCommEventCounterResponse)
100= MBAP Guess Payload ModbusPDU0BGetCommEventCounterError
101p = ModbusADUResponse(b'\x00\x00\x00\x00\x00\x03\xff\x8b\x01')
102assert isinstance(p.payload, ModbusPDU0BGetCommEventCounterError)
103
104= MBAP Guess Payload ModbusPDU0CGetCommEventLogRequest
105p = ModbusADURequest(b'\x00\x00\x00\x00\x00\x02\xff\x0c')
106assert isinstance(p.payload, ModbusPDU0CGetCommEventLogRequest)
107= MBAP Guess Payload ModbusPDU0CGetCommEventLogResponse
108p = ModbusADUResponse(b'\x00\x00\x00\x00\x00\x02\xff\x0c\x00\x00\x00\x00\x00\x00\x00')
109assert isinstance(p.payload, ModbusPDU0CGetCommEventLogResponse)
110= MBAP Guess Payload ModbusPDU0CGetCommEventLogError
111p = ModbusADUResponse(b'\x00\x00\x00\x00\x00\x03\xff\x8c\x01')
112assert isinstance(p.payload, ModbusPDU0CGetCommEventLogError)
113
114= MBAP Guess Payload ModbusPDU0FWriteMultipleCoilsRequest
115p = ModbusADURequest(b'\x00\x00\x00\x00\x00\x08\xff\x0f\x00\x00\x00\x01\x01\x00')
116assert isinstance(p.payload, ModbusPDU0FWriteMultipleCoilsRequest)
117= MBAP Guess Payload ModbusPDU0FWriteMultipleCoilsResponse
118p = ModbusADUResponse(b'\x00\x00\x00\x00\x00\x06\xff\x0f\x00\x00\x00\x01')
119assert isinstance(p.payload, ModbusPDU0FWriteMultipleCoilsResponse)
120= MBAP Guess Payload ModbusPDU0FWriteMultipleCoilsError
121p = ModbusADUResponse(b'\x00\x00\x00\x00\x00\x03\xff\x8f\x01')
122assert isinstance(p.payload, ModbusPDU0FWriteMultipleCoilsError)
123
124= MBAP Guess Payload ModbusPDU10WriteMultipleRegistersRequest
125p = ModbusADURequest(b'\x00\x00\x00\x00\x00\t\xff\x10\x00\x00\x00\x01\x02\x00\x00')
126assert isinstance(p.payload, ModbusPDU10WriteMultipleRegistersRequest)
127= MBAP Guess Payload ModbusPDU10WriteMultipleRegistersResponse
128p = ModbusADUResponse(b'\x00\x00\x00\x00\x00\x06\xff\x10\x00\x00\x00\x01')
129assert isinstance(p.payload, ModbusPDU10WriteMultipleRegistersResponse)
130= MBAP Guess Payload ModbusPDU10WriteMultipleRegistersError
131p = ModbusADUResponse(b'\x00\x00\x00\x00\x00\x03\xff\x90\x01')
132assert isinstance(p.payload, ModbusPDU10WriteMultipleRegistersError)
133
134= MBAP Guess Payload ModbusPDU11ReportSlaveIdRequest
135p = ModbusADURequest(b'\x00\x00\x00\x00\x00\x02\xff\x11')
136assert isinstance(p.payload, ModbusPDU11ReportSlaveIdRequest)
137= MBAP Guess Payload ModbusPDU11ReportSlaveIdResponse
138p = ModbusADUResponse(b'\x00\x00\x00\x00\x00\x03\xff\x11\x00')
139assert isinstance(p.payload, ModbusPDU11ReportSlaveIdResponse)
140= MBAP Guess Payload ModbusPDU11ReportSlaveIdError
141p = ModbusADUResponse(b'\x00\x00\x00\x00\x00\x03\xff\x91\x01')
142assert isinstance(p.payload, ModbusPDU11ReportSlaveIdError)
143
144= MBAP Guess Payload ModbusPDU14ReadFileRecordRequest
145p = ModbusADURequest(b'\x00\x00\x00\x00\x00\x03\xff\x14\x00')
146assert isinstance(p.payload, ModbusPDU14ReadFileRecordRequest)
147= MBAP Guess Payload ModbusPDU14ReadFileRecordResponse
148p = ModbusADUResponse(b'\x00\x00\x00\x00\x00\x03\xff\x14\x00')
149assert isinstance(p.payload, ModbusPDU14ReadFileRecordResponse)
150= MBAP Guess Payload ModbusPDU14ReadFileRecordError
151p = ModbusADUResponse(b'\x00\x00\x00\x00\x00\x03\xff\x91\x01')
152assert isinstance(p.payload, ModbusPDU11ReportSlaveIdError)
153
154= MBAP Guess Payload ModbusPDU15WriteFileRecordRequest
155p = ModbusADURequest(b'\x00\x00\x00\x00\x00\x03\xff\x15\x00')
156assert isinstance(p.payload, ModbusPDU15WriteFileRecordRequest)
157= MBAP Guess Payload ModbusPDU15WriteFileRecordResponse
158p = ModbusADUResponse(b'\x00\x00\x00\x00\x00\x03\xff\x15\x00')
159assert isinstance(p.payload, ModbusPDU15WriteFileRecordResponse)
160= MBAP Guess Payload ModbusPDU15WriteFileRecordError
161p = ModbusADUResponse(b'\x00\x00\x00\x00\x00\x03\xff\x95\x01')
162assert isinstance(p.payload, ModbusPDU15WriteFileRecordError)
163
164= MBAP Guess Payload ModbusPDU16MaskWriteRegisterRequest
165p = ModbusADURequest(b'\x00\x00\x00\x00\x00\x08\xff\x16\x00\x00\xff\xff\x00\x00')
166assert isinstance(p.payload, ModbusPDU16MaskWriteRegisterRequest)
167= MBAP Guess Payload ModbusPDU16MaskWriteRegisterResponse
168p = ModbusADUResponse(b'\x00\x00\x00\x00\x00\x08\xff\x16\x00\x00\xff\xff\x00\x00')
169assert isinstance(p.payload, ModbusPDU16MaskWriteRegisterResponse)
170= MBAP Guess Payload ModbusPDU16MaskWriteRegisterError
171p = ModbusADUResponse(b'\x00\x00\x00\x00\x00\x03\xff\x96\x01')
172assert isinstance(p.payload, ModbusPDU16MaskWriteRegisterError)
173
174= MBAP Guess Payload ModbusPDU16MaskWriteRegisterRequest
175p = ModbusADURequest(b'\x00\x00\x00\x00\x00\x08\xff\x16\x00\x00\xff\xff\x00\x00')
176assert isinstance(p.payload, ModbusPDU16MaskWriteRegisterRequest)
177= MBAP Guess Payload ModbusPDU16MaskWriteRegisterResponse
178p = ModbusADUResponse(b'\x00\x00\x00\x00\x00\x08\xff\x16\x00\x00\xff\xff\x00\x00')
179assert isinstance(p.payload, ModbusPDU16MaskWriteRegisterResponse)
180= MBAP Guess Payload ModbusPDU16MaskWriteRegisterError
181p = ModbusADUResponse(b'\x00\x00\x00\x00\x00\x03\xff\x96\x01')
182assert isinstance(p.payload, ModbusPDU16MaskWriteRegisterError)
183
184= MBAP Guess Payload ModbusPDU17ReadWriteMultipleRegistersRequest
185p = ModbusADURequest(b'\x00\x00\x00\x00\x00\r\xff\x17\x00\x00\x00\x01\x00\x00\x00\x01\x02\x00\x00')
186assert isinstance(p.payload, ModbusPDU17ReadWriteMultipleRegistersRequest)
187= MBAP Guess Payload ModbusPDU17ReadWriteMultipleRegistersResponse
188p = ModbusADUResponse(b'\x00\x00\x00\x00\x00\x05\xff\x17\x02\x00\x00')
189assert isinstance(p.payload, ModbusPDU17ReadWriteMultipleRegistersResponse)
190= MBAP Guess Payload ModbusPDU17ReadWriteMultipleRegistersError
191p = ModbusADUResponse(b'\x00\x00\x00\x00\x00\x03\xff\x97\x01')
192assert isinstance(p.payload, ModbusPDU17ReadWriteMultipleRegistersError)
193
194= MBAP Guess Payload ModbusPDU18ReadFIFOQueueRequest
195p = ModbusADURequest(b'\x00\x00\x00\x00\x00\x04\xff\x18\x00\x00')
196assert isinstance(p.payload, ModbusPDU18ReadFIFOQueueRequest)
197= MBAP Guess Payload ModbusPDU18ReadFIFOQueueResponse
198p = ModbusADUResponse(b'\x00\x00\x00\x00\x00\x06\xff\x18\x00\x02\x00\x00')
199assert isinstance(p.payload, ModbusPDU18ReadFIFOQueueResponse)
200= MBAP Guess Payload ModbusPDU18ReadFIFOQueueError
201p = ModbusADUResponse(b'\x00\x00\x00\x00\x00\x03\xff\x98\x01')
202assert isinstance(p.payload, ModbusPDU18ReadFIFOQueueError)
203
204= MBAP Guess Payload ModbusPDU2B0EReadDeviceIdentificationRequest (2 level test)
205p = ModbusADURequest(b'\x00\x00\x00\x00\x00\x04\xff+\x0e\x01\x00')
206assert isinstance(p.payload, ModbusPDU2B0EReadDeviceIdentificationRequest)
207= MBAP Guess Payload ModbusPDU2B0EReadDeviceIdentificationResponse
208p = ModbusADUResponse(b'\x00\x00\x00\x00\x00\x1b\xff+\x0e\x01\x83\x00\x00\x03\x00\x08Pymodbus\x01\x02PM\x02\x031.0')
209assert isinstance(p.payload, ModbusPDU2B0EReadDeviceIdentificationResponse)
210= MBAP Guess Payload ModbusPDU2B0EReadDeviceIdentificationError
211p = ModbusADUResponse(b'\x00\x00\x00\x00\x00\x03\xff\xab\x01')
212assert isinstance(p.payload, ModbusPDU2B0EReadDeviceIdentificationError)
213
214= MBAP Guess Payload Reserved Function Request (Invalid payload)
215p = ModbusADURequest(b'\x00\x00\x00\x00\x00\x02\xff\x5b')
216assert isinstance(p.payload,ModbusPDUReservedFunctionCodeRequest)
217= MBAP Guess Payload Reserved Function Response (Invalid payload)
218p = ModbusADUResponse(b'\x00\x00\x00\x00\x00\x02\xff\x7e')
219assert isinstance(p.payload, ModbusPDUReservedFunctionCodeResponse)
220= MBAP Guess Payload Reserved Function Error (Invalid payload)
221p = ModbusADUResponse(b'\x00\x00\x00\x00\x00\x02\xff\x8a')
222assert isinstance(p.payload, ModbusPDUReservedFunctionCodeError)
223
224= MBAP Guess Payload ModbusPDU02ReadDiscreteInputsResponse
225assert raw(ModbusPDU02ReadDiscreteInputsResponse()) == b'\x02\x01\x00'
226= MBAP Guess Payload ModbusPDU02ReadDiscreteInputsResponse minimal parameters
227assert raw(ModbusPDU02ReadDiscreteInputsResponse(inputStatus=[0x02, 0x01])) == b'\x02\x02\x02\x01'
228= MBAP Guess Payload ModbusPDU02ReadDiscreteInputsRequest dissection
229p = ModbusPDU02ReadDiscreteInputsResponse(b'\x02\x02\x02\x01')
230p.byteCount == 2 and p.inputStatus == [0x02, 0x01]
231
232= ModbusPDU02ReadDiscreteInputsError
233raw(ModbusPDU02ReadDiscreteInputsError()) == b'\x82\x01'
234
235= MBAP Guess Payload User-Defined Function Request (Invalid payload)
236p = ModbusADURequest(b'\x00\x00\x00\x00\x00\x02\xff\x5b')
237assert isinstance(p.payload, ModbusPDUReservedFunctionCodeRequest)
238= MBAP Guess Payload User-Defined Function Response (Invalid payload)
239p = ModbusADUResponse(b'\x00\x00\x00\x00\x00\x02\xff\x7e')
240assert isinstance(p.payload, ModbusPDUReservedFunctionCodeResponse)
241= MBAP Guess Payload User-Defined Function Error (Invalid payload)
242p = ModbusADUResponse(b'\x00\x00\x00\x00\x00\x02\xff\x8a')
243assert isinstance(p.payload, ModbusPDUReservedFunctionCodeError)
244
245+ Test layer binding
246= Destination port
247p = TCP()/ModbusADURequest()
248p[TCP].dport == 502
249
250= Source port
251p = TCP()/ModbusADUResponse()
252p[TCP].sport == 502
253
254+ Test PDU
255* Note on tests cases: dissection/minimal parameters will not be done for packets that does not perform calculation
256# 0x01/0x81 Read Coils --------------------------------------------------------------
257= ModbusPDU01ReadCoilsRequest
258raw(ModbusPDU01ReadCoilsRequest()) == b'\x01\x00\x00\x00\x01'
259= ModbusPDU01ReadCoilsRequest minimal parameters
260raw(ModbusPDU01ReadCoilsRequest(startAddr=16, quantity=2)) == b'\x01\x00\x10\x00\x02'
261= ModbusPDU01ReadCoilsRequest dissection
262p = ModbusPDU01ReadCoilsRequest(b'\x01\x00\x10\x00\x02')
263assert p.startAddr == 16
264assert p.quantity == 2
265
266= ModbusPDU01ReadCoilsResponse
267raw(ModbusPDU01ReadCoilsResponse()) == b'\x01\x01\x00'
268= ModbusPDU01ReadCoilsResponse minimal parameters
269raw(ModbusPDU01ReadCoilsResponse(coilStatus=[0x10]*3)) == b'\x01\x03\x10\x10\x10'
270= ModbusPDU01ReadCoilsResponse dissection
271p = ModbusPDU01ReadCoilsResponse(b'\x01\x03\x10\x10\x10')
272assert p.coilStatus == [16, 16, 16]
273assert p.byteCount == 3
274
275= ModbusPDU01ReadCoilsError
276raw(ModbusPDU01ReadCoilsError()) == b'\x81\x01'
277= ModbusPDU81ReadCoilsError minimal parameters
278raw(ModbusPDU01ReadCoilsError(exceptCode=2)) == b'\x81\x02'
279= ModbusPDU81ReadCoilsError dissection
280p = ModbusPDU01ReadCoilsError(b'\x81\x02')
281assert p.funcCode == 0x81
282assert p.exceptCode == 2
283
284# 0x02/0x82 Read Discrete Inputs Registers ------------------------------------------
285= ModbusPDU02ReadDiscreteInputsRequest
286raw(ModbusPDU02ReadDiscreteInputsRequest()) == b'\x02\x00\x00\x00\x01'
287= ModbusPDU02ReadDiscreteInputsRequest minimal parameters
288raw(ModbusPDU02ReadDiscreteInputsRequest(startAddr=8, quantity=128)) == b'\x02\x00\x08\x00\x80'
289
290= ModbusPDU02ReadDiscreteInputsResponse
291raw(ModbusPDU02ReadDiscreteInputsResponse()) == b'\x02\x01\x00'
292= ModbusPDU02ReadDiscreteInputsResponse minimal parameters
293raw(ModbusPDU02ReadDiscreteInputsResponse(inputStatus=[0x02, 0x01])) == b'\x02\x02\x02\x01'
294= ModbusPDU02ReadDiscreteInputsRequest dissection
295p = ModbusPDU02ReadDiscreteInputsResponse(b'\x02\x02\x02\x01')
296assert p.byteCount == 2
297assert p.inputStatus == [0x02, 0x01]
298
299= ModbusPDU02ReadDiscreteInputsError
300raw(ModbusPDU02ReadDiscreteInputsError()) == b'\x82\x01'
301
302# 0x03/0x83 Read Holding Registers --------------------------------------------------
303= ModbusPDU03ReadHoldingRegistersRequest
304raw(ModbusPDU03ReadHoldingRegistersRequest()) == b'\x03\x00\x00\x00\x01'
305= ModbusPDU03ReadHoldingRegistersRequest minimal parameters
306raw(ModbusPDU03ReadHoldingRegistersRequest(startAddr=2048, quantity=16)) == b'\x03\x08\x00\x00\x10'
307
308= ModbusPDU03ReadHoldingRegistersResponse
309raw(ModbusPDU03ReadHoldingRegistersResponse()) == b'\x03\x02\x00\x00'
310= ModbusPDU03ReadHoldingRegistersResponse minimal parameters
3111==1
312= ModbusPDU03ReadHoldingRegistersResponse dissection
313p = ModbusPDU03ReadHoldingRegistersResponse(b'\x03\x06\x02+\x00\x00\x00d')
314assert p.byteCount == 6
315assert p.registerVal == [555, 0, 100]
316
317= ModbusPDU03ReadHoldingRegistersError
318raw(ModbusPDU03ReadHoldingRegistersError()) == b'\x83\x01'
319
320# 0x04/0x84 Read Input Register -----------------------------------------------------
321= ModbusPDU04ReadInputRegistersRequest
322raw(ModbusPDU04ReadInputRegistersRequest()) == b'\x04\x00\x00\x00\x01'
323
324= ModbusPDU04ReadInputRegistersResponse
325raw(ModbusPDU04ReadInputRegistersResponse()) == b'\x04\x02\x00\x00'
326= ModbusPDU04ReadInputRegistersResponse minimal parameters
327raw(ModbusPDU04ReadInputRegistersResponse(registerVal=[0x01, 0x02])) == b'\x04\x04\x00\x01\x00\x02'
328
329= ModbusPDU04ReadInputRegistersError
330raw(ModbusPDU04ReadInputRegistersError()) == b'\x84\x01'
331
332# 0x05/0x85 Write Single Coil -------------------------------------------------------
333= ModbusPDU05WriteSingleCoilRequest
334raw(ModbusPDU05WriteSingleCoilRequest()) == b'\x05\x00\x00\x00\x00'
335
336= ModbusPDU05WriteSingleCoilResponse
337raw(ModbusPDU05WriteSingleCoilResponse()) == b'\x05\x00\x00\x00\x00'
338
339= ModbusPDU05WriteSingleCoilError
340raw(ModbusPDU05WriteSingleCoilError()) == b'\x85\x01'
341
342# 0x06/0x86 Write Single Register ---------------------------------------------------
343= ModbusPDU06WriteSingleRegisterRequest
344raw(ModbusPDU06WriteSingleRegisterRequest()) == b'\x06\x00\x00\x00\x00'
345
346= ModbusPDU06WriteSingleRegisterResponse
347raw(ModbusPDU06WriteSingleRegisterResponse()) == b'\x06\x00\x00\x00\x00'
348
349= ModbusPDU06WriteSingleRegisterError
350raw(ModbusPDU06WriteSingleRegisterError()) == b'\x86\x01'
351
352# 0x07/0x87 Read Exception Status (serial line only) --------------------------------
353= ModbusPDU07ReadExceptionStatusRequest
354raw(ModbusPDU07ReadExceptionStatusRequest()) == b'\x07'
355
356= ModbusPDU07ReadExceptionStatusResponse
357raw(ModbusPDU07ReadExceptionStatusResponse()) == b'\x07\x00'
358
359= ModbusPDU07ReadExceptionStatusError
360raw(ModbusPDU07ReadExceptionStatusError()) == b'\x87\x01'
361
362# 0x08/0x88 Diagnostics (serial line only) ------------------------------------------
363= ModbusPDU08DiagnosticsRequest
364raw(ModbusPDU08DiagnosticsRequest())
365= ModbusPDU08DiagnosticsRequest minimal parameters
366raw(ModbusPDU08DiagnosticsRequest(data=[0x1234])) == b'\x08\x00\x00\x12\x34'
367
368= ModbusPDU08DiagnosticsResponse
369raw(ModbusPDU08DiagnosticsResponse()) == b'\x08\x00\x00\x00\x00'
370= ModbusPDU08DiagnosticsResponse minimal parameters
371raw(ModbusPDU08DiagnosticsResponse(data=[0x1234])) == b'\x08\x00\x00\x12\x34'
372
373= ModbusPDU08DiagnosticsError
374raw(ModbusPDU08DiagnosticsError()) == b'\x88\x01'
375
376# 0x0b Get Comm Event Counter: serial line only -------------------------------------
377= ModbusPDU0BGetCommEventCounterRequest
378raw(ModbusPDU0BGetCommEventCounterRequest()) == b'\x0b'
379
380= ModbusPDU0BGetCommEventCounterResponse
381raw(ModbusPDU0BGetCommEventCounterResponse()) == b'\x0b\x00\x00\xff\xff'
382
383= ModbusPDU0BGetCommEventCounterError
384raw(ModbusPDU0BGetCommEventCounterError()) == b'\x8b\x01'
385
386# 0x0c Get Comm Event Log: serial line only -----------------------------------------
387= ModbusPDU0CGetCommEventLogRequest
388raw(ModbusPDU0CGetCommEventLogRequest()) == b'\x0c'
389
390= ModbusPDU0CGetCommEventLogResponse
391raw(ModbusPDU0CGetCommEventLogResponse()) == b'\x0c\x08\x00\x00\x01\x08\x01\x21\x20\x00'
392
393= ModbusPDU0CGetCommEventLogError
394raw(ModbusPDU0CGetCommEventLogError()) == b'\x8c\x01'
395
396# 0x0f/0x8f Write Multiple Coils ----------------------------------------------------
397= ModbusPDU0FWriteMultipleCoilsRequest
398raw(ModbusPDU0FWriteMultipleCoilsRequest())
399= ModbusPDU0FWriteMultipleCoilsRequest minimal parameters
400raw(ModbusPDU0FWriteMultipleCoilsRequest(outputsValue=[0x01, 0x01])) == b'\x0f\x00\x00\x00\x01\x02\x01\x01'
401
402= ModbusPDU0FWriteMultipleCoilsResponse
403raw(ModbusPDU0FWriteMultipleCoilsResponse()) == b'\x0f\x00\x00\x00\x01'
404
405= ModbusPDU0FWriteMultipleCoilsError
406raw(ModbusPDU0FWriteMultipleCoilsError()) == b'\x8f\x01'
407
408# 0x10/0x90 Write Multiple Registers ----------------------------------------------------
409= ModbusPDU10WriteMultipleRegistersRequest
410raw(ModbusPDU10WriteMultipleRegistersRequest()) == b'\x10\x00\x00\x00\x01\x02\x00\x00'
411= ModbusPDU10WriteMultipleRegistersRequest minimal parameters
412raw(ModbusPDU10WriteMultipleRegistersRequest(outputsValue=[0x0001, 0x0002])) == b'\x10\x00\x00\x00\x02\x04\x00\x01\x00\x02'
413
414= ModbusPDU10WriteMultipleRegistersResponse
415raw(ModbusPDU10WriteMultipleRegistersResponse()) == b'\x10\x00\x00\x00\x01'
416
417= ModbusPDU10WriteMultipleRegistersError
418raw(ModbusPDU10WriteMultipleRegistersError()) == b'\x90\x01'
419
420# 0x11/91 Report Slave ID: serial line only ----------------------------------------
421= ModbusPDU11ReportSlaveIdRequest
422raw(ModbusPDU11ReportSlaveIdRequest()) == b'\x11'
423
424= ModbusPDU11ReportSlaveIdResponse minimal parameters
425raw(ModbusPDU11ReportSlaveIdResponse(byteCount=3, slaveId="ID")) == b'\x11\x03\x49\x44\x00'
426
427= ModbusPDU11ReportSlaveIdError
428raw(ModbusPDU11ReportSlaveIdError()) == b'\x91\x01'
429
430# 0x14/944 Read File Record ---------------------------------------------------------
431= ModbusPDU14ReadFileRecordRequest len parameters
432p = raw(ModbusPDU14ReadFileRecordRequest()/ModbusReadFileSubRequest()/ModbusReadFileSubRequest())
433assert p == b'\x14\x0e\x06\x00\x01\x00\x00\x00\x01\x06\x00\x01\x00\x00\x00\x01'
434= ModbusPDU14ReadFileRecordRequest minimal parameters
435p = raw(ModbusPDU14ReadFileRecordRequest()/ModbusReadFileSubRequest(fileNumber=4, recordNumber=1, recordLength=2)/ModbusReadFileSubRequest(fileNumber=3, recordNumber=9, recordLength=2))
436assert p == b'\x14\x0e\x06\x00\x04\x00\x01\x00\x02\x06\x00\x03\x00\t\x00\x02'
437= ModbusPDU14ReadFileRecordRequest dissection
438p = ModbusPDU14ReadFileRecordRequest(b'\x14\x0e\x06\x00\x04\x00\x01\x00\x02\x06\x00\x03\x00\t\x00\x02')
439assert isinstance(p.payload, ModbusReadFileSubRequest)
440assert isinstance(p.payload.payload, ModbusReadFileSubRequest)
441
442= ModbusPDU14ReadFileRecordResponse minimal parameters
443raw(ModbusPDU14ReadFileRecordResponse()/ModbusReadFileSubResponse(recData=[0x0dfe, 0x0020])/ModbusReadFileSubResponse(recData=[0x33cd, 0x0040])) == b'\x14\x0c\x05\x06\r\xfe\x00 \x05\x063\xcd\x00@'
444= ModbusPDU14ReadFileRecordResponse dissection
445p = ModbusPDU14ReadFileRecordResponse(b'\x14\x0c\x05\x06\r\xfe\x00 \x05\x063\xcd\x00@')
446assert isinstance(p.payload, ModbusReadFileSubResponse)
447assert isinstance(p.payload.payload, ModbusReadFileSubResponse)
448
449= ModbusPDU14ReadFileRecordError
450raw(ModbusPDU14ReadFileRecordError()) == b'\x94\x01'
451
452# 0x15/0x95 Write File Record -------------------------------------------------------
453= ModbusPDU15WriteFileRecordRequest minimal parameters
454raw(ModbusPDU15WriteFileRecordRequest()/ModbusWriteFileSubRequest(fileNumber=4, recordNumber=7, recordData=[0x06af, 0x04be, 0x100d])) == b'\x15\r\x06\x00\x04\x00\x07\x00\x03\x06\xaf\x04\xbe\x10\r'
455= ModbusPDU15WriteFileRecordRequest dissection
456p = ModbusPDU15WriteFileRecordRequest(b'\x15\x0d\x06\x00\x04\x00\x07\x00\x03\x06\xaf\x04\xbe\x10\r')
457assert isinstance(p.payload, ModbusWriteFileSubRequest)
458assert p.payload.recordLength == 3
459
460= ModbusPDU15WriteFileRecordResponse minimal parameters
461raw(ModbusPDU15WriteFileRecordResponse()/ModbusWriteFileSubResponse(fileNumber=4, recordNumber=7, recordData=[0x06af, 0x04be, 0x100d])) == b'\x15\r\x06\x00\x04\x00\x07\x00\x03\x06\xaf\x04\xbe\x10\r'
462= ModbusPDU15WriteFileRecordResponse dissection
463p = ModbusPDU15WriteFileRecordResponse(b'\x15\x0d\x06\x00\x04\x00\x07\x00\x03\x06\xaf\x04\xbe\x10\r')
464assert isinstance(p.payload, ModbusWriteFileSubResponse)
465assert p.payload.recordLength == 3
466
467= ModbusPDU15WriteFileRecordError
468raw(ModbusPDU15WriteFileRecordError()) == b'\x95\x01'
469
470# 0x16/0x96 Mask Write Register -----------------------------------------------------
471= ModbusPDU16MaskWriteRegisterRequest
472raw(ModbusPDU16MaskWriteRegisterRequest()) == b'\x16\x00\x00\xff\xff\x00\x00'
473
474= ModbusPDU16MaskWriteRegisterResponse
475raw(ModbusPDU16MaskWriteRegisterResponse()) == b'\x16\x00\x00\xff\xff\x00\x00'
476
477= ModbusPDU16MaskWriteRegisterError
478raw(ModbusPDU16MaskWriteRegisterError()) == b'\x96\x01'
479
480# 0x17/0x97 Read/Write Multiple Registers -------------------------------------------
481= ModbusPDU17ReadWriteMultipleRegistersRequest
482raw(ModbusPDU17ReadWriteMultipleRegistersRequest()) == b'\x17\x00\x00\x00\x01\x00\x00\x00\x01\x02\x00\x00'
483= ModbusPDU17ReadWriteMultipleRegistersRequest minimal parameters
484raw(ModbusPDU17ReadWriteMultipleRegistersRequest(writeRegistersValue=[0x0001, 0x0002])) == b'\x17\x00\x00\x00\x01\x00\x00\x00\x02\x04\x00\x01\x00\x02'
485= ModbusPDU17ReadWriteMultipleRegistersRequest dissection
486p = ModbusPDU17ReadWriteMultipleRegistersRequest(b'\x17\x00\x00\x00\x01\x00\x00\x00\x02\x04\x00\x01\x00\x02')
487assert p.byteCount == 4
488assert p.writeQuantityRegisters == 2
489
490= ModbusPDU17ReadWriteMultipleRegistersResponse
491raw(ModbusPDU17ReadWriteMultipleRegistersResponse()) == b'\x17\x02\x00\x00'
492= ModbusPDU17ReadWriteMultipleRegistersResponse minimal parameters
493raw(ModbusPDU17ReadWriteMultipleRegistersResponse(registerVal=[1,2,3])) == b'\x17\x06\x00\x01\x00\x02\x00\x03'
494= ModbusPDU17ReadWriteMultipleRegistersResponse dissection
495raw(ModbusPDU17ReadWriteMultipleRegistersResponse(b'\x17\x02\x00\x01')) == b'\x17\x02\x00\x01'
496
497= ModbusPDU17ReadWriteMultipleRegistersError
498raw(ModbusPDU17ReadWriteMultipleRegistersError()) == b'\x97\x01'
499
500# 0x18/0x88 Read FIFO Queue ---------------------------------------------------------
501= ModbusPDU18ReadFIFOQueueRequest
502raw(ModbusPDU18ReadFIFOQueueRequest()) == b'\x18\x00\x00'
503
504= ModbusPDU18ReadFIFOQueueResponse
505= ModbusPDU18ReadFIFOQueueResponse
506raw(ModbusPDU18ReadFIFOQueueResponse()) == b'\x18\x00\x02\x00\x00'
507= ModbusPDU18ReadFIFOQueueResponse minimal parameters
508raw(ModbusPDU18ReadFIFOQueueResponse(FIFOVal=[0x0001, 0x0002, 0x0003])) == b'\x18\x00\x08\x00\x03\x00\x01\x00\x02\x00\x03'
509= ModbusPDU18ReadFIFOQueueResponse dissection
510p = ModbusPDU18ReadFIFOQueueResponse(b'\x18\x00\x08\x00\x03\x00\x01\x00\x02\x00\x03')
511assert p.byteCount == 8
512assert p.FIFOCount == 3
513
514= ModbusPDU18ReadFIFOQueueError
515raw(ModbusPDU18ReadFIFOQueueError()) == b'\x98\x01'
516
517# 0x2b encapsulated Interface Transport ---------------------------------------------
518# 0x2b 0xOD CANopen General Reference (out of the main specification) ---------------
519
520# 0x2b 0xOE Read Device Information -------------------------------------------------
521= ModbusPDU2B0EReadDeviceIdentificationRequest
522raw(ModbusPDU2B0EReadDeviceIdentificationRequest()) == b'+\x0e\x01\x00'
523
524= ModbusPDU2B0EReadDeviceIdentificationResponse
525raw(ModbusPDU2B0EReadDeviceIdentificationResponse()) == b'+\x0e\x04\x01\x00\x00\x00'
526= ModbusPDU2B0EReadDeviceIdentificationResponse complete response
527p = raw(ModbusPDU2B0EReadDeviceIdentificationResponse(objCount=2)/ModbusObjectId(id=0, value="Obj1")/ModbusObjectId(id=1, value="Obj2"))
528assert p == b'+\x0e\x04\x01\x00\x00\x02\x00\x04Obj1\x01\x04Obj2'
529= ModbusPDU2B0EReadDeviceIdentificationResponse dissection
530p = ModbusPDU2B0EReadDeviceIdentificationResponse(b'+\x0e\x01\x83\x00\x00\x03\x00\x08Pymodbus\x01\x02PM\x02\x031.0')
531assert p.payload.payload.payload.id == 2
532assert p.payload.payload.id == 1
533assert p.payload.id == 0
534
535= ModbusPDU2B0EReadDeviceIdentificationError
536raw(ModbusPDU2B0EReadDeviceIdentificationError()) == b'\xab\x01'
537
538= Modbus test for payload subfield
539# GH4112
540pkt = ModbusPDUUserDefinedFunctionCodeRequest(b'M\x00\x05\x00\n')
541pkt = next(iter(pkt))
542assert pkt.mb_payload == b'\x00\x05\x00\n'
543
544