66
77use ModbusTcpClient \Network \IOException ;
88use ModbusTcpClient \Packet \ErrorResponse ;
9+ use ModbusTcpClient \Packet \ModbusPacket ;
910
1011final class Packet
1112{
@@ -39,8 +40,8 @@ public static function isCompleteLength(string|null $binaryData): bool
3940 }
4041
4142 /**
42- * isCompleteLengthRTU checks if binary string is complete modbus RTU packet
43- * NB: this function works only for MODBUS RTU packets
43+ * isCompleteLengthRTU checks if binary string is complete modbus RTU response packet
44+ * NB: this function works only for MODBUS RTU response packets
4445 *
4546 * @param string|null $binaryData binary string to be checked
4647 * @return bool true if data is actual error packet
@@ -52,17 +53,36 @@ public static function isCompleteLengthRTU(string|null $binaryData): bool
5253 if ($ length < 5 ) {
5354 return false ;
5455 }
55- if ((ord ($ binaryData [1 ]) & ErrorResponse::EXCEPTION_BITMASK ) > 0 ) { // seems to be error response
56+ $ functionCode = ord ($ binaryData [1 ]);
57+ if (($ functionCode & ErrorResponse::EXCEPTION_BITMASK ) > 0 ) { // seems to be error response
5658 return true ;
5759 }
58- // if it is not error response then 3rd byte contains data length in bytes
60+ switch ($ functionCode ) {
61+ case ModbusPacket::READ_COILS : //
62+ case ModbusPacket::READ_INPUT_DISCRETES : //
63+ case ModbusPacket::READ_HOLDING_REGISTERS : //
64+ case ModbusPacket::READ_INPUT_REGISTERS : //
65+ case ModbusPacket::READ_WRITE_MULTIPLE_REGISTERS : //
66+ // if it is not error response then 3rd byte contains data length in bytes
5967
60- // trailing 3 bytes are = unit id + function code + data length in bytes
61- // next is N bytes of data that should match 3rd byte value
62- // and 2 bytes for CRC
63- // so adding these number is what complete packet would be
64- $ expectedLength = 3 + ord ($ binaryData [2 ]) + 2 ;
68+ // trailing 3 bytes are = unit id (1) + function code (1) + data length in bytes (1) + (N)
69+ // next is N bytes of data that should match 3rd byte value
70+ $ responseBytesLen = 3 + ord ($ binaryData [2 ]);
71+ break ;
72+ case ModbusPacket::WRITE_SINGLE_COIL : // unit id (1) + function code (1) + start address (2) + coil data (2)
73+ case ModbusPacket::WRITE_SINGLE_REGISTER : // unit id (1) + function code (1) + start address (2) + register data (2)
74+ case ModbusPacket::WRITE_MULTIPLE_COILS : // unit id (1) + function code (1) + start address (2) + count of coils written (2)
75+ case ModbusPacket::WRITE_MULTIPLE_REGISTERS : // unit id (1) + function code (1) + start address (2) + count of registers written (2)
76+ $ responseBytesLen = 6 ;
77+ break ;
78+ case ModbusPacket::MASK_WRITE_REGISTER :
79+ $ responseBytesLen = 8 ; // unit id (1) + function code (1) + start address (2) + AND mask (2) + OR mask (2)
80+ break ;
81+ default :
82+ throw new IOException ('can not determine complete length for unsupported modbus function code ' );
83+ }
6584
85+ $ expectedLength = $ responseBytesLen + 2 ; // and 2 bytes for CRC
6686 if ($ length > $ expectedLength ) {
6787 throw new IOException ('packet length more bytes than expected ' );
6888 }
0 commit comments