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