From 1b215f991c7e4d5bae176972f708672854a7ebcb Mon Sep 17 00:00:00 2001 From: Martti T Date: Thu, 15 Jun 2023 11:32:58 +0300 Subject: [PATCH] debug page for writing registers, similar to index.php which is for reading registers (#148) --- examples/index_write.php | 314 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 314 insertions(+) create mode 100644 examples/index_write.php diff --git a/examples/index_write.php b/examples/index_write.php new file mode 100644 index 0000000..a08ba8e --- /dev/null +++ b/examples/index_write.php @@ -0,0 +1,314 @@ + 255) { + $error = "valid range of uint8 is 0 to 255"; + } else { + $v = Types::toByte($value); + if ($endianess & Endian::BIG_ENDIAN) { + $v = "\x00" . $v; + } else { + $v = $v . "\x00"; + } + } + break; + case 'int8': + $value = (int)$value; + if ($value < -128 || $value > 127) { + $error = "valid range of int8 is -128 to 127"; + } else { + $v = Types::toByte($value); + } + if ($endianess & Endian::BIG_ENDIAN) { + $v = "\x00" . $v; + } else { + $v = $v . "\x00"; + } + break; + case 'uint16': + $value = (int)$value; + if ($value < 0 || $value > 65535) { + $error = "valid range of uint16 is 0 to 65535"; + } else { + $v = Types::toUint16($value); + } + break; + case 'int16': + $value = (int)$value; + if ($value < -32768 || $value > 32767) { + $error = "valid range of uint16 is -32768 to 32767"; + } else { + $v = Types::toInt16($value); + } + break; + case 'uint32': + $value = (int)$value; + if ($value < 0 || $value > 4294967295) { + $error = "valid range of uint32 is 0 to 4294967295"; + } else { + $v = Types::toUint32($value); + } + break; + case 'int32': + $value = (int)$value; + if ($value < -2147483648 || $value > 2147483647) { + $error = "valid range of int32 is -2147483648 to 2147483647"; + } else { + $v = Types::toInt32($value); + } + break; + case 'float32': + $value = (float)$value; + if ($value < -3.4e+38 || $value > 3.4e+38) { + $error = "valid range of float32 is -3.4e+38 to 3.4e+38"; + } else { + $v = Types::toReal($value); + } + break; + case 'uint64': + $value = (int)$value; + if ($value < 0 || $value > 9223372036854775807) { + $error = "valid range of uint64 is 0 to 9223372036854775807"; + } else { + $v = Types::toUint64($value); + } + break; + case 'int64': + $value = (int)$value; + if ($value < 0 || $value > 9223372036854775807) { + $error = "valid range of int64 is -9223372036854775808 to 9223372036854775807"; + } else { + $v = Types::toInt64($value); + } + break; + case 'float64': + $value = (double)$value; + if ($value < 1.7E-308 || $value > 1.7E+308) { + $error = "valid range of float64 is 1.7E-308 to 1.7E+308"; + } else { + $v = Types::toDouble($value); + } + break; + default: + $error = "invalid data type"; +} + +$startTime = round(microtime(true) * 1000, 3); +if ($_SERVER['REQUEST_METHOD'] === 'POST' && $v !== null) { + + $log = []; + + $builder = BinaryStreamConnection::getBuilder() + ->setConnectTimeoutSec(1.5) // timeout when establishing connection to the server + ->setWriteTimeoutSec(1.0) // timeout when writing/sending packet to the server + ->setReadTimeoutSec(1.0); // timeout when waiting response from server + + $protocolType = "Modbus TCP"; + if ($isRTU) { + $protocolType = "Modbus RTU"; + $builder->setIsCompleteCallback(static function ($binaryData, $streamIndex): bool { + return Packet::isCompleteLengthRTU($binaryData); + }); + } + + if ($isSerialDevice) { + $builder->setUri($deviceURI) + ->setProtocol('serial') + // delay this is crucial for some serial devices and delay needs to be long as 100ms (depending on the quantity) + // or you will experience read errors ("stream_select interrupted") or invalid CRCs + ->setDelayRead(100_000); // 100 milliseconds + } else { + $builder->setPort($port)->setHost($ip); + } + + $connection = $builder->build(); + $packet = new WriteMultipleRegistersRequest($startAddress, [$v], $unitId); + if ($isRTU) { + $packet = RtuConverter::toRtu($packet); + $log[] = 'Modbus RTU Packet to be sent (in hex): ' . unpack('H*', $packet)[1]; + } else { + $log[] = 'Modbus TCP Packet to be sent (in hex): ' . $packet->toHex(); + } + try { + $binaryData = $connection->connect()->sendAndReceive($packet); + + $log[] = 'Binary received (in hex): ' . unpack('H*', $binaryData)[1]; + } catch (Exception $exception) { + $result = null; + $log[] = 'An exception occurred'; + $log[] = $exception->getMessage(); + $log[] = $exception->getTraceAsString(); + } finally { + $connection->close(); + } +} +$elapsed = round(microtime(true) * 1000) - $startTime; + +?> +

Example Modbus TCP/RTU Write Multiple Registers (FC=16)

+
+ Modbus TCP or RTU:
+ "; + } else { + echo "IP:
"; + echo "Port:
"; + } ?> + UnitID (SlaveID):
+ Address: (NB: does your modbus server + documentation uses + `0` based addressing or `1` based?)
+ +
+ Endianess:
+ Data type:
+ Value: + )
"; + } ?> + +
+ +
+ +

Debug info

+
+
+
+Time ms +
+Page generated: