Skip to content

Commit 85d9f13

Browse files
committed
Fix Packet::isCompleteLengthRTU to differentiate fix sized response packets from variable size function code responses
1 parent 48c46a8 commit 85d9f13

File tree

2 files changed

+33
-9
lines changed

2 files changed

+33
-9
lines changed

CHANGELOG.md

+4
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,10 @@ All notable changes to this project will be documented in this file.
44
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
55
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
66

7+
# [3.1.1] - 2023-01-25
8+
9+
* Fixed `Packet::isCompleteLengthRTU()` to differentiate fix sized function code responses from variable sized responses.
10+
711
# [3.1.0] - 2022-10-16
812

913
* Added `Packet::isCompleteLengthRTU()` to help checking if packet is complete RTU packet. Helps when receiving fragmented packets.

src/Utils/Packet.php

+29-9
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
use ModbusTcpClient\Network\IOException;
88
use ModbusTcpClient\Packet\ErrorResponse;
9+
use ModbusTcpClient\Packet\ModbusPacket;
910

1011
final 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

Comments
 (0)