1 Star 0 Fork 2

tonyang / modbus-tcp-client

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
Packet.php 3.88 KB
一键复制 编辑 原始数据 按行查看 历史
<?php
declare(strict_types=1);
namespace ModbusTcpClient\Utils;
use ModbusTcpClient\Network\IOException;
use ModbusTcpClient\Packet\ErrorResponse;
use ModbusTcpClient\Packet\ModbusPacket;
final class Packet
{
private function __construct()
{
// no access, this is an utility class
}
/**
* isCompleteLength checks if binary string is complete modbus TCP packet
* NB: this function works only for MODBUS TCP packets
*
* @param string|null $binaryData binary string to be checked
* @return bool true if data is actual modbus TCP packet
*/
public static function isCompleteLength(string|null $binaryData): bool
{
// minimal amount is 9 bytes (header + function code + 1 byte of something ala error code)
$length = strlen($binaryData);
if ($length < 9) {
return false;
}
// modbus header 6 bytes are = transaction id + protocol id + length of PDU part.
// so adding these number is what complete packet would be
$expectedLength = 6 + unpack('n', ($binaryData[4] . $binaryData[5]))[1];
if ($length > $expectedLength) {
throw new IOException('packet length more bytes than expected');
}
return $length === $expectedLength;
}
/**
* isCompleteLengthRTU checks if binary string is complete modbus RTU response packet
* NB: this function works only for MODBUS RTU response packets
*
* @param string|null $binaryData binary string to be checked
* @return bool true if data is actual error packet
*/
public static function isCompleteLengthRTU(string|null $binaryData): bool
{
// minimal RTU packet length is 5 bytes (1 byte unit id + 1 byte function code + 1 byte of error code or byte length + 2 bytes for CRC)
$length = strlen($binaryData);
if ($length < 5) {
return false;
}
$functionCode = ord($binaryData[1]);
if (($functionCode & ErrorResponse::EXCEPTION_BITMASK) > 0) { // seems to be error response
return true;
}
switch ($functionCode) {
case ModbusPacket::READ_COILS: //
case ModbusPacket::READ_INPUT_DISCRETES: //
case ModbusPacket::READ_HOLDING_REGISTERS: //
case ModbusPacket::READ_INPUT_REGISTERS: //
case ModbusPacket::READ_WRITE_MULTIPLE_REGISTERS: //
// if it is not error response then 3rd byte contains data length in bytes
// trailing 3 bytes are = unit id (1) + function code (1) + data length in bytes (1) + (N)
// next is N bytes of data that should match 3rd byte value
$responseBytesLen = 3 + ord($binaryData[2]);
break;
case ModbusPacket::WRITE_SINGLE_COIL: // unit id (1) + function code (1) + start address (2) + coil data (2)
case ModbusPacket::WRITE_SINGLE_REGISTER: // unit id (1) + function code (1) + start address (2) + register data (2)
case ModbusPacket::WRITE_MULTIPLE_COILS: // unit id (1) + function code (1) + start address (2) + count of coils written (2)
case ModbusPacket::WRITE_MULTIPLE_REGISTERS: // unit id (1) + function code (1) + start address (2) + count of registers written (2)
$responseBytesLen = 6;
break;
case ModbusPacket::MASK_WRITE_REGISTER:
$responseBytesLen = 8; // unit id (1) + function code (1) + start address (2) + AND mask (2) + OR mask (2)
break;
default:
throw new IOException('can not determine complete length for unsupported modbus function code');
}
$expectedLength = $responseBytesLen + 2; // and 2 bytes for CRC
if ($length > $expectedLength) {
throw new IOException('packet length more bytes than expected');
}
return $length === $expectedLength;
}
}
1
https://gitee.com/xuxiaowu/modbus-tcp-client.git
git@gitee.com:xuxiaowu/modbus-tcp-client.git
xuxiaowu
modbus-tcp-client
modbus-tcp-client
master

搜索帮助