From 5f069276eb5f983e507d8a82fdbd5cf3fba56083 Mon Sep 17 00:00:00 2001 From: John Long Date: Fri, 14 Jun 2013 07:43:00 -0500 Subject: [PATCH] 0.6 release --- Phpmodbus/IecType.php | 12 +- Phpmodbus/ModbusMaster.php | 1810 +++++++++-------- Phpmodbus/PhpType.php | 6 +- examples/example_fc2.php | 26 + examples/example_fc6.php | 26 + tests/Codesys/DEFAULT.DFR | Bin 0 -> 445 bytes tests/Codesys/TEST.EXP | 256 +++ tests/Codesys/_make_exp.cmd | 15 + tests/Codesys/test.SDB | Bin 0 -> 72 bytes tests/Codesys/test.SYM | 4 + tests/Codesys/test.pro | Bin 0 -> 34020 bytes tests/Codesys/test00002ed2r.ci | Bin 0 -> 35661 bytes tests/Codesys/test00002ed2r.ri | Bin 0 -> 22479 bytes tests/IecType/output/test.iecByte.php.html | 1 + tests/IecType/output/test.iecDInt.php.html | 1 + tests/IecType/output/test.iecInt.php.html | 1 + tests/IecType/output/test.iecReal.php.html | 12 + tests/IecType/ref/test.iecReal.php.html | 24 +- tests/IecType/test.iecReal.php | 2 +- .../output/test.tcp.fc16fc3.php.html | 72 + .../output/test.tcp.fc26.php.html | 1 + ...test.tcp.socket_protocol_mismatch.php.html | 1 + .../output/test.udp.fc16fc3.php.html | 72 + .../output/test.udp.fc26.php.html | 1 + ...test.tcp.socket_protocol_mismatch.php.html | 8 +- .../test.tcp.socket_protocol_mismatch.php | 10 +- .../output/test.fc16fc3.php.html | 72 + .../ModbusMasterTcp/output/test.fc26.php.html | 1 + .../output/test.fc15fc1.php.html | 66 + .../output/test.fc16fc3.php.html | 72 + .../output/test.fc16fc3bind.php.html | 72 + .../ModbusMasterUdp/output/test.fc2.php.html | 7 + .../ModbusMasterUdp/output/test.fc26.php.html | 1 + .../output/test.fc26bind.php.html | 1 + .../output/test.fc6fc3.php.html | 5 + .../ModbusMasterUdp/ref/test.fc15fc1.php.html | 66 + .../ModbusMasterUdp/ref/test.fc16fc3.php.html | 2 +- tests/ModbusMasterUdp/ref/test.fc2.php.html | 7 + .../ModbusMasterUdp/ref/test.fc6fc3.php.html | 5 + tests/ModbusMasterUdp/test.fc15fc1.php | 10 +- tests/ModbusMasterUdp/test.fc2.php | 14 + tests/ModbusMasterUdp/test.fc6fc3.php | 15 + .../PhpType/output/test.bytes2mixed.php.html | 1 + tests/PhpType/output/test.bytes2real.php.html | 1 + .../output/test.bytes2signedint.php.html | 1 + .../PhpType/output/test.bytes2string.php.html | 1 + .../output/test.bytes2unsignedint.php.html | 6 + .../output/test.strangearray.size.php.html | 1 + .../test.strangearray.textarray.php.html | 1 + tests/config.bat | 2 +- tests/config.php | 5 +- tutorials/Phpmodbus/Phpmodbus.pkg | 23 +- 52 files changed, 1976 insertions(+), 843 deletions(-) create mode 100644 examples/example_fc2.php create mode 100644 examples/example_fc6.php create mode 100644 tests/Codesys/DEFAULT.DFR create mode 100644 tests/Codesys/TEST.EXP create mode 100644 tests/Codesys/_make_exp.cmd create mode 100644 tests/Codesys/test.SDB create mode 100644 tests/Codesys/test.SYM create mode 100644 tests/Codesys/test.pro create mode 100644 tests/Codesys/test00002ed2r.ci create mode 100644 tests/Codesys/test00002ed2r.ri create mode 100644 tests/IecType/output/test.iecByte.php.html create mode 100644 tests/IecType/output/test.iecDInt.php.html create mode 100644 tests/IecType/output/test.iecInt.php.html create mode 100644 tests/IecType/output/test.iecReal.php.html create mode 100644 tests/ModbusMaster/output/test.tcp.fc16fc3.php.html create mode 100644 tests/ModbusMaster/output/test.tcp.fc26.php.html create mode 100644 tests/ModbusMaster/output/test.tcp.socket_protocol_mismatch.php.html create mode 100644 tests/ModbusMaster/output/test.udp.fc16fc3.php.html create mode 100644 tests/ModbusMaster/output/test.udp.fc26.php.html create mode 100644 tests/ModbusMasterTcp/output/test.fc16fc3.php.html create mode 100644 tests/ModbusMasterTcp/output/test.fc26.php.html create mode 100644 tests/ModbusMasterUdp/output/test.fc15fc1.php.html create mode 100644 tests/ModbusMasterUdp/output/test.fc16fc3.php.html create mode 100644 tests/ModbusMasterUdp/output/test.fc16fc3bind.php.html create mode 100644 tests/ModbusMasterUdp/output/test.fc2.php.html create mode 100644 tests/ModbusMasterUdp/output/test.fc26.php.html create mode 100644 tests/ModbusMasterUdp/output/test.fc26bind.php.html create mode 100644 tests/ModbusMasterUdp/output/test.fc6fc3.php.html create mode 100644 tests/ModbusMasterUdp/ref/test.fc15fc1.php.html create mode 100644 tests/ModbusMasterUdp/ref/test.fc2.php.html create mode 100644 tests/ModbusMasterUdp/ref/test.fc6fc3.php.html create mode 100644 tests/ModbusMasterUdp/test.fc2.php create mode 100644 tests/ModbusMasterUdp/test.fc6fc3.php create mode 100644 tests/PhpType/output/test.bytes2mixed.php.html create mode 100644 tests/PhpType/output/test.bytes2real.php.html create mode 100644 tests/PhpType/output/test.bytes2signedint.php.html create mode 100644 tests/PhpType/output/test.bytes2string.php.html create mode 100644 tests/PhpType/output/test.bytes2unsignedint.php.html create mode 100644 tests/PhpType/output/test.strangearray.size.php.html create mode 100644 tests/PhpType/output/test.strangearray.textarray.php.html diff --git a/Phpmodbus/IecType.php b/Phpmodbus/IecType.php index 9beb696..dd23ccc 100644 --- a/Phpmodbus/IecType.php +++ b/Phpmodbus/IecType.php @@ -34,7 +34,7 @@ class IecType { * @return value IEC BYTE data type * */ - function iecBYTE($value) { + public static function iecBYTE($value) { return chr($value & 0xFF); } @@ -47,7 +47,7 @@ class IecType { * @return value IEC-1131 INT data type * */ - function iecINT($value) { + public static function iecINT($value) { return self::iecBYTE(($value >> 8) & 0x00FF) . self::iecBYTE(($value & 0x00FF)); } @@ -62,7 +62,7 @@ class IecType { * @return value IEC-1131 INT data type * */ - function iecDINT($value, $endianness = 0) { + public static function iecDINT($value, $endianness = 0) { // result with right endianness return self::endianness($value, $endianness); } @@ -76,7 +76,7 @@ class IecType { * @param value endianness defines endian codding (little endian == 0, big endian == 1) * @return value IEC-1131 REAL data type */ - function iecREAL($value, $endianness = 0) { + public static function iecREAL($value, $endianness = 0) { // iecREAL representation $real = self::float2iecReal($value); // result with right endianness @@ -95,7 +95,7 @@ class IecType { * @param float value to be converted * @return value IEC REAL data type */ - private function float2iecReal($value) { + private static function float2iecReal($value) { // get float binary string $float = pack("f", $value); // set 32-bit unsigned integer of the float @@ -113,7 +113,7 @@ class IecType { * @param bool $endianness * @return int */ - private function endianness($value, $endianness = 0) { + private static function endianness($value, $endianness = 0) { if ($endianness == 0) return self::iecBYTE(($value >> 8) & 0x000000FF) . diff --git a/Phpmodbus/ModbusMaster.php b/Phpmodbus/ModbusMaster.php index 0a1997d..e5a0ba6 100644 --- a/Phpmodbus/ModbusMaster.php +++ b/Phpmodbus/ModbusMaster.php @@ -1,798 +1,1012 @@ -socket_protocol = $protocol; - $this->host = $host; - } - - /** - * __toString - * - * Magic method - */ - function __toString() { - return "
" . $this->status . "
"; - } - - /** - * connect - * - * Connect the socket - * - * @return bool - */ - private function connect(){ - // Create a protocol specific socket - if ($this->socket_protocol == "TCP"){ - // TCP socket - $this->sock = socket_create(AF_INET, SOCK_STREAM, SOL_TCP); - } elseif ($this->socket_protocol == "UDP"){ - // UDP socket - $this->sock = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP); - } else { - throw new Exception("Unknown socket protocol, should be 'TCP' or 'UDP'"); - } - // Bind the client socket to a specific local port - if (strlen($this->client)>0){ - $result = socket_bind($this->sock, $this->client, $this->client_port); - if ($result === false) { - throw new Exception("socket_bind() failed.
Reason: ($result)". - socket_strerror(socket_last_error($this->sock))); - } else { - $this->status .= "Bound\n"; - } - } - // Connect the socket - $result = @socket_connect($this->sock, $this->host, $this->port); - if ($result === false) { - throw new Exception("socket_connect() failed.
Reason: ($result)". - socket_strerror(socket_last_error($this->sock))); - } else { - $this->status .= "Connected\n"; - return true; - } - } - - /** - * disconnect - * - * Disconnect the socket - */ - private function disconnect(){ - socket_close($this->sock); - $this->status .= "Disconnected\n"; - } - - /** - * send - * - * Send the packet via Modbus - * - * @param string $packet - */ - private function send($packet){ - socket_write($this->sock, $packet, strlen($packet)); - $this->status .= "Send\n"; - } - - /** - * rec - * - * Receive data from the socket - * - * @return bool - */ - private function rec(){ - socket_set_nonblock($this->sock); - $readsocks[] = $this->sock; - $writesocks = NULL; - $exceptsocks = NULL; - $rec = ""; - $lastAccess = time(); - while (socket_select($readsocks, - $writesocks, - $exceptsocks, - 0, - 300000) !== FALSE) { - $this->status .= "Wait data ... \n"; - if (in_array($this->sock, $readsocks)) { - while (@socket_recv($this->sock, $rec, 2000, 0)) { - $this->status .= "Data received\n"; - return $rec; - } - $lastAccess = time(); - } else { - if (time()-$lastAccess >= $this->timeout_sec) { - throw new Exception( "Watchdog time expired [ " . - $this->timeout_sec . " sec]!!! Connection to " . - $this->host . " is not established."); - } - } - $readsocks[] = $this->sock; - } - } - - /** - * responseCode - * - * Check the Modbus response code - * - * @param string $packet - * @return bool - */ - private function responseCode($packet){ - if(($packet[7] & 0x80) > 0) { - throw new Exception("Modbus response error code:" . ord($packet[8])); - } else { - $this->status .= "Modbus response error code: NOERROR\n"; - return true; - } - } - - /** - * readCoils - * - * Modbus function FC 1(0x01) - Read Coils - * - * Reads {@link $quantity} of Coils (boolean) from reference - * {@link $referenceRead} of a memory of a Modbus device given by - * {@link $unitId}. - * - * @param type $unitId - * @param type $reference - * @param type $quantity - */ - function readCoils($unitId, $reference, $quantity){ - $this->status .= "readCoils: START\n"; - // connect - $this->connect(); - // send FC 3 - $packet = $this->readCoilsPacketBuilder($unitId, $reference, $quantity); - $this->status .= $this->printPacket($packet); - $this->send($packet); - // receive response - $rpacket = $this->rec(); - $this->status .= $this->printPacket($rpacket); - // parse packet - $receivedData = $this->readCoilsParser($rpacket, $quantity); - // disconnect - $this->disconnect(); - $this->status .= "readCoils: DONE\n"; - // return - return $receivedData; - } - - /** - * fc1 - * - * Alias to {@link readMultipleCoils} method - * - * @param type $unitId - * @param type $reference - * @param type $quantity - * @return type - */ - function fc1($unitId, $reference, $quantity){ - return $this->readCoils($unitId, $reference, $quantity); - } - - /** - * readCoilsPacketBuilder - * - * FC1 packet builder - read coils - * - * @param type $unitId - * @param type $reference - * @param type $quantity - * @return type - */ - private function readCoilsPacketBuilder($unitId, $reference, $quantity){ - $dataLen = 0; - // build data section - $buffer1 = ""; - // build body - $buffer2 = ""; - $buffer2 .= iecType::iecBYTE(1); // FC 1 = 1(0x01) - // build body - read section - $buffer2 .= iecType::iecINT($reference); // refnumber = 12288 - $buffer2 .= iecType::iecINT($quantity); // quantity - $dataLen += 5; - // build header - $buffer3 = ''; - $buffer3 .= iecType::iecINT(rand(0,65000)); // transaction ID - $buffer3 .= iecType::iecINT(0); // protocol ID - $buffer3 .= iecType::iecINT($dataLen + 1); // lenght - $buffer3 .= iecType::iecBYTE($unitId); //unit ID - // return packet string - return $buffer3. $buffer2. $buffer1; - } - - /** - * readCoilsParser - * - * FC 1 response parser - * - * @param type $packet - * @param type $quantity - * @return type - */ - private function readCoilsParser($packet, $quantity){ - $data = array(); - // check Response code - $this->responseCode($packet); - // get data from stream - for($i=0;$i $quantity) continue; - // get boolean value - $v = ($value >> $i) & 0x01; - // build boolean array - if($v == 0){ - $data_bolean_array[] = FALSE; - } else { - $data_bolean_array[] = TRUE; - } - $di++; - } - } - return $data_bolean_array; - } - - /** - * readMultipleRegisters - * - * Modbus function FC 3(0x03) - Read Multiple Registers. - * - * This function reads {@link $quantity} of Words (2 bytes) from reference - * {@link $referenceRead} of a memory of a Modbus device given by - * {@link $unitId}. - * - * - * @param int $unitId usually ID of Modbus device - * @param int $reference Reference in the device memory to read data (e.g. in device WAGO 750-841, memory MW0 starts at address 12288). - * @param int $quantity Amounth of the data to be read from device. - * @return false|Array Success flag or array of received data. - */ - function readMultipleRegisters($unitId, $reference, $quantity){ - $this->status .= "readMultipleRegisters: START\n"; - // connect - $this->connect(); - // send FC 3 - $packet = $this->readMultipleRegistersPacketBuilder($unitId, $reference, $quantity); - $this->status .= $this->printPacket($packet); - $this->send($packet); - // receive response - $rpacket = $this->rec(); - $this->status .= $this->printPacket($rpacket); - // parse packet - $receivedData = $this->readMultipleRegistersParser($rpacket); - // disconnect - $this->disconnect(); - $this->status .= "readMultipleRegisters: DONE\n"; - // return - return $receivedData; - } - - /** - * fc3 - * - * Alias to {@link readMultipleRegisters} method. - * - * @param int $unitId - * @param int $reference - * @param int $quantity - * @return false|Array - */ - function fc3($unitId, $reference, $quantity){ - return $this->readMultipleRegisters($unitId, $reference, $quantity); - } - - /** - * readMultipleRegistersPacketBuilder - * - * Packet FC 3 builder - read multiple registers - * - * @param int $unitId - * @param int $reference - * @param int $quantity - * @return string - */ - private function readMultipleRegistersPacketBuilder($unitId, $reference, $quantity){ - $dataLen = 0; - // build data section - $buffer1 = ""; - // build body - $buffer2 = ""; - $buffer2 .= iecType::iecBYTE(3); // FC 3 = 3(0x03) - // build body - read section - $buffer2 .= iecType::iecINT($reference); // refnumber = 12288 - $buffer2 .= iecType::iecINT($quantity); // quantity - $dataLen += 5; - // build header - $buffer3 = ''; - $buffer3 .= iecType::iecINT(rand(0,65000)); // transaction ID - $buffer3 .= iecType::iecINT(0); // protocol ID - $buffer3 .= iecType::iecINT($dataLen + 1); // lenght - $buffer3 .= iecType::iecBYTE($unitId); //unit ID - // return packet string - return $buffer3. $buffer2. $buffer1; - } - - /** - * readMultipleRegistersParser - * - * FC 3 response parser - * - * @param string $packet - * @return array - */ - private function readMultipleRegistersParser($packet){ - $data = array(); - // check Response code - $this->responseCode($packet); - // get data - for($i=0;$istatus .= "writeMultipleCoils: START\n"; - // connect - $this->connect(); - // send FC16 - $packet = $this->writeMultipleCoilsPacketBuilder($unitId, $reference, $data); - $this->status .= $this->printPacket($packet); - $this->send($packet); - // receive response - $rpacket = $this->rec(); - $this->status .= $this->printPacket($rpacket); - // parse packet - $this->writeMultipleCoilsParser($rpacket); - // disconnect - $this->disconnect(); - $this->status .= "writeMultipleCoils: DONE\n"; - return true; - } - - /** - * fc15 - * - * Alias to {@link writeMultipleCoils} method - * - * @param int $unitId - * @param int $reference - * @param array $data - * @return bool - */ - function fc15($unitId, $reference, $data){ - return $this->writeMultipleCoils($unitId, $reference, $data); - } - - /** - * writeMultipleCoilsPacketBuilder - * - * Packet builder FC15 - Write multiple coils - * - * @param int $unitId - * @param int $reference - * @param array $data - * @return string - */ - private function writeMultipleCoilsPacketBuilder($unitId, $reference, $data){ - $dataLen = 0; - // build bool stream to the WORD array - $data_word_stream = array(); - $data_word = 0; - $shift = 0; - for($i=0;$i 0)) { - $data_word_stream[] = $data_word; - $shift = 0; - $data_word = 0; - $data_word |= (0x01 && $data[$i]) << $shift; - $shift++; - } - else { - $data_word |= (0x01 && $data[$i]) << $shift; - $shift++; - } - } - $data_word_stream[] = $data_word; - // show binary stream to status string - foreach($data_word_stream as $d){ - $this->status .= sprintf("byte=b%08b\n", $d); - } - // build data section - $buffer1 = ""; - foreach($data_word_stream as $key=>$dataitem) { - $buffer1 .= iecType::iecBYTE($dataitem); // register values x - $dataLen += 1; - } - // build body - $buffer2 = ""; - $buffer2 .= iecType::iecBYTE(15); // FC 15 = 15(0x0f) - $buffer2 .= iecType::iecINT($reference); // refnumber = 12288 - $buffer2 .= iecType::iecINT(count($data)); // bit count - $buffer2 .= iecType::iecBYTE((count($data)+7)/8); // byte count - $dataLen += 6; - // build header - $buffer3 = ''; - $buffer3 .= iecType::iecINT(rand(0,65000)); // transaction ID - $buffer3 .= iecType::iecINT(0); // protocol ID - $buffer3 .= iecType::iecINT($dataLen + 1); // lenght - $buffer3 .= iecType::iecBYTE($unitId); // unit ID - - // return packet string - return $buffer3. $buffer2. $buffer1; - } - - /** - * writeMultipleCoilsParser - * - * FC15 response parser - * - * @param string $packet - * @return bool - */ - private function writeMultipleCoilsParser($packet){ - $this->responseCode($packet); - return true; - } - - /** - * writeMultipleRegister - * - * Modbus function FC16(0x10) - Write Multiple Register. - * - * This function writes {@link $data} array at {@link $reference} position of - * memory of a Modbus device given by {@link $unitId}. - * - * - * @param int $unitId usually ID of Modbus device - * @param int $reference Reference in the device memory (e.g. in device WAGO 750-841, memory MW0 starts at address 12288) - * @param array $data Array of values to be written. - * @param array $dataTypes Array of types of values to be written. The array should consists of string "INT", "DINT" and "REAL". - * @return bool Success flag - */ - function writeMultipleRegister($unitId, $reference, $data, $dataTypes){ - $this->status .= "writeMultipleRegister: START\n"; - // connect - $this->connect(); - // send FC16 - $packet = $this->writeMultipleRegisterPacketBuilder($unitId, $reference, $data, $dataTypes); - $this->status .= $this->printPacket($packet); - $this->send($packet); - // receive response - $rpacket = $this->rec(); - $this->status .= $this->printPacket($rpacket); - // parse packet - $this->writeMultipleRegisterParser($rpacket); - // disconnect - $this->disconnect(); - $this->status .= "writeMultipleRegister: DONE\n"; - return true; - } - - - /** - * fc16 - * - * Alias to {@link writeMultipleRegister} method - * - * @param int $unitId - * @param int $reference - * @param array $data - * @param array $dataTypes - * @return bool - */ - function fc16($unitId, $reference, $data, $dataTypes){ - return $this->writeMultipleRegister($unitId, $reference, $data, $dataTypes); - } - - - /** - * writeMultipleRegisterPacketBuilder - * - * Packet builder FC16 - WRITE multiple register - * e.g.: 4dd90000000d0010300000030603e807d00bb8 - * - * @param int $unitId - * @param int $reference - * @param array $data - * @param array $dataTypes - * @return string - */ - private function writeMultipleRegisterPacketBuilder($unitId, $reference, $data, $dataTypes){ - $dataLen = 0; - // build data section - $buffer1 = ""; - foreach($data as $key=>$dataitem) { - if($dataTypes[$key]=="INT"){ - $buffer1 .= iecType::iecINT($dataitem); // register values x - $dataLen += 2; - } - elseif($dataTypes[$key]=="DINT"){ - $buffer1 .= iecType::iecDINT($dataitem, $this->endianness); // register values x - $dataLen += 4; - } - elseif($dataTypes[$key]=="REAL") { - $buffer1 .= iecType::iecREAL($dataitem, $this->endianness); // register values x - $dataLen += 4; - } - else{ - $buffer1 .= iecType::iecINT($dataitem); // register values x - $dataLen += 2; - } - } - // build body - $buffer2 = ""; - $buffer2 .= iecType::iecBYTE(16); // FC 16 = 16(0x10) - $buffer2 .= iecType::iecINT($reference); // refnumber = 12288 - $buffer2 .= iecType::iecINT($dataLen/2); // word count - $buffer2 .= iecType::iecBYTE($dataLen); // byte count - $dataLen += 6; - // build header - $buffer3 = ''; - $buffer3 .= iecType::iecINT(rand(0,65000)); // transaction ID - $buffer3 .= iecType::iecINT(0); // protocol ID - $buffer3 .= iecType::iecINT($dataLen + 1); // lenght - $buffer3 .= iecType::iecBYTE($unitId); //unit ID - - // return packet string - return $buffer3. $buffer2. $buffer1; - } - - /** - * writeMultipleRegisterParser - * - * FC16 response parser - * - * @param string $packet - * @return bool - */ - private function writeMultipleRegisterParser($packet){ - $this->responseCode($packet); - return true; - } - - /** - * readWriteRegisters - * - * Modbus function FC23(0x17) - Read Write Registers. - * - * This function writes {@link $data} array at reference {@link $referenceWrite} - * position of memory of a Modbus device given by {@link $unitId}. Simultanously, - * it returns {@link $quantity} of Words (2 bytes) from reference {@link $referenceRead}. - * - * - * @param int $unitId usually ID of Modbus device - * @param int $referenceRead Reference in the device memory to read data (e.g. in device WAGO 750-841, memory MW0 starts at address 12288). - * @param int $quantity Amounth of the data to be read from device. - * @param int $referenceWrite Reference in the device memory to write data. - * @param array $data Array of values to be written. - * @param array $dataTypes Array of types of values to be written. The array should consists of string "INT", "DINT" and "REAL". - * @return false|Array Success flag or array of data. - */ - function readWriteRegisters($unitId, $referenceRead, $quantity, $referenceWrite, $data, $dataTypes){ - $this->status .= "readWriteRegisters: START\n"; - // connect - $this->connect(); - // send FC23 - $packet = $this->readWriteRegistersPacketBuilder($unitId, $referenceRead, $quantity, $referenceWrite, $data, $dataTypes); - $this->status .= $this->printPacket($packet); - $this->send($packet); - // receive response - $rpacket = $this->rec(); - $this->status .= $this->printPacket($rpacket); - // parse packet - $receivedData = $this->readWriteRegistersParser($rpacket); - // disconnect - $this->disconnect(); - $this->status .= "writeMultipleRegister: DONE\n"; - // return - return $receivedData; - } - - /** - * fc23 - * - * Alias to {@link readWriteRegisters} method. - * - * @param int $unitId - * @param int $referenceRead - * @param int $quantity - * @param int $referenceWrite - * @param array $data - * @param array $dataTypes - * @return false|Array - */ - function fc23($unitId, $referenceRead, $quantity, $referenceWrite, $data, $dataTypes){ - return $this->readWriteRegisters($unitId, $referenceRead, $quantity, $referenceWrite, $data, $dataTypes); - } - - /** - * readWriteRegistersPacketBuilder - * - * Packet FC23 builder - READ WRITE registers - * - * - * @param int $unitId - * @param int $referenceRead - * @param int $quantity - * @param int $referenceWrite - * @param array $data - * @param array $dataTypes - * @return string - */ - private function readWriteRegistersPacketBuilder($unitId, $referenceRead, $quantity, $referenceWrite, $data, $dataTypes){ - $dataLen = 0; - // build data section - $buffer1 = ""; - foreach($data as $key => $dataitem) { - if($dataTypes[$key]=="INT"){ - $buffer1 .= iecType::iecINT($dataitem); // register values x - $dataLen += 2; - } - elseif($dataTypes[$key]=="DINT"){ - $buffer1 .= iecType::iecDINT($dataitem, $this->endianness); // register values x - $dataLen += 4; - } - elseif($dataTypes[$key]=="REAL") { - $buffer1 .= iecType::iecREAL($dataitem, $this->endianness); // register values x - $dataLen += 4; - } - else{ - $buffer1 .= iecType::iecINT($dataitem); // register values x - $dataLen += 2; - } - } - // build body - $buffer2 = ""; - $buffer2 .= iecType::iecBYTE(23); // FC 23 = 23(0x17) - // build body - read section - $buffer2 .= iecType::iecINT($referenceRead); // refnumber = 12288 - $buffer2 .= iecType::iecINT($quantity); // quantity - // build body - write section - $buffer2 .= iecType::iecINT($referenceWrite); // refnumber = 12288 - $buffer2 .= iecType::iecINT($dataLen/2); // word count - $buffer2 .= iecType::iecBYTE($dataLen); // byte count - $dataLen += 10; - // build header - $buffer3 = ''; - $buffer3 .= iecType::iecINT(rand(0,65000)); // transaction ID - $buffer3 .= iecType::iecINT(0); // protocol ID - $buffer3 .= iecType::iecINT($dataLen + 1); // lenght - $buffer3 .= iecType::iecBYTE($unitId); //unit ID - - // return packet string - return $buffer3. $buffer2. $buffer1; - } - - - /** - * readWriteRegistersParser - * - * FC23 response parser - * - * @param string $packet - * @return array - */ - private function readWriteRegistersParser($packet){ - $data = array(); - // if not exception - if(!$this->responseCode($packet)) - return false; - // get data - for($i=0;$i> 4) & 0x0F); - $l = dechex($value & 0x0F); - return "$h$l"; - } - - /** - * printPacket - * - * Print a packet in the hex form - * - * @param string $packet - * @return string - */ - private function printPacket($packet){ - $str = ""; - $str .= "Packet: "; - for($i=0;$ibyte2hex(ord($packet[$i])); - } - $str .= "\n"; - return $str; - } -} +socket_protocol = $protocol; + $this->host = $host; + } + + /** + * __toString + * + * Magic method + */ + function __toString() { + return "
" . $this->status . "
"; + } + + /** + * connect + * + * Connect the socket + * + * @return bool + */ + private function connect(){ + // Create a protocol specific socket + if ($this->socket_protocol == "TCP"){ + // TCP socket + $this->sock = socket_create(AF_INET, SOCK_STREAM, SOL_TCP); + } elseif ($this->socket_protocol == "UDP"){ + // UDP socket + $this->sock = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP); + } else { + throw new Exception("Unknown socket protocol, should be 'TCP' or 'UDP'"); + } + // Bind the client socket to a specific local port + if (strlen($this->client)>0){ + $result = socket_bind($this->sock, $this->client, $this->client_port); + if ($result === false) { + throw new Exception("socket_bind() failed.
Reason: ($result)". + socket_strerror(socket_last_error($this->sock))); + } else { + $this->status .= "Bound\n"; + } + } + // Connect the socket + $result = @socket_connect($this->sock, $this->host, $this->port); + if ($result === false) { + throw new Exception("socket_connect() failed.
Reason: ($result)". + socket_strerror(socket_last_error($this->sock))); + } else { + $this->status .= "Connected\n"; + return true; + } + } + + /** + * disconnect + * + * Disconnect the socket + */ + private function disconnect(){ + socket_close($this->sock); + $this->status .= "Disconnected\n"; + } + + /** + * send + * + * Send the packet via Modbus + * + * @param string $packet + */ + private function send($packet){ + socket_write($this->sock, $packet, strlen($packet)); + $this->status .= "Send\n"; + } + + /** + * rec + * + * Receive data from the socket + * + * @return bool + */ + private function rec(){ + socket_set_nonblock($this->sock); + $readsocks[] = $this->sock; + $writesocks = NULL; + $exceptsocks = NULL; + $rec = ""; + $lastAccess = time(); + while (socket_select($readsocks, + $writesocks, + $exceptsocks, + 0, + 300000) !== FALSE) { + $this->status .= "Wait data ... \n"; + if (in_array($this->sock, $readsocks)) { + while (@socket_recv($this->sock, $rec, 2000, 0)) { + $this->status .= "Data received\n"; + return $rec; + } + $lastAccess = time(); + } else { + if (time()-$lastAccess >= $this->timeout_sec) { + throw new Exception( "Watchdog time expired [ " . + $this->timeout_sec . " sec]!!! Connection to " . + $this->host . " is not established."); + } + } + $readsocks[] = $this->sock; + } + } + + /** + * responseCode + * + * Check the Modbus response code + * + * @param string $packet + * @return bool + */ + private function responseCode($packet){ + if((ord($packet[7]) & 0x80) > 0) { + // failure code + $failure_code = ord($packet[8]); + // failure code strings + $failures = array( + 0x01 => "ILLEGAL FUNCTION", + 0x02 => "ILLEGAL DATA ADDRESS", + 0x03 => "ILLEGAL DATA VALUE", + 0x04 => "SLAVE DEVICE FAILURE", + 0x05 => "ACKNOWLEDGE", + 0x06 => "SLAVE DEVICE BUSY", + 0x08 => "MEMORY PARITY ERROR", + 0x0A => "GATEWAY PATH UNAVAILABLE", + 0x0B => "GATEWAY TARGET DEVICE FAILED TO RESPOND"); + // get failure string + if(key_exists($failure_code, $failures)) { + $failure_str = $failures[$failure_code]; + } else { + $failure_str = "UNDEFINED FAILURE CODE"; + } + // exception response + throw new Exception("Modbus response error code: $failure_code ($failure_str)"); + } else { + $this->status .= "Modbus response error code: NOERROR\n"; + return true; + } + } + + /** + * readCoils + * + * Modbus function FC 1(0x01) - Read Coils + * + * Reads {@link $quantity} of Coils (boolean) from reference + * {@link $reference} of a memory of a Modbus device given by + * {@link $unitId}. + * + * @param type $unitId + * @param type $reference + * @param type $quantity + */ + function readCoils($unitId, $reference, $quantity){ + $this->status .= "readCoils: START\n"; + // connect + $this->connect(); + // send FC 1 + $packet = $this->readCoilsPacketBuilder($unitId, $reference, $quantity); + $this->status .= $this->printPacket($packet); + $this->send($packet); + // receive response + $rpacket = $this->rec(); + $this->status .= $this->printPacket($rpacket); + // parse packet + $receivedData = $this->readCoilsParser($rpacket, $quantity); + // disconnect + $this->disconnect(); + $this->status .= "readCoils: DONE\n"; + // return + return $receivedData; + } + + /** + * fc1 + * + * Alias to {@link readCoils} method + * + * @param type $unitId + * @param type $reference + * @param type $quantity + * @return type + */ + function fc1($unitId, $reference, $quantity){ + return $this->readCoils($unitId, $reference, $quantity); + } + + /** + * readCoilsPacketBuilder + * + * FC1 packet builder - read coils + * + * @param type $unitId + * @param type $reference + * @param type $quantity + * @return type + */ + private function readCoilsPacketBuilder($unitId, $reference, $quantity){ + $dataLen = 0; + // build data section + $buffer1 = ""; + // build body + $buffer2 = ""; + $buffer2 .= iecType::iecBYTE(1); // FC 1 = 1(0x01) + // build body - read section + $buffer2 .= iecType::iecINT($reference); // refnumber = 12288 + $buffer2 .= iecType::iecINT($quantity); // quantity + $dataLen += 5; + // build header + $buffer3 = ''; + $buffer3 .= iecType::iecINT(rand(0,65000)); // transaction ID + $buffer3 .= iecType::iecINT(0); // protocol ID + $buffer3 .= iecType::iecINT($dataLen + 1); // lenght + $buffer3 .= iecType::iecBYTE($unitId); //unit ID + // return packet string + return $buffer3. $buffer2. $buffer1; + } + + /** + * readCoilsParser + * + * FC 1 response parser + * + * @param type $packet + * @param type $quantity + * @return type + */ + private function readCoilsParser($packet, $quantity){ + $data = array(); + // check Response code + $this->responseCode($packet); + // get data from stream + for($i=0;$i> $i) & 0x01; + // build boolean array + if($v == 0){ + $data_bolean_array[] = FALSE; + } else { + $data_bolean_array[] = TRUE; + } + $di++; + } + } + return $data_bolean_array; + } + + /** + * readInputDiscretes + * + * Modbus function FC 2(0x02) - Read Input Discretes + * + * Reads {@link $quantity} of Inputs (boolean) from reference + * {@link $reference} of a memory of a Modbus device given by + * {@link $unitId}. + * + * @param type $unitId + * @param type $reference + * @param type $quantity + */ + function readInputDiscretes($unitId, $reference, $quantity){ + $this->status .= "readInputDiscretes: START\n"; + // connect + $this->connect(); + // send FC 2 + $packet = $this->readInputDiscretesPacketBuilder($unitId, $reference, $quantity); + $this->status .= $this->printPacket($packet); + $this->send($packet); + // receive response + $rpacket = $this->rec(); + $this->status .= $this->printPacket($rpacket); + // parse packet + $receivedData = $this->readInputDiscretesParser($rpacket, $quantity); + // disconnect + $this->disconnect(); + $this->status .= "readInputDiscretes: DONE\n"; + // return + return $receivedData; + } + + /** + * fc2 + * + * Alias to {@link readInputDiscretes} method + * + * @param type $unitId + * @param type $reference + * @param type $quantity + * @return type + */ + function fc2($unitId, $reference, $quantity){ + return $this->readInputDiscretes($unitId, $reference, $quantity); + } + + /** + * readInputDiscretesPacketBuilder + * + * FC2 packet builder - read coils + * + * @param type $unitId + * @param type $reference + * @param type $quantity + * @return type + */ + private function readInputDiscretesPacketBuilder($unitId, $reference, $quantity){ + $dataLen = 0; + // build data section + $buffer1 = ""; + // build body + $buffer2 = ""; + $buffer2 .= iecType::iecBYTE(2); // FC 2 = 2(0x02) + // build body - read section + $buffer2 .= iecType::iecINT($reference); // refnumber = 12288 + $buffer2 .= iecType::iecINT($quantity); // quantity + $dataLen += 5; + // build header + $buffer3 = ''; + $buffer3 .= iecType::iecINT(rand(0,65000)); // transaction ID + $buffer3 .= iecType::iecINT(0); // protocol ID + $buffer3 .= iecType::iecINT($dataLen + 1); // lenght + $buffer3 .= iecType::iecBYTE($unitId); //unit ID + // return packet string + return $buffer3. $buffer2. $buffer1; + } + + /** + * readInputDiscretesParser + * + * FC 2 response parser, alias to FC 1 parser i.e. readCoilsParser. + * + * @param type $packet + * @param type $quantity + * @return type + */ + private function readInputDiscretesParser($packet, $quantity){ + return $this->readCoilsParser($packet, $quantity); + } + + /** + * readMultipleRegisters + * + * Modbus function FC 3(0x03) - Read Multiple Registers. + * + * This function reads {@link $quantity} of Words (2 bytes) from reference + * {@link $referenceRead} of a memory of a Modbus device given by + * {@link $unitId}. + * + * + * @param int $unitId usually ID of Modbus device + * @param int $reference Reference in the device memory to read data (e.g. in device WAGO 750-841, memory MW0 starts at address 12288). + * @param int $quantity Amounth of the data to be read from device. + * @return false|Array Success flag or array of received data. + */ + function readMultipleRegisters($unitId, $reference, $quantity){ + $this->status .= "readMultipleRegisters: START\n"; + // connect + $this->connect(); + // send FC 3 + $packet = $this->readMultipleRegistersPacketBuilder($unitId, $reference, $quantity); + $this->status .= $this->printPacket($packet); + $this->send($packet); + // receive response + $rpacket = $this->rec(); + $this->status .= $this->printPacket($rpacket); + // parse packet + $receivedData = $this->readMultipleRegistersParser($rpacket); + // disconnect + $this->disconnect(); + $this->status .= "readMultipleRegisters: DONE\n"; + // return + return $receivedData; + } + + /** + * fc3 + * + * Alias to {@link readMultipleRegisters} method. + * + * @param int $unitId + * @param int $reference + * @param int $quantity + * @return false|Array + */ + function fc3($unitId, $reference, $quantity){ + return $this->readMultipleRegisters($unitId, $reference, $quantity); + } + + /** + * readMultipleRegistersPacketBuilder + * + * Packet FC 3 builder - read multiple registers + * + * @param int $unitId + * @param int $reference + * @param int $quantity + * @return string + */ + private function readMultipleRegistersPacketBuilder($unitId, $reference, $quantity){ + $dataLen = 0; + // build data section + $buffer1 = ""; + // build body + $buffer2 = ""; + $buffer2 .= iecType::iecBYTE(3); // FC 3 = 3(0x03) + // build body - read section + $buffer2 .= iecType::iecINT($reference); // refnumber = 12288 + $buffer2 .= iecType::iecINT($quantity); // quantity + $dataLen += 5; + // build header + $buffer3 = ''; + $buffer3 .= iecType::iecINT(rand(0,65000)); // transaction ID + $buffer3 .= iecType::iecINT(0); // protocol ID + $buffer3 .= iecType::iecINT($dataLen + 1); // lenght + $buffer3 .= iecType::iecBYTE($unitId); //unit ID + // return packet string + return $buffer3. $buffer2. $buffer1; + } + + /** + * readMultipleRegistersParser + * + * FC 3 response parser + * + * @param string $packet + * @return array + */ + private function readMultipleRegistersParser($packet){ + $data = array(); + // check Response code + $this->responseCode($packet); + // get data + for($i=0;$istatus .= "writeSingleRegister: START\n"; + // connect + $this->connect(); + // send FC6 + $packet = $this->writeSingleRegisterPacketBuilder($unitId, $reference, $data, $dataTypes); + $this->status .= $this->printPacket($packet); + $this->send($packet); + // receive response + $rpacket = $this->rec(); + $this->status .= $this->printPacket($rpacket); + // parse packet + $this->writeSingleRegisterParser($rpacket); + // disconnect + $this->disconnect(); + $this->status .= "writeSingleRegister: DONE\n"; + return true; + } + + + /** + * fc6 + * + * Alias to {@link writeSingleRegister} method + * + * @param int $unitId + * @param int $reference + * @param array $data + * @param array $dataTypes + * @return bool + */ + function fc6($unitId, $reference, $data, $dataTypes){ + return $this->writeSingleRegister($unitId, $reference, $data, $dataTypes); + } + + + /** + * writeSingleRegisterPacketBuilder + * + * Packet builder FC6 - WRITE single register + * + * @param int $unitId + * @param int $reference + * @param array $data + * @param array $dataTypes + * @return string + */ + private function writeSingleRegisterPacketBuilder($unitId, $reference, $data, $dataTypes){ + $dataLen = 0; + // build data section + $buffer1 = ""; + foreach($data as $key=>$dataitem) { + $buffer1 .= iecType::iecINT($dataitem); // register values x + $dataLen += 2; + break; + } + // build body + $buffer2 = ""; + $buffer2 .= iecType::iecBYTE(6); // FC6 = 6(0x06) + $buffer2 .= iecType::iecINT($reference); // refnumber = 12288 + $dataLen += 3; + // build header + $buffer3 = ''; + $buffer3 .= iecType::iecINT(rand(0,65000)); // transaction ID + $buffer3 .= iecType::iecINT(0); // protocol ID + $buffer3 .= iecType::iecINT($dataLen + 1); // lenght + $buffer3 .= iecType::iecBYTE($unitId); //unit ID + + // return packet string + return $buffer3. $buffer2. $buffer1; + } + + /** + * writeSingleRegisterParser + * + * FC6 response parser + * + * @param string $packet + * @return bool + */ + private function writeSingleRegisterParser($packet){ + $this->responseCode($packet); + return true; + } + + + /** + * writeMultipleCoils + * + * Modbus function FC15(0x0F) - Write Multiple Coils + * + * This function writes {@link $data} array at {@link $reference} position of + * memory of a Modbus device given by {@link $unitId}. + * + * @param type $unitId + * @param type $reference + * @param type $data + * @return type + */ + function writeMultipleCoils($unitId, $reference, $data){ + $this->status .= "writeMultipleCoils: START\n"; + // connect + $this->connect(); + // send FC15 + $packet = $this->writeMultipleCoilsPacketBuilder($unitId, $reference, $data); + $this->status .= $this->printPacket($packet); + $this->send($packet); + // receive response + $rpacket = $this->rec(); + $this->status .= $this->printPacket($rpacket); + // parse packet + $this->writeMultipleCoilsParser($rpacket); + // disconnect + $this->disconnect(); + $this->status .= "writeMultipleCoils: DONE\n"; + return true; + } + + /** + * fc15 + * + * Alias to {@link writeMultipleCoils} method + * + * @param int $unitId + * @param int $reference + * @param array $data + * @return bool + */ + function fc15($unitId, $reference, $data){ + return $this->writeMultipleCoils($unitId, $reference, $data); + } + + /** + * writeMultipleCoilsPacketBuilder + * + * Packet builder FC15 - Write multiple coils + * + * @param int $unitId + * @param int $reference + * @param array $data + * @return string + */ + private function writeMultipleCoilsPacketBuilder($unitId, $reference, $data){ + $dataLen = 0; + // build bool stream to the WORD array + $data_word_stream = array(); + $data_word = 0; + $shift = 0; + for($i=0;$i 0)) { + $data_word_stream[] = $data_word; + $shift = 0; + $data_word = 0; + $data_word |= (0x01 && $data[$i]) << $shift; + $shift++; + } + else { + $data_word |= (0x01 && $data[$i]) << $shift; + $shift++; + } + } + $data_word_stream[] = $data_word; + // show binary stream to status string + foreach($data_word_stream as $d){ + $this->status .= sprintf("byte=b%08b\n", $d); + } + // build data section + $buffer1 = ""; + foreach($data_word_stream as $key=>$dataitem) { + $buffer1 .= iecType::iecBYTE($dataitem); // register values x + $dataLen += 1; + } + // build body + $buffer2 = ""; + $buffer2 .= iecType::iecBYTE(15); // FC 15 = 15(0x0f) + $buffer2 .= iecType::iecINT($reference); // refnumber = 12288 + $buffer2 .= iecType::iecINT(count($data)); // bit count + $buffer2 .= iecType::iecBYTE((count($data)+7)/8); // byte count + $dataLen += 6; + // build header + $buffer3 = ''; + $buffer3 .= iecType::iecINT(rand(0,65000)); // transaction ID + $buffer3 .= iecType::iecINT(0); // protocol ID + $buffer3 .= iecType::iecINT($dataLen + 1); // lenght + $buffer3 .= iecType::iecBYTE($unitId); // unit ID + + // return packet string + return $buffer3. $buffer2. $buffer1; + } + + /** + * writeMultipleCoilsParser + * + * FC15 response parser + * + * @param string $packet + * @return bool + */ + private function writeMultipleCoilsParser($packet){ + $this->responseCode($packet); + return true; + } + + /** + * writeMultipleRegister + * + * Modbus function FC16(0x10) - Write Multiple Register. + * + * This function writes {@link $data} array at {@link $reference} position of + * memory of a Modbus device given by {@link $unitId}. + * + * + * @param int $unitId usually ID of Modbus device + * @param int $reference Reference in the device memory (e.g. in device WAGO 750-841, memory MW0 starts at address 12288) + * @param array $data Array of values to be written. + * @param array $dataTypes Array of types of values to be written. The array should consists of string "INT", "DINT" and "REAL". + * @return bool Success flag + */ + function writeMultipleRegister($unitId, $reference, $data, $dataTypes){ + $this->status .= "writeMultipleRegister: START\n"; + // connect + $this->connect(); + // send FC16 + $packet = $this->writeMultipleRegisterPacketBuilder($unitId, $reference, $data, $dataTypes); + $this->status .= $this->printPacket($packet); + $this->send($packet); + // receive response + $rpacket = $this->rec(); + $this->status .= $this->printPacket($rpacket); + // parse packet + $this->writeMultipleRegisterParser($rpacket); + // disconnect + $this->disconnect(); + $this->status .= "writeMultipleRegister: DONE\n"; + return true; + } + + + /** + * fc16 + * + * Alias to {@link writeMultipleRegister} method + * + * @param int $unitId + * @param int $reference + * @param array $data + * @param array $dataTypes + * @return bool + */ + function fc16($unitId, $reference, $data, $dataTypes){ + return $this->writeMultipleRegister($unitId, $reference, $data, $dataTypes); + } + + + /** + * writeMultipleRegisterPacketBuilder + * + * Packet builder FC16 - WRITE multiple register + * e.g.: 4dd90000000d0010300000030603e807d00bb8 + * + * @param int $unitId + * @param int $reference + * @param array $data + * @param array $dataTypes + * @return string + */ + private function writeMultipleRegisterPacketBuilder($unitId, $reference, $data, $dataTypes){ + $dataLen = 0; + // build data section + $buffer1 = ""; + foreach($data as $key=>$dataitem) { + if($dataTypes[$key]=="INT"){ + $buffer1 .= iecType::iecINT($dataitem); // register values x + $dataLen += 2; + } + elseif($dataTypes[$key]=="DINT"){ + $buffer1 .= iecType::iecDINT($dataitem, $this->endianness); // register values x + $dataLen += 4; + } + elseif($dataTypes[$key]=="REAL") { + $buffer1 .= iecType::iecREAL($dataitem, $this->endianness); // register values x + $dataLen += 4; + } + else{ + $buffer1 .= iecType::iecINT($dataitem); // register values x + $dataLen += 2; + } + } + // build body + $buffer2 = ""; + $buffer2 .= iecType::iecBYTE(16); // FC 16 = 16(0x10) + $buffer2 .= iecType::iecINT($reference); // refnumber = 12288 + $buffer2 .= iecType::iecINT($dataLen/2); // word count + $buffer2 .= iecType::iecBYTE($dataLen); // byte count + $dataLen += 6; + // build header + $buffer3 = ''; + $buffer3 .= iecType::iecINT(rand(0,65000)); // transaction ID + $buffer3 .= iecType::iecINT(0); // protocol ID + $buffer3 .= iecType::iecINT($dataLen + 1); // lenght + $buffer3 .= iecType::iecBYTE($unitId); //unit ID + + // return packet string + return $buffer3. $buffer2. $buffer1; + } + + /** + * writeMultipleRegisterParser + * + * FC16 response parser + * + * @param string $packet + * @return bool + */ + private function writeMultipleRegisterParser($packet){ + $this->responseCode($packet); + return true; + } + + /** + * readWriteRegisters + * + * Modbus function FC23(0x17) - Read Write Registers. + * + * This function writes {@link $data} array at reference {@link $referenceWrite} + * position of memory of a Modbus device given by {@link $unitId}. Simultanously, + * it returns {@link $quantity} of Words (2 bytes) from reference {@link $referenceRead}. + * + * + * @param int $unitId usually ID of Modbus device + * @param int $referenceRead Reference in the device memory to read data (e.g. in device WAGO 750-841, memory MW0 starts at address 12288). + * @param int $quantity Amounth of the data to be read from device. + * @param int $referenceWrite Reference in the device memory to write data. + * @param array $data Array of values to be written. + * @param array $dataTypes Array of types of values to be written. The array should consists of string "INT", "DINT" and "REAL". + * @return false|Array Success flag or array of data. + */ + function readWriteRegisters($unitId, $referenceRead, $quantity, $referenceWrite, $data, $dataTypes){ + $this->status .= "readWriteRegisters: START\n"; + // connect + $this->connect(); + // send FC23 + $packet = $this->readWriteRegistersPacketBuilder($unitId, $referenceRead, $quantity, $referenceWrite, $data, $dataTypes); + $this->status .= $this->printPacket($packet); + $this->send($packet); + // receive response + $rpacket = $this->rec(); + $this->status .= $this->printPacket($rpacket); + // parse packet + $receivedData = $this->readWriteRegistersParser($rpacket); + // disconnect + $this->disconnect(); + $this->status .= "writeMultipleRegister: DONE\n"; + // return + return $receivedData; + } + + /** + * fc23 + * + * Alias to {@link readWriteRegisters} method. + * + * @param int $unitId + * @param int $referenceRead + * @param int $quantity + * @param int $referenceWrite + * @param array $data + * @param array $dataTypes + * @return false|Array + */ + function fc23($unitId, $referenceRead, $quantity, $referenceWrite, $data, $dataTypes){ + return $this->readWriteRegisters($unitId, $referenceRead, $quantity, $referenceWrite, $data, $dataTypes); + } + + /** + * readWriteRegistersPacketBuilder + * + * Packet FC23 builder - READ WRITE registers + * + * + * @param int $unitId + * @param int $referenceRead + * @param int $quantity + * @param int $referenceWrite + * @param array $data + * @param array $dataTypes + * @return string + */ + private function readWriteRegistersPacketBuilder($unitId, $referenceRead, $quantity, $referenceWrite, $data, $dataTypes){ + $dataLen = 0; + // build data section + $buffer1 = ""; + foreach($data as $key => $dataitem) { + if($dataTypes[$key]=="INT"){ + $buffer1 .= iecType::iecINT($dataitem); // register values x + $dataLen += 2; + } + elseif($dataTypes[$key]=="DINT"){ + $buffer1 .= iecType::iecDINT($dataitem, $this->endianness); // register values x + $dataLen += 4; + } + elseif($dataTypes[$key]=="REAL") { + $buffer1 .= iecType::iecREAL($dataitem, $this->endianness); // register values x + $dataLen += 4; + } + else{ + $buffer1 .= iecType::iecINT($dataitem); // register values x + $dataLen += 2; + } + } + // build body + $buffer2 = ""; + $buffer2 .= iecType::iecBYTE(23); // FC 23 = 23(0x17) + // build body - read section + $buffer2 .= iecType::iecINT($referenceRead); // refnumber = 12288 + $buffer2 .= iecType::iecINT($quantity); // quantity + // build body - write section + $buffer2 .= iecType::iecINT($referenceWrite); // refnumber = 12288 + $buffer2 .= iecType::iecINT($dataLen/2); // word count + $buffer2 .= iecType::iecBYTE($dataLen); // byte count + $dataLen += 10; + // build header + $buffer3 = ''; + $buffer3 .= iecType::iecINT(rand(0,65000)); // transaction ID + $buffer3 .= iecType::iecINT(0); // protocol ID + $buffer3 .= iecType::iecINT($dataLen + 1); // lenght + $buffer3 .= iecType::iecBYTE($unitId); //unit ID + + // return packet string + return $buffer3. $buffer2. $buffer1; + } + + + /** + * readWriteRegistersParser + * + * FC23 response parser + * + * @param string $packet + * @return array + */ + private function readWriteRegistersParser($packet){ + $data = array(); + // if not exception + if(!$this->responseCode($packet)) + return false; + // get data + for($i=0;$i> 4) & 0x0F); + $l = dechex($value & 0x0F); + return "$h$l"; + } + + /** + * printPacket + * + * Print a packet in the hex form + * + * @param string $packet + * @return string + */ + private function printPacket($packet){ + $str = ""; + $str .= "Packet: "; + for($i=0;$ibyte2hex(ord($packet[$i])); + } + $str .= "\n"; + return $str; + } +} diff --git a/Phpmodbus/PhpType.php b/Phpmodbus/PhpType.php index 97670a9..5552e61 100644 --- a/Phpmodbus/PhpType.php +++ b/Phpmodbus/PhpType.php @@ -1,12 +1,12 @@ readInputDiscretes(0, 0, 2); +} +catch (Exception $e) { + // Print error information if any + echo $modbus; + echo $e; + exit; +} + +// Print status information +echo "
Status:
" . $modbus; + +// Print read data +echo "
Data:
"; +var_dump($recData); +echo "
"; \ No newline at end of file diff --git a/examples/example_fc6.php b/examples/example_fc6.php new file mode 100644 index 0000000..4db6b04 --- /dev/null +++ b/examples/example_fc6.php @@ -0,0 +1,26 @@ +writeSingleRegister(0, 12288, $data, $dataTypes); +} +catch (Exception $e) { + // Print error information if any + echo $modbus; + echo $e; + exit; +} + +// Print status information +echo $modbus; + +?> \ No newline at end of file diff --git a/tests/Codesys/DEFAULT.DFR b/tests/Codesys/DEFAULT.DFR new file mode 100644 index 0000000000000000000000000000000000000000..656e9fe6900bbd2d625e7d2368e5eb67aa1420b6 GIT binary patch literal 445 zcmY%GVPIfjWaRks|NnmmhO#DEI9fr?yQ-5f)GLiAkRf*3gB&nN|O0RZm|KoB=b4ivb9kBUnIuMj!-x3&@7iFm?E7UZ7;PbADb)YF> codesys_cmd_file.cmd +echo project export %PROJECT%.EXP >> codesys_cmd_file.cmd +rem echo file saveas %PROJECT%.lib internallib >> codesys_cmd_file.cmd +echo file close >> codesys_cmd_file.cmd +echo file quit >> codesys_cmd_file.cmd +%CODESYS% /noinfo /cmd codesys_cmd_file.cmd + +rem Clean all when finished +del codesys_cmd_file.cmd \ No newline at end of file diff --git a/tests/Codesys/test.SDB b/tests/Codesys/test.SDB new file mode 100644 index 0000000000000000000000000000000000000000..7a1a08b0cfe1b2ab018e73665fa2ec10965bcca4 GIT binary patch literal 72 pcmZQ%U|^5{Vn!hTcYu+hZgYj12awGK!~#GJ1I$1MGM^2N4*=@51Uvu$ literal 0 HcmV?d00001 diff --git a/tests/Codesys/test.SYM b/tests/Codesys/test.SYM new file mode 100644 index 0000000..7ed349a --- /dev/null +++ b/tests/Codesys/test.SYM @@ -0,0 +1,4 @@ +;Version=2 +;ProjectId=114942 +;Checksum=0 +;Filesize=0 diff --git a/tests/Codesys/test.pro b/tests/Codesys/test.pro new file mode 100644 index 0000000000000000000000000000000000000000..6904c0c412cd9814cce6b332086a34bc044fff9d GIT binary patch literal 34020 zcmeHQ3yfRGb$u(zwq#q5tvIghIPu7_EXk7gC&`lKCMB2TO0>93isb5JsA0Lwx4X2s zd@Mg&tzo!w`bBFXO!*}^zN!D&nLBsxeBa|t$P2rvh02b;BaY+z%)@ls*yrHSag=kd zvxcB|I?m0Plivy8_7>a%ee3By+`qg3uKwZuFM~ROfRI<5&d)^7RNZ1F?-lqJ;QE~Ch=v;PTl$bUejkblWI4olmxvB*s%!9^FMpJHql;vT|v65^vPA;jm}2=V2%LTrM*8Vi>6 z`SXO;76E|W8t44}KKk^n3AF>P0hklHe>Sc;9u8dpH;QudrnF1cjeoGktgYXBWTy?soD+S)p|J?VJpv z#5IPS?-rM?GoD-Msg7pL`RruDRnuNsg~BS5n{idxt-4cHYKIUZLoastzMFt9lvB)?mG!^cPOSbZohe;CgR5OXSAdn!;7X?0LULb1aDwF9)cg!tgtvQqh(Vz!{DA=zHT0c_{4-X@924P}R}zPSu+YBo1^l!KVsxo*0Tj;A6? zF+_n{S3+*Y+s3?XqXV TcAy3BK2FUdT!;GAc5Nf`Kp{>y5P_qS2a&-W%~X4QO$x zdGKYExi~^YJgTj}F(KNnGB?X(V(`Vju*!*O#-hTif#@p8$}~Dgj*FvRlyCA4-{PQ6 zNJfG&n*RjT5#4qYiYrma9vfx~CkAU6IGwiRb|@Ikkz_K?y^1y)+E745GeDepixYXR(B$^4D`xqfINMC<*#3d6w zcxa{Dqk1|QM{F2CGUXc?{M-z*&Ie=zz%>n%2A=E^4>?^DvhM>15grj#@GmaO;vhub zb?Sv7QZgOVav};u-7;lG7jGS;4d0U#C|)vxCA@54w2!~Lnw{aIq^BPN)ln7 zBB6%a%u1D5saggg(l(Kgkc~*8Oja=R;b)M$lRJPu-YNr&hFk0t8188nVirX zV0}T*&yH19rCJ6k*Yn_SzZlpiMi6Tey9;`zgPSCnUe1d!7ju$2Uh$f|-Rvx=%xLs(Yx`Rc5i&K3%G?QJKmbkWjIL%3X; zLjnnI_;jQ?0b9X%aS$Fwg*78Y0H%)Z;xL3H;?ZC%71^m0 zX=0o5in)r)PGc4y9apoo@|SH8o1@izl$Hz0_zfw{Qn`g}sY25{mX8p1*Qp)SB|82F zEKyNn?Fv*DIBRZYOLUMljS@{KC%P7>ka|VR6E=}f_?=|e%4P=-7hKskBiHG2erAS@ z7VG4Ct=gMb7>Sz&i|*BFD@Q@p1-Cdu71i(_%FoR1G7;p9YG`n-vV65d@21ieSE*L0 z=*9BR_2qU;JY`n0OS4&GYLh+@)?K@LG)bWs{cX{S6ul=31!J+1VCXR389|M3+*zDR z*`Q?PU^JDEB>m0;gedlWB0do<=G-%Aig4Mc(vAhW^oU3?6>>gBt>k2O>Xe$U75Ozs zKQG5dPSZ+1V$j0}9UqcNrc;^7(a1O&%WM6?7uypvp^YrNGx-WyHSn?Y3zd*bC~3kF zq@B&C^*27h@rAqYZZ{Tq89yV#DqQ?M7Yq@Ru zmZ^n%w@;zDQ4E&5*%(^5_cU`OpO#w>E^W$=)55*CnHzn)<(30P#L>ciXEQfygyp^r zEW)*L?`!79gv4@NQ?wDZaPM#CM$NR`*4`Sp5v9UwX0FiyxYV_V6$K9Pz_!mB8v$S2 zI1qr0ftyQRa-%Z=HzZq@n@e4CqfG)gaLaOYsY`CWxCJ*#d|7TTb;*s@b#SA^+j1k% zG$uUUQb4RVTSI3qabywaq=@>yoqXB)6i#<#iW^$w2}DtUKu1aTHwx z&b#PNafIp7T>@~k?j-kZh8rc?Reo@@?j-jX!`;>DtmLda$$h)wURHNVn{_9-w;FEX z+DZ^lv6SN+x5S%H#$mtpU! zz&bl?P_p+M_Kq3^tHOFbTOR<{AJC*Vf1a)5gK-Y>i`&iKDAhZ5*uA);RW>I67(;0}PrZm9Z27JJoA6tljm_5klZw zfLw61L58b)Hf2e@l14h zTxk{k*_S@>&`-a9-KP#Y*WP>2lUOdQyYy6PAX-w}Vn{;`tE5+}x>UrZnhdEXGng6L z=j=`?L)So7R$*WBuu^C~Xw>ejTG8sjtXHWPvvV%lov-%6eu^7!7?4$H-ElCSdtx1C zwEqKba?wR|`ZEYZI{WA%uQNuXefL}8(=zb#Ln{0DM_*(^hn}BZ?@H+&2i-38;fXK;h75Hre{;YsMC*VI9 z@Lvh|uMLd6{Dr`OS-@Wr@K*)>7X+o9VUo1=vU$ZdL{IY-_6!2LAe?Y*$E8yP~@b3%w5dnWtz#kIu9|-uv0)9xq?-TH^ z2>4e8{A&XKbpii|g#(WBn*#nV0sppu9~SWY1^l>$N#~Cl7>`d_Ji#Ba@L6gE4Geo2 zw|Ii%0!|3{7X^J*;Hv^&5b*s1o-{DhniBZqdMHF#YM2F$E8vWvKO*3h1S3AUq`)5* z@Pwc_F5r6w{O^MP83UtAKWkvL1J4Qk^9DxRKQJ&l#UBd%%L0DUz(nG_B;Z#JjK`}6 z#yIOog678pe$Bw!i2iy#EJu{i4FbN=z>xnYfxlV6?-VpVPUl#ty)t;@YqOw#mw;~* zG>;0|-Yei~10$Xpfu9v{UcmPW_>_Ukgq=~5?jZvs_#Oje7#tHcF!Vq@ zXkh5)tbw7=Ga}CW4GdfQq=@rR3=Da;7#g5HEolB!z@HKH0aKU3`)!fdGXnmmp@%%T z3;at0-XP-HB-)2(1{IS44Dd0a7@TUa)X#symz)uMHF9rO0 z0Y4?+9|-tA1$;T>3v$6-C-NH=_Sd+CevkmDU8YL z;~3=(*2gYiS?kotF3NG)$i* zaq1G5@4_GZ-kY@xe?fFR|-D3UYGCx!rXTI-|Thm zY#XqVUf0g5=ymN{4d^}2cZHzWwQJq=x^}IHUe~VmAZO<*(Y0S8X3SR$xYy-3cKKiJ zb@yzLmt1#0*kL9=C}#5X_NF(J=iKk( z(M4}D{}Nox4>-zS%)i24%nyhm0KvT>0Jkx{Aponv!79b2@NT|01kmNt8vv#bI>%2*wc#}0@i`3~ChQ-l8@^n?HIDC+(FY&^-?iXVeK_PF z-;VK*WSIg~ps@S?*=vsEUx5#U!DU`DoRTfZEC8ICN>m-AKqoj805+QlgH zaAxezjCJmIdf<&dnF1OD1u_G;&Tjl;`Qo|JWzQ^2hf=|{mlA~Vy&}^(NH3JM+1kQ? zkd$)`T`&Op`4rF-=82zE;jQKb00hJ=0ss&xivR!we(8xPeoX~d{xKC0_%RL;F#s@8 z{Yw@CxOjXcL4AXf;I|TBWPy!8>`rHE1#P^Y=wMjZkh;(YzU z_yg_@-QRN|GJ2lVLXAX`p<9&h6>7G+kFLS>KDsjD+T7ei0L%f@ z)j*$y5iLW6)9zz01}w-=@&_rg&Pz5Xsav`<`cXm3U{d@GY?$_-dhuH*eSfJKI``X{Wa253CyQ{{$T&>{t zCq1vaX4lZhOs42nGt;!QcP^6w*$s!X<=lL>>?+zUj7~+Vm9sdD09{SvIVMe~mylQQ z>Y>xxf^2yVUu}{+oEfQA`i7(g2*2#`F2VykulT{B3hM1y~k-L1NC zJ4vEbgV+t}Vi16FHSb`DU%-ZFrzG0YZGP4*D*83?OgTGewzmTx%wlw6Jd~z=8C7M0 zwpp5^pYRr|2h0Wt$ZK>wF_BiedESu81l&#j(R_h+WfF+^d{Ov~Y7|!htns6%s8qcY zHvVWYl~-b0Sq-6J!Vn763cdYahBx)Q#TU-(%ExF`&7N{As#M5MxkRxldPDg`M2t&# zTR$x!b}cdL)0_Pn0X^^3>dJ@mgnSqYRAy_{9Gy}U@`W?%vmw~ruH=?!lealC$8Dqe z@*KBBwNfsNMFslpy>iX(^|wcgx-#gbkA)$AHl<{uOZjDo(o|DC~oPEeJibQ0@{d zn~8W;$`!IgW;EPd=Au`m?zx&T)^L0f=75niQ*H@8HSOwIq=mdyD_{s^g|kgiHbX$t*S{{Z#h-+$UG@%RU||I2g$IyKpTSOi*9C$ zjBduo*g9I_9UiIu);&*%c0-94^VMzJAuQD-BHtBaa-v=pc~MUx?_20;${qbsfeya9 zjZnVCrp&RgC=T)g!77h~ZZ)E!Kj%Rf75YrRIM7K<4yBEK%ct{GZbSD;9IK+-AJbqM z%Ecgw`sNHeX(*1{B-2-`xIwO#P(P%h8-#)o5Q_Hqp{fMx zYjZ`}k85g0?I`atOM6->Oo;Mi#`$a^k3DtBt;P`aMUxRU0+UpAPGzR3K8=%a+?`j9 zp?O-)RRd}S!P+xba7kVoK`At53I|?Hq%w4FU?vt!(J_%Ytb+IUq2nmB`9ejl+F zlONbOZ!A=<(ST}j8+oJH#2a2Z6pgm>#>U+$RPd%wsclpf$_r-u>QxgJTLr;}Zu{@9 zs|9^_HMY|v3`1YqvbdO|d9}lbL2mF*gzUsbJdKX$ofu7bUO2Jy&QN@OGygLKf?*xzV8NTDZME#{yNa`(XVbWKXSTUoh1oP`!rmJ4he2%T{9!y{GnUau zj+#{yk<0E;*j%nc*>P6<8{XwTF!;cr6X5YfAW8lpol0470wBWB^U$HK2e!`5(Tz4a z<8`!a2%F1o-L-XWjBX3$up4+IMoG3GQ62gny=+2+jSgsB)HFDKI|+hk2^W?LpWdyX zgkeA7(HJ^`rL&rXmp}r9!R#j-84XUv(gYdT$L|e!(L!VX|MQC$OzK7}8kuh6Fy3p_ zt0o8OCbH4Bx=rAflXZR073(on*hxd&8=QyMUbO~ivC2Q_$ZXN8*oEpoz43W zngQEWY7OtkD|ta{!?rurNIV|fsY0~Fv$|vZ#w#}f8dAZu+A?;0uzye;Ub| z6FgiG9%>i7yB<8;E_hEpcz3(tz4hQd?Sk*D2k&hcyssX7XS?A2_27L?!IU*91A8B{ z8hG<#O+CU&K!{ZW?`>=XSq063Mg=3RfaXA>fDz7qbD+uo2xnddYWe7myB3cCQ%J`k z9q?8-f=vM(gKSMfMzUj&tSQLIbqsPf1sSQ1K`IfXh2mXQS!sZzSR7*If=3G05-3G$ z36#RM1WNH_pq39`GH9&N_eE0ErC+V zmOv?DOP~}`25R}tuBog`vu&zYCf5>;K}Ffxuzl)QYS`+F{F~5XQ&W)g=4j@DJy>y= zrpLL)u>uW_{B)#2x3^(ycn@Yfe(W#gCl&1^O8w(YFpOsCtm|gPgpWWcje~!E z4C2vevNq!MVWvI~oH!cP$AD9xap~hgg>x!>3}m81AR7^M7^9CsJo+F*ABVvy3_%|Y zXz-M4EN+;?_k3bZTj=1`Ln2j-UXv-G1X9qEYCZyjrsz;H9|M+D()VNh*n9w%2_;gj zuW8G(M^O1;cuiu$bBl>D?bLMREsq!T^?#vw3aJz!UMTua-*`ZQ}Oe3Gt| zf0~3nWJABF)k-kub`T+dzE?lUBSUB1(`h2D_*8r%8HxZe9fp=7CI8%tMuD(Py%yT7 zPcw=>3Ci=RTgJk!kCe$cH?CoCrzsf}Gwi%d4_w-TgQ{8w+!&xh04Wn(fo~i$O;*e~?};(={%0#RN<}r0a#|#dfFJ=rp^{-am+$v)Pf!j(SV4H@nfs+R}1U5PKrG2Sf)J->>V^ zMTy#S_=Ikq_)M;6u-$%rZ}~%?@OMbp?xoG%O8d%sK4#8|&zD3kiLcp_q%X@HkIc0? zm#-{!n$hOQ%2KZxwcluVqGs<>v$NjpJtr)CB4T<9O?X(>=9|kKy~dTL-twiD_Ug0B zskJZm439oDYF~_sh5XUpQup$stm9#3tj4|yn9%{d!ko(g=ZYM<$1lmzT95#wbnP6F03^lQGVgg z<>m%#MVFS=SJs+)reK)z%y}2Iw9;B%ZM4=mHhbMCRi5xgrkIXmAq21|Vtm|j`Y~Od zKflsxNrPZ4Wnm6Er-V=W5r||nhU7g+;ht}FlE6*q^=Gf_6BTO{w0QPtu#Dor38PClmOG;mD zt-r7po2E4CHal;$mYV~^r)unpaDSm0EF3dQ(%9T!kVdk`C%LgYs<_O(V(PCob%QCG zfGN!vuCzO^YjU)-ay6^WSm!GmpqG2{@77$=ec3`s@}m*=3#EL-G^8anZY`~~x_dXG z|4-KtoWKQjo!1-7>Q80em77;0lM|5>y%5b%Y;Ts=n&MY8s0e2k)#|zWVy!V>s5eTv zTD?)IRx8y=v#e;P*;{I@b)!9-OugsYgMBlgb~>AyP))N!D*D@~+FV+T>aEMoD8JTT zemy#(p3u1}E7y>>vS+ORM00Cwh^gze!ina}307-NvSbmBh3Y)3luYK+icAvom15~Q z5H>_Up+(v0SNk_X;#q+EasLAux;gi83TThpP$wgkiOesc9yjSQq~ezF9d1$tkNd^A zeq;&&@VGs&DbPqxj6K`m}l1drQT zd59a!1~=D{a5Gi2xJiLGDwgXJ^>sD+v{n--#|Gg)M`|Se4-3%ZCq;0mjXFcrPUPoC zRwuJIi<%U{p*GqKQIikXBWrU?6)b8}1c%xvGek`v0QJbqWaeQ}lOj0OMwcOKx)`V_ zA4%4%1}$n*rgxfsIJ8Q_Xw&-DNLe=QNShy49ZP`}!Q(dS3~}#Roh%nEZc+q~+vqdI zy<>fTRM;$TQUs6NC^W>qV}-J4w75wTJZ_`W5ciHX`f*{ixJem}&eA=hK*DGgX{g(p zUw)*~S*|1549iAKffT{xHX03aJE_lNqa)#F7G!bT`B048Xf(v_Br`j54`p}S;wDA# zd>f61xN(}u1Wk;@_hSOIxJeN_ZlloLwRFV1R zXGc0^gTT@tMd%|pN)3_2ILJp&V$edI>3A@UvT^{~)c8T`)R>_vQk@a*$(u5u9_9<1dbVw0k8wy6X z!xVO`;HQPpQXoa}6pVg{DePFw&j_cbK#Jfg7$px=*s-dg6;4Zm6v0z4njWUGV|{;0 zI4uQIh#;!xuwNMm4BohUoPtrA=(QDPc@n56Un%Evb@_IfQGgM_Az3HZKFWP` zD63K+2@cY93F!uw2p-bklcgBb<1U1Uca>TxsBAEVynFhvo3GD4X12XRM?B4s3rb=k zHlUK|>{6%2X1&>X$in(G`(#D(&SdV?h&e~=(qIBUbd|L%rlHej>&O_h;pW(*_ zWcR+lUN9ERq@I*$w{7{7wxOmCnS4OTR-!u*nDj*X%}z%TmHU+~f2Q31pa=15Y{<*j z>S1wPJ$N!A0--@YEGG02^%b!gw-Kov%J_R$l}-_h85x zx2@N9GD(X5kTGdhFniT~_)_a~t7n7=k%aIM^@Sf>NFaPRFys13B^)w74TATe1TR?3 zC0}23y#bRVo(=?v?EFGs(opH$)L<|K#%wXrd_qJVRAjP48O4AlAMk-@9yHvkz&u%r z6=`4tiWb&(3%kATV0kpKmD(TdE6~VuNbTiK?Z>8f)d%~IarCbGU|;u40SCJ33kmD- zc6}xg2i@?&gazPW0`rMY=S(0QThVKj1yP@x@ARgnMy82=|DcgO^1la@^Ca=ZvxQQj zUeK5Z6$M&I)YyTYgbp5E`pqB}DF9e1lmR5#PAd?5V{!mlsML}mwA}}iF)Q4KRDqn# zOa$=09@lVK@w|a+uAy1Q{A0$Ds7g$XEPn4vB?4(rEdzP^6xng-XRtwr8cdH@YZ+2O<4l;E} z7i8Q(ll0VlOXPW!6r3{&i!=TWW$x)B^J2MHsA?KAfgBaMY{xSLV;r{QS&#wGsU{_m zfL)+tmbgor)CV&A1NfMYL6h<wVjF^G3C7+S zAd;R8=_JDs8?6}7#80RXPZ!qIGsUkX!DSnM{jQ)z?STjSHbx;ZhcCgyKu7e*pm(|$ zSTPyfFyZ$PEp7k@7(iwM2^aum$hk}n2nuMx#0SZwRHym^QsF=drRo{Oq^fuKEPk`n z;`1B~d6q}|P1%uWd8BXXJMb)?C43|cV6A0x^@8<}unCh}Ou}H!hF}uLgy;=F7x$IT zBT;T_AHiTg)Ndm)j0zl@a-MS=Kj=v^L9G@RO1V5E6lzqUlb8;*#p=fIwi;j$nd%A! z3AZkgEb(LWur>h%PJ(+)hu!{>iTAi32`0Z(xC`gMs(01`6kJABm z3nwK%W(*7%0?3GVN<@y38z?aNV7%6>S?XA+Sr9*z0_M3&Oe#Kx|LX_v4&;$!A~ zTOTG!gre}xGX_#Pog17ey-FKhP?8yD9AFK5$(M4)Kxnk#;{(dFJ)u;{)y%kOF<3Bg z_y8@~m|3j77Sp9EA2*KM!-dzdDV{rU)~bVsXPcL_DZhDdF>c}Y9vx^4j6oo2c#oP~ zi)ipSWYH5udGfpE*<4j8whPso&VtLYxr&}f(s=yy01F0G8XoekgG6+n*p@F*G#$cY zX40T}jCSD~`O4{qTs2q^&}t*bExfINq9CvsGS%A(5++?BIZQVOpcSeST8gi#E7J9? z@EqVYT`RO#*Wb7s6fh#{_BzlB_uVi{|NKHl3P5auks`|%Og^?1j{{74^}|rqsRN^v_)MQCl<}BO$h~B|G05-+m5GkAu>ckJ0-{XD%cLF8_JeMog3eQIib$76->rS8*%R0fk5-km|ZP40r$nu5$9`8F$%rR=N zEp6y%nrT_2jD83^wAYZ;W_ep}`o~JvoOY(oC+=07PuxwLfwt0=87kXIEvd~X%$_a6 zxp!?o(bwj*@Sx3lb#Yr|23)7=@`-!UrPmK8S6_I{V8HaY>16(4-j*r_7ctq%p6u)M zuu7wPr?tvqcn%TT{bU`GW@ha+89H-5Y>fiV{@%*H?))eXv0ATqAj zYmLI$Lb)EhE?)^DGxQ6`9s3+wc?_D12b2x!TeTVV#I7hTW^(yu(~|WtJc6;MeDgw%8wkiy}Sq~LjH*3>t)#$2%^BN)x* zFc56+DNlUh8rmEXKo8QYRTiuH!f3P@QlRzp01bZ=(gFf#mQE~~v%Eq$U#iS#b+0Fa zwR-kBQUk}Fmf$teiu~s-AWaiBls3r z6W^+t5=>^OL>vaEzj*M9S!+)kd8R|tY70G6n5$F^jVdch%My}Fuf0qs5kPj<+amZJY8s1H1(e=Rm|bNNu$1W z3@i>q4Ciw7{K?tMJkXP74Vqq$5iP8DQp=5Vn$$N25wIjpN01~uS1gofwLY_i(f?@m zij~EMS#2}fdgwO29-ca6xL7I`=4Hj&P}YpVyfSN1FifSRU`7_A$mR2eTCH)mSSjUr z<<{0`20B{(g=+EaFnzXz)9bU83h5WijfLEN!M-J6iDN?Pm07`rmDN@9rxIquUSE1` zR+nMz)5Th@RGcrL)|hH3)63KAvUm>b=Bm})YcrL_@~l%foh7|$lI(2pY;m?Q^V)A0 zsufF??wMXUX<&mrf)OyiUQ$qH9ek*i>&5b7Zl>hS4BY9plQvSWH0Bl-8@aQ&VkxfA z*pptLl2BMw?r(WcYUgFEicw0%*+RKeJuM@zEEKBR5`g5S*=k8Ao@5^4!y-p1>Gcn% z@K7wDm8HyD7UEulEvF+%>KrBpb%%!1>#_n)O3xa4{$wF<9=c7MHF$dUSoJyQwR1Yu zId9*YcgBj0(rd@kb0fvMYEfo0->59s_0GMkkK;_QkK?h-ELuY3$7lq zINvB${9xuMrLxk*NEwVU63FbLx94a}D)bXerBW^x%Y{b%WUf5#y20TstHoyQWWi|W z54}v9NltpJVjow})lTIrvxP>vqJd4*fP%AM<|OHrWA!^`^{nu0QBJxsqY1h5&p%h) z^y;w!N|iqNFSZ1a+n8Uh)hnkPo*LLEGr!!jV%)|;{iIxY{*>PL!o*_%@mgFulYuu? z<#M5}gXE_)zsSv+oz2M%FQTPajV)$Isyw9$+^kb1FMFleiDjbG&5db*CNsQnH43=d zL7&Y0bVP8oqc@rP%Mrm}w9Nd~h~O_-@Slwc{;~!CA0vXlV!{722vj=4CS|=Tz`JaQ=T)wQa%MDtrS< z<_il<30x)o(_JgcU`1$g!H=ilORt1ZeCvbRVmdJMNV|k?ES75vg?v#95;x$e$Si_~ z1x)K*E$w~O3+7psU3<#5QZ&K<>?%|jHK{!9v=3A1HE5r!p^ud;R4enRYp7r#0FM$oXPX^9vBCYp%zuimeR&_7Psfi)NTcHa!5d@VQ(m14>1SlO-^ioX7?8ALl%|!$VQ2V75hxXZ&xz$eyXuMqr z7=ng?#?6I*2;7Gd(D=6y5RQEa0gayu0qIgcgn(wa3IS!?{SX40fhq)KdhSCAXojc| zkm;}wA)pzYLcqvF=?dV5nRa{43*44jfj<)fqMZv>UW#8&1AR6CO-pWT23qdT73Z^` zNvqh;<3nFwx_&ciQKhtuBenqI9=EchWzi!2vZ9I@D|{mJFEUdELp(r)iari1V-82 zya1jPiWp=vpEA!1X~Os-LA$joxSm$@mSA(pO&IzCOhyFJ9|`v9Va_Hap(he3$( zc>#mv1xoB6z{g-NC7~SR((&o{wS0MV4LUC>4rt%yQ?~os$00UW*V-3keqI;M8rsF8EI2gc@CHG!?1NK;70K@Z&-X3iZxuG5`?D#ssrY`DZPrb&{a=QzaSw*xk zTteyY>%mxc|4=YASQzws#6St9p%ez|jxP=Tpblv9IXMlJOY6o-R+NcAQVZc|_ho|T zHv{ro69S)8go8vjMfa0-4+5W69HecsDcXJ7%<`QzUNFY^TaNlr!Tq5h+kE$TI;NdP z$G~vO{o$am;&r3>R~-37_WhyF`d#lWoveeNRT`aeAd`Y{hSDz_zw3d)zBdIC8GC;) zigPImyMJ6~eEQbqYkst}vZ8MR8|%Z#V*6=j@Zvkb5pERha1h|gl6$Yi0Ve0x4Enw) zm=+Y_XSjq?&kbq9_%dOX(@QWQ;m$v}5=wW! z;V}pL{IBr?Cx%kAZ9h0$A9cwg4SpabTz~c+)-V zI2+7`nQ(-OOUI{=EZpZ;Av3M```QagWK+aSkPw+)YgN8xmb@1f{o@yQYYB99B4Zi2 zNhd?NJs$TXH>dcrpa=WWeVuHm>2|T_W_d3;^2vPKu=_TP)Ogz;?95*=(lC$w&?>@@Af2R@QJ&-? zG**Kn3)H
COHw6|7fM_5QQ9~z;#hUMey1PryR=iwR0!(eWbgSd2e=-W>ZL50Ij z$N;=?E+t{#h)c((kJRJuV0bw|4L;IK;V0C{Fx2>bA&LG>I-b*iMcMS3EsEhRX|?0? z0tWkOLGWXLUPo~*B}pCG((&mtd(>xJAi+61hzD6@hm>8>?vT~60eX;YDV$qu{ zvWG>#IKJq?P_20~!ebitaw$>Mo<%JGoQPcjjfkI%(~;{qy&6_G-iM}8;*Up78vo^zzWtqjQ*6k%ms zAOORm!2qYdPCP!dW|bAcTJ2w~hJ#~@u(}NhU?HOhG-lMl`#nCJ7^rdI&EJ9M%ZhZY zL^egc-=%Of@e_SBxq;9rMek-(iUHYuUXY~yOdZfB;h-}>Rx zN>BfV?$6v3s5Vco-`qF-jay>)FG<_`|8UEsr~lm4`DRL;{fRpJrw8j?N~trEs56nM z^HNHkLy0SPmjvWYq?DRr(T>Re0Inf|(X zo3gr!g7j37&IIZAz81s(TOT)pUB9{i#`T-u5!@lcWU|*yKX`chy8238{p9-7nd$2~y z^_vsZ|Lxt0=|6vWU-lpW`0wuA>Gz>EL+eMTp9!^rHSlj8y*+VF@y5~H5ir;O==KLi z^U!;??@iqJ);kl|6yN&RJ9irY{wKH{+>wUwNPRw%--_gDB2B;|wINc!jpQ>TfkcO= zt>f9=J>i;&KU8(Dzj9Y4@9MU;byv96#wGo?$Yuvm1uXc3Y~7g$MB=j_-cd_%#uIAc zlwf~-hYB{_5o9pc2)(c2GAN$`iI?94xVcVg;W z?;vDE2)o-04{m^Z#$9z8PiT-EeB4f>7)lVzaH%pgSr-SI71-6|cd;v)dtNOWy}2yS zfF|7SdUqRXZnX5A92?=?A@CU+vDt=%^6ZyZ4`vQcOi#Qz@%F^84nFk0J9qk<636WX zmt*WFY?8CfFWMygDKGVBz%SdB&iB1yQ)@jPvNV|1nmX!fQko@w-ldwEFAUCJzL;36 ze#ruA>1y8V_|4!1rDRvK-EL>7E~>U;n)uU>z zS}fGgzj&fCQ>>pCnDYF0#Ew;FzCzFR4q$I6(l#iXfK%AsI{~)ez~24Jg5aV zH9L`|5Bk<*}Y5unT94$&`>ssoWSu(tb$X7n`$WtIffyY*K2FqjT zN`L|!xx)vDo|fShgKXVpA{Rq%$gG#qmgq-Os_&lo?%I0&)8YOzQ@GbK7mrgxnX=8} zLJfZd6L*~S|09-p>IKUv2Nuk*>sa-)Dzm?qtCTF~js z@c+A>t!1ZXJu)+Mq=1qowQdqUUubUmc& zJGwrk>yLDu()EB=MBh6uSownoGG}h?%W5W{WhP(0C3j+H=bG(LEL^|!hx-oPIFSAN zyZffT_T#?|X7u2gh_oUQ+&@3_?b~lIS$u!6?|~Z+WdDhQKM3v(;oT7a%(+{?ymQCk zo>tvIedO(%`*r;@T_4c(-|D(g*MFz$SzW)Y>p@*#n!0xT$kY$T>zP~HG?75A-;Ac- zy8TS_mR9bfpR;r)GPRrg7DQ)(b}ZhKYqTqp1-0RUgEy3a>)^uI-aWXWwoHHH$A1&F z#jI?yU%Ne_wtQznvJ=b)zk2=VH3*Mj_ql>ey9UkUQ3lt1P2 zPX_sqDnIM;pAYiiR(|C2r-J;@XTSOPckX;n@rdG-;!pn1ojX7K-*@h?%faH{*K81H zGg0P8|Mf`bXNn95k+r1lof5W2{D^+I9&uMC&HZ-QZGAtBwY)65TCC+6tytHSzvAFY#i5+2w>-0K^X|x>7a5E{01K zL0}DFMKP5F6Q@!+_@LaJ#42y9a>&64A9Bb+sd70#<%3dDTsinCT4G7E9Y={J#|KxK z?|a>i>G{LLan<(LV0ya0_xkmFuV4RQu%}Ng-*LimoCCO+?!fgBuG>hsxy~{^k>vR& z|9avVcU#XtNIWkq{6Pg#pKshHy#Mz*2ju=Wls>9z{za#QPW(^R{`u>V)>KY^egbz& zHyXEx<6gTQ_TBB_U~AaE>PqE^6alW)R;AeVs}*;2eKZcQhA)Nv@#o#r zg=)Rzo-fn`zfx;8-Oe@7s`vt)SG&D&IMhfMRIl}|XRlHUK<-M1zW=1-%%QE(c(DCR z+_R+`Z10;;)INo}2ltKe(qI?{!*CRies-2u)vwJDynW z4zFHo4?}lnyVD+r?%<_x=!WCV;jkZ$p8%JAQ87mfyKory@a4_zad53Y-n`ryY<&tP zjlrd{$Y=`P!6n!CiYLeI(G@p*dAmCdJHYLWsCS{AxTu%9VXw2XGotXTI`4+V;b6F5 zG960E)Ey{$E}-V@%FbwiUP47>%Sik2cJf13D2YMpzm&6cUktN zTkZF*yWRdc+=2rR;Gyj?>PN=`-WR)4R?5u4tz_;G`kRCPxZB@pZ}h_ZQ0~3F8E#W7 z_j0@6>4p1dUGrpRZhw1cJbDE6iC84n94HC_z`m&QsFw5r+;u#^Hta%) zTftywOj%vjXjye=(f|spF@Wrgw2a}@D;*Z@xw94Y27_&`C`x>C`Q*08?#3`|U)dhO zJyEqUl5zf{WcT7e==Zw)FxZ6CZH1pffj@FL)pA13JjFpL^!wfMi6Z>X8K zQ;PbzB=sGD8*1k5l%jq0gQLkKVdSY*-TXzCH;Hgi@43{h^eatKno_%q z5|u!Ffw{eiMQ1j#?)8PKI@2wS%4}jS_Jye`)5M}No0z^uv8QTG6N|!ZVulqGvp%=a z^nISOh{n_)bWxlgbpXWODRn|e`G zvn-dIhLHn3aW+cwE2(WlE_$=c*(zn9s<#QbD9$FINpTZ$(VR^_ljbJmqB@&=Ce@Lk z?iJMRPhRLSd%NT^D`_UTBM(tun#W8^G;)Xz(>!L?;JmV{9JrwPoF`=5Q&d(;&2?MT7D7b`lR0B{`TXz z3XP)gbCwU9)j-Meu$)k%4j%0|9E}^-$INnAE332fQDR*VFILTKLNYjrf;)t7L>}cR zD4gI%2Sug{s}#5HcLn3be-&Yt@A@CWaF`l6l|a%n#dxVY%Q3cQSrrQOZx&F z<+X10kW%m5wQ3^?VRuYoHWGzTcB@1#ICB=>(D7~u z9U~igtp=D?){cnzNXjb_cX&DxB?2gGv3xdairu+ecTGWA$15>d?vA;ef~rqj@1{li z(W+l5MOvrwS(+EmIUz?$BQxVUkdge7HLV%Z;iJd`r!5}wRXJOwrd_JkuQa?m=Ab#M z35mC9GIJV_(lnWYv}Dfo7(gs>iH=0#Q_^GZbq-qiNQ}707!fI4*;{4jG!<_YBxe{L zwmB*-_+R!Yi0TL(2N?ArSY}N#%qImtELIU{;={IwX_um5;6Yy91aDL1<)L_#3^+D) z=@fuzei2yZY#|IYwzuwEUd)0iLU2VGB?4mtP-lQx0uYjl9g8tV5ltB6U^c1M#fgGY z8B2DDj9_%B`rd(q=gmRzo}D01$g1(4|9dYqpkbK4rU zE|-W^*)&Xj)fRXHtizb&fd$?%+oqE_#p$-hmD6sO)S9+6k7$d0{EOxyfkH%hP~zRJIJiC-iT ztk>MgJ|M1WkYvV7Eml-1d+`AMV3OE=tt9Jdr8NaHvmkLss>C>cfT3%W$fs!Yp(-Ab zZ}uk`D`O9J(>-wzZ@my-!o0vf>V)irCNFo2Mt>=m3%;c^_Tj;pvD8Q?dxeHfS&E5* zk%viai(;&_8W*E>*_8*yaSYDB+g&lzk!PbGcRba-q)+jC?39## z3TQDe>-0N?qGl164mTOcW=iZb_85 zjcV}i%5?BKI`JLCDH1PVc1kRP!Xe<%SnwgDCb35aF@=~R_8g7H9)jHJaMiD@DdEWVmELbG4>W+U*Ncf6$5Z{0#-skU`oqi~9iOR3Mh?zh6DJ5( z{W6R*n=jCC^o2)bJu(lrFAza=ysbvHRWEw8wZ-7XwjML=V|TkPB8cV!mfMzPzQVp% zuC8GJg!A-9bNLCB<|p!^oG;=sUm9?Amf{nX{T0p2M?GCw22ub|hoqKwVo~`gWF@~9 zK#h6@Oo6fds7v%;5T7Su8cs(y@T%;17DS)fX!cs6SG?6~-3#hm$19PjnQSUc$i->F@E*P|6XIjlt^@2=w3$h-~reN$*6y6KPS~DnKEaD{6U-yD47GSI8s(jbK zAm+>Fz$LoP;X_sS)#l2yaB z|7>)AwN)!&Bd_Ra+iW^UP+MTXT=v%B#W;~`)?4zE4aI^7jM*$Wx7#cV#iG|}1n2!~ zxxk-%D0(h7W}~mw{qyPed7hR{&jqdBzF!Gyg*8vTrKTFE3uO~?9cdF|s1(m8+=Pcx z+0M}*+NzYau{l_>Nt4Z%{PTXvTe66(O4F~j3M*ypX5^hso%E4PHCU~+g2MTNUykTG z_hi$v##R=ICkIUn*#G7cx*3EeuTrhA!^x{Pua1own_Q3$Z+7EJ;n{dvLeq6weeYYkC+Q&n1i8SnGnbnfcmp zK^8gLy^3O7v(PwOtd_i>QpLoEWq_ysmur%2;>i43SbW)X-bauQR~*$-#MYt#OGR=l?D|K#Gi28;Cb^l44- z4%Y5eZ91?<`<3;AoG)XLQnBH5f#cVLwk!lMav?`67SM;$V(Gw1;WD}fLFnh15aE{URIH-R6^*6P)@dOcUd zmWZbjhv&l~f8xpKJDq=WZ+z(hPgzbqxwLc&-0qC;#Iv^hobA%veRY)m|2RG1`YDf{ zb%+2|X3CO~!^C2#h2kis3&|Y@kFt8)!pqpoBRaNQIkZ z10}xMKuTUirYik&;-4}INHJi-JJWl-fN*tgUBIkTo^GFo$O)aWB2pE3?ME6LePt+Z`I<$#CXdIYt9{YHbDBY-IFDLc7mnZV zbnu@`q#K;7*^R6^o6ia0n36ckt_L>$p8^pzT*gD7&ACoJeF-W8X?WqaDj_MJjX0$q{Eflj98*x^op6A#Y1W|6MR;~^meKiR(2 z<-Y<^6VaUJl2vE(ffGnd;-~>->|UP$4;NLNEVp?PXA&*B7LLbwCyYgPTqI8v=TUPf zIdQefZGTsD$*Ioc#=cF~RNB(#G^?z-JU$bzKsX1vb4v3_mgmt^?8fzx{8y1P(f^KV zX*N04dE7X5cepI$(54IF+4-X8m06j`iAE7048KAir!|j6aUM0rj+Pr@HF7ztx#U#m zaho){C4TdH%_UL1H?_=2pG#3oaUL~&A*s+WXck#@d3^Y7Hw_S5^K#3;UeH-ml_-<< zExFdc_dB~cofl5Nch9$RcfNVc`I{r}@n6w#;lLpKB$g8RZw(`784ps*_E^g_>z$G7 z$<4vlt5}hb?!W^(!#fi@Yp-noO1(-VvM1|^=W3RhE&A=?=7FWJz6F7Q#Jqa`hqolZ^j)F(Mh4Bn1kJ&vIL+k@nz;ncT!QA= z44U}_&3uB!$)H(G&@3isUVk*L12;kACTPB%L9?8oSx(S&GH7ljXl^8Emi`E`Eh<~N zR({dSJ68VvKaB7nAph;f@7<)G-?Z|tTlv?l{I{(9-&y&;w(_r7`5RV#+sgj|^3LL) zim$wA<;zz7i&p-(to*W-f85G1T6xFHzkefYYtAZv*DC*aEB}vH{%>{uu)BK`zW?Lc zFKaP=4lnNBJox7B&2IrW4~(I7^C=}arfrj(!aek zxAfh24lMui4}W(1_GAq8q^%#wI0I|J3jURox8`o(dh_HhmzW!0zx7eHIsd*IdvkBT z`u5xnT(7+P_U+*B-(}cgIKrguV$8dUTP^~Pi-m=YKDZdSE@FlYhBGhsmrf~l3ow>zV-=+%K zK?*y)Yfyxs9@lr=e!VWSx%iHPonoNp{E@Cjp|h;7Shp;zAKk<1?C$TOC$o2#s|})= z_PS5CASXt>9biAni~Y2U@uYkWce{g}W@O61kT7n$cL&IAFM&<{RKaC7w3gnK9wQ`j zJ*$q5Vl>HRcY%7}N0B+G`M=`oexpbw&rv296ZmbaTb)M!@+q|*L9j8WldiMOTK)WM U{9E0B9{98
0
0
0
0
0
0
0
0
0
0
255
255
255
255
158
88
97
168
\ No newline at end of file diff --git a/tests/IecType/output/test.iecDInt.php.html b/tests/IecType/output/test.iecDInt.php.html new file mode 100644 index 0000000..1abf31b --- /dev/null +++ b/tests/IecType/output/test.iecDInt.php.html @@ -0,0 +1 @@ +Endianing off
0 --> Packet: 0000_0000_
1 --> Packet: 0001_0000_
-1 --> Packet: ffff_ffff_
2147483647 --> Packet: ffff_7fff_
-2147483648 --> Packet: 0000_8000_
Endianing on
0 --> Packet: 0000_0000_
1 --> Packet: 0000_0001_
-1 --> Packet: ffff_ffff_
2147483647 --> Packet: 7fff_ffff_
-2147483648 --> Packet: 8000_0000_
\ No newline at end of file diff --git a/tests/IecType/output/test.iecInt.php.html b/tests/IecType/output/test.iecInt.php.html new file mode 100644 index 0000000..583ad9b --- /dev/null +++ b/tests/IecType/output/test.iecInt.php.html @@ -0,0 +1 @@ +Endianing off
0 --> Packet: 0000_
1 --> Packet: 0001_
-1 --> Packet: ffff_
32767 --> Packet: 7fff_
-32768 --> Packet: 8000_
Endianing on
0 --> Packet: 0000_
1 --> Packet: 0001_
-1 --> Packet: ffff_
32767 --> Packet: 7fff_
-32768 --> Packet: 8000_
\ No newline at end of file diff --git a/tests/IecType/output/test.iecReal.php.html b/tests/IecType/output/test.iecReal.php.html new file mode 100644 index 0000000..a195b00 --- /dev/null +++ b/tests/IecType/output/test.iecReal.php.html @@ -0,0 +1,12 @@ +Endianing off
+0 --> Packet: 0000_0000_
+1 --> Packet: 0000_3f80_
+-2 --> Packet: 0000_c000_
+0.333333333333 --> Packet: aaab_3eaa_
+25 --> Packet: 0000_41c8_
+Endianing on
+0 --> Packet: 0000_0000_
+1 --> Packet: 3f80_0000_
+-2 --> Packet: c000_0000_
+0.333333333333 --> Packet: 3eaa_aaab_
+25 --> Packet: 41c8_0000_
diff --git a/tests/IecType/ref/test.iecReal.php.html b/tests/IecType/ref/test.iecReal.php.html index 661237e..a195b00 100644 --- a/tests/IecType/ref/test.iecReal.php.html +++ b/tests/IecType/ref/test.iecReal.php.html @@ -1,12 +1,12 @@ -Endianing off
-0 --> Packet: 0000_0000_
-1 --> Packet: 0000_3f80_
--2 --> Packet: 0000_c000_
-0.333333333333 --> Packet: aaaa_3eaa_
-25 --> Packet: 0000_41c8_
-Endianing on
-0 --> Packet: 0000_0000_
-1 --> Packet: 3f80_0000_
--2 --> Packet: c000_0000_
-0.333333333333 --> Packet: 3eaa_aaaa_
-25 --> Packet: 41c8_0000_
\ No newline at end of file +Endianing off
+0 --> Packet: 0000_0000_
+1 --> Packet: 0000_3f80_
+-2 --> Packet: 0000_c000_
+0.333333333333 --> Packet: aaab_3eaa_
+25 --> Packet: 0000_41c8_
+Endianing on
+0 --> Packet: 0000_0000_
+1 --> Packet: 3f80_0000_
+-2 --> Packet: c000_0000_
+0.333333333333 --> Packet: 3eaa_aaab_
+25 --> Packet: 41c8_0000_
diff --git a/tests/IecType/test.iecReal.php b/tests/IecType/test.iecReal.php index f9ed82d..30495fd 100644 --- a/tests/IecType/test.iecReal.php +++ b/tests/IecType/test.iecReal.php @@ -7,7 +7,7 @@ $data = Array ( "0" => 0, // -> 0000 0000 "1" => 1, // -> 3f80 0000 "2" => -2, // -> c000 0000 - "3" => 1/3, // -> 3eaa aaab + "3" => 0.333333333333, //1/3 -> 3eaa aaab "4" => 25 // -> 41c8 0000 ); diff --git a/tests/ModbusMaster/output/test.tcp.fc16fc3.php.html b/tests/ModbusMaster/output/test.tcp.fc16fc3.php.html new file mode 100644 index 0000000..00dd046 --- /dev/null +++ b/tests/ModbusMaster/output/test.tcp.fc16fc3.php.html @@ -0,0 +1,72 @@ +Array +( + [0] => 0 + [1] => 0 + [2] => 0 + [3] => 1 + [4] => 0 + [5] => 1 + [6] => 0 + [7] => 255 + [8] => 0 + [9] => 255 +) +Array +( + [0] => 0 + [1] => 0 + [2] => 0 + [3] => 1 + [4] => 255 + [5] => 255 + [6] => 127 + [7] => 255 + [8] => 128 + [9] => 0 +) +Array +( + [0] => 0 + [1] => 0 + [2] => 0 + [3] => 0 + [4] => 0 + [5] => 1 + [6] => 0 + [7] => 0 + [8] => 255 + [9] => 255 + [10] => 255 + [11] => 255 + [12] => 255 + [13] => 255 + [14] => 127 + [15] => 255 + [16] => 0 + [17] => 0 + [18] => 128 + [19] => 0 +) +Array +( + [0] => 0 + [1] => 0 + [2] => 0 + [3] => 0 + [4] => 0 + [5] => 0 + [6] => 63 + [7] => 128 + [8] => 0 + [9] => 0 + [10] => 192 + [11] => 0 + [12] => 170 + [13] => 171 + [14] => 62 + [15] => 170 + [16] => 0 + [17] => 0 + [18] => 65 + [19] => 200 +) diff --git a/tests/ModbusMaster/output/test.tcp.fc26.php.html b/tests/ModbusMaster/output/test.tcp.fc26.php.html new file mode 100644 index 0000000..7991aa8 --- /dev/null +++ b/tests/ModbusMaster/output/test.tcp.fc26.php.html @@ -0,0 +1 @@ +writeMultipleRegister (FC26): DONE \ No newline at end of file diff --git a/tests/ModbusMaster/output/test.tcp.socket_protocol_mismatch.php.html b/tests/ModbusMaster/output/test.tcp.socket_protocol_mismatch.php.html new file mode 100644 index 0000000..b25cfe4 --- /dev/null +++ b/tests/ModbusMaster/output/test.tcp.socket_protocol_mismatch.php.html @@ -0,0 +1 @@ +Caught exception: Unknown socket protocol, should be 'TCP' or 'UDP' diff --git a/tests/ModbusMaster/output/test.udp.fc16fc3.php.html b/tests/ModbusMaster/output/test.udp.fc16fc3.php.html new file mode 100644 index 0000000..00dd046 --- /dev/null +++ b/tests/ModbusMaster/output/test.udp.fc16fc3.php.html @@ -0,0 +1,72 @@ +Array +( + [0] => 0 + [1] => 0 + [2] => 0 + [3] => 1 + [4] => 0 + [5] => 1 + [6] => 0 + [7] => 255 + [8] => 0 + [9] => 255 +) +Array +( + [0] => 0 + [1] => 0 + [2] => 0 + [3] => 1 + [4] => 255 + [5] => 255 + [6] => 127 + [7] => 255 + [8] => 128 + [9] => 0 +) +Array +( + [0] => 0 + [1] => 0 + [2] => 0 + [3] => 0 + [4] => 0 + [5] => 1 + [6] => 0 + [7] => 0 + [8] => 255 + [9] => 255 + [10] => 255 + [11] => 255 + [12] => 255 + [13] => 255 + [14] => 127 + [15] => 255 + [16] => 0 + [17] => 0 + [18] => 128 + [19] => 0 +) +Array +( + [0] => 0 + [1] => 0 + [2] => 0 + [3] => 0 + [4] => 0 + [5] => 0 + [6] => 63 + [7] => 128 + [8] => 0 + [9] => 0 + [10] => 192 + [11] => 0 + [12] => 170 + [13] => 171 + [14] => 62 + [15] => 170 + [16] => 0 + [17] => 0 + [18] => 65 + [19] => 200 +) diff --git a/tests/ModbusMaster/output/test.udp.fc26.php.html b/tests/ModbusMaster/output/test.udp.fc26.php.html new file mode 100644 index 0000000..7991aa8 --- /dev/null +++ b/tests/ModbusMaster/output/test.udp.fc26.php.html @@ -0,0 +1 @@ +writeMultipleRegister (FC26): DONE \ No newline at end of file diff --git a/tests/ModbusMaster/ref/test.tcp.socket_protocol_mismatch.php.html b/tests/ModbusMaster/ref/test.tcp.socket_protocol_mismatch.php.html index 294f1f5..b25cfe4 100644 --- a/tests/ModbusMaster/ref/test.tcp.socket_protocol_mismatch.php.html +++ b/tests/ModbusMaster/ref/test.tcp.socket_protocol_mismatch.php.html @@ -1,7 +1 @@ - -Fatal error: Uncaught exception 'Exception' with message 'Unknown socket protocol, should be 'TCP' or 'UDP'' in D:\Projects\20081010_phpmodbus\src\trunk\Phpmodbus\ModbusMaster.php:87 -Stack trace: -#0 D:\Projects\20081010_phpmodbus\src\trunk\Phpmodbus\ModbusMaster.php(654): ModbusMaster->connect() -#1 D:\Projects\20081010_phpmodbus\src\trunk\tests\ModbusMaster\test.tcp.socket_protocol_mismatch.php(13): ModbusMaster->readWriteRegisters(0, 12288, 6, 12288, Array, Array) -#2 {main} - thrown in D:\Projects\20081010_phpmodbus\src\trunk\Phpmodbus\ModbusMaster.php on line 87 +Caught exception: Unknown socket protocol, should be 'TCP' or 'UDP' diff --git a/tests/ModbusMaster/test.tcp.socket_protocol_mismatch.php b/tests/ModbusMaster/test.tcp.socket_protocol_mismatch.php index ed016b4..aa5f691 100644 --- a/tests/ModbusMaster/test.tcp.socket_protocol_mismatch.php +++ b/tests/ModbusMaster/test.tcp.socket_protocol_mismatch.php @@ -10,9 +10,13 @@ $data = array(1000, 2000, 1.250, 1.250); $dataTypes = array("REAL", "REAL", "REAL", "REAL"); // FC23 -$recData = $modbus->readWriteRegisters(0, 12288, 6, 12288, $data, $dataTypes); - +try { + $recData = $modbus->readWriteRegisters(0, 12288, 6, 12288, $data, $dataTypes); +} catch (Exception $e) { + echo 'Caught exception: ', $e->getMessage(), "\n"; + exit(); +} // Should through an Exception // Print status information -echo "Something wrong!"; \ No newline at end of file +echo "Should never reach this line!"; \ No newline at end of file diff --git a/tests/ModbusMasterTcp/output/test.fc16fc3.php.html b/tests/ModbusMasterTcp/output/test.fc16fc3.php.html new file mode 100644 index 0000000..00dd046 --- /dev/null +++ b/tests/ModbusMasterTcp/output/test.fc16fc3.php.html @@ -0,0 +1,72 @@ +Array +( + [0] => 0 + [1] => 0 + [2] => 0 + [3] => 1 + [4] => 0 + [5] => 1 + [6] => 0 + [7] => 255 + [8] => 0 + [9] => 255 +) +Array +( + [0] => 0 + [1] => 0 + [2] => 0 + [3] => 1 + [4] => 255 + [5] => 255 + [6] => 127 + [7] => 255 + [8] => 128 + [9] => 0 +) +Array +( + [0] => 0 + [1] => 0 + [2] => 0 + [3] => 0 + [4] => 0 + [5] => 1 + [6] => 0 + [7] => 0 + [8] => 255 + [9] => 255 + [10] => 255 + [11] => 255 + [12] => 255 + [13] => 255 + [14] => 127 + [15] => 255 + [16] => 0 + [17] => 0 + [18] => 128 + [19] => 0 +) +Array +( + [0] => 0 + [1] => 0 + [2] => 0 + [3] => 0 + [4] => 0 + [5] => 0 + [6] => 63 + [7] => 128 + [8] => 0 + [9] => 0 + [10] => 192 + [11] => 0 + [12] => 170 + [13] => 171 + [14] => 62 + [15] => 170 + [16] => 0 + [17] => 0 + [18] => 65 + [19] => 200 +) diff --git a/tests/ModbusMasterTcp/output/test.fc26.php.html b/tests/ModbusMasterTcp/output/test.fc26.php.html new file mode 100644 index 0000000..7991aa8 --- /dev/null +++ b/tests/ModbusMasterTcp/output/test.fc26.php.html @@ -0,0 +1 @@ +writeMultipleRegister (FC26): DONE \ No newline at end of file diff --git a/tests/ModbusMasterUdp/output/test.fc15fc1.php.html b/tests/ModbusMasterUdp/output/test.fc15fc1.php.html new file mode 100644 index 0000000..55a3de0 --- /dev/null +++ b/tests/ModbusMasterUdp/output/test.fc15fc1.php.html @@ -0,0 +1,66 @@ +array(32) { + [0]=> + bool(true) + [1]=> + bool(false) + [2]=> + bool(true) + [3]=> + bool(true) + [4]=> + bool(false) + [5]=> + bool(true) + [6]=> + bool(true) + [7]=> + bool(true) + [8]=> + bool(true) + [9]=> + bool(true) + [10]=> + bool(true) + [11]=> + bool(true) + [12]=> + bool(false) + [13]=> + bool(false) + [14]=> + bool(false) + [15]=> + bool(false) + [16]=> + bool(false) + [17]=> + bool(false) + [18]=> + bool(false) + [19]=> + bool(false) + [20]=> + bool(true) + [21]=> + bool(true) + [22]=> + bool(true) + [23]=> + bool(true) + [24]=> + bool(true) + [25]=> + bool(true) + [26]=> + bool(true) + [27]=> + bool(true) + [28]=> + bool(true) + [29]=> + bool(true) + [30]=> + bool(true) + [31]=> + bool(true) +} diff --git a/tests/ModbusMasterUdp/output/test.fc16fc3.php.html b/tests/ModbusMasterUdp/output/test.fc16fc3.php.html new file mode 100644 index 0000000..00dd046 --- /dev/null +++ b/tests/ModbusMasterUdp/output/test.fc16fc3.php.html @@ -0,0 +1,72 @@ +Array +( + [0] => 0 + [1] => 0 + [2] => 0 + [3] => 1 + [4] => 0 + [5] => 1 + [6] => 0 + [7] => 255 + [8] => 0 + [9] => 255 +) +Array +( + [0] => 0 + [1] => 0 + [2] => 0 + [3] => 1 + [4] => 255 + [5] => 255 + [6] => 127 + [7] => 255 + [8] => 128 + [9] => 0 +) +Array +( + [0] => 0 + [1] => 0 + [2] => 0 + [3] => 0 + [4] => 0 + [5] => 1 + [6] => 0 + [7] => 0 + [8] => 255 + [9] => 255 + [10] => 255 + [11] => 255 + [12] => 255 + [13] => 255 + [14] => 127 + [15] => 255 + [16] => 0 + [17] => 0 + [18] => 128 + [19] => 0 +) +Array +( + [0] => 0 + [1] => 0 + [2] => 0 + [3] => 0 + [4] => 0 + [5] => 0 + [6] => 63 + [7] => 128 + [8] => 0 + [9] => 0 + [10] => 192 + [11] => 0 + [12] => 170 + [13] => 171 + [14] => 62 + [15] => 170 + [16] => 0 + [17] => 0 + [18] => 65 + [19] => 200 +) diff --git a/tests/ModbusMasterUdp/output/test.fc16fc3bind.php.html b/tests/ModbusMasterUdp/output/test.fc16fc3bind.php.html new file mode 100644 index 0000000..00dd046 --- /dev/null +++ b/tests/ModbusMasterUdp/output/test.fc16fc3bind.php.html @@ -0,0 +1,72 @@ +Array +( + [0] => 0 + [1] => 0 + [2] => 0 + [3] => 1 + [4] => 0 + [5] => 1 + [6] => 0 + [7] => 255 + [8] => 0 + [9] => 255 +) +Array +( + [0] => 0 + [1] => 0 + [2] => 0 + [3] => 1 + [4] => 255 + [5] => 255 + [6] => 127 + [7] => 255 + [8] => 128 + [9] => 0 +) +Array +( + [0] => 0 + [1] => 0 + [2] => 0 + [3] => 0 + [4] => 0 + [5] => 1 + [6] => 0 + [7] => 0 + [8] => 255 + [9] => 255 + [10] => 255 + [11] => 255 + [12] => 255 + [13] => 255 + [14] => 127 + [15] => 255 + [16] => 0 + [17] => 0 + [18] => 128 + [19] => 0 +) +Array +( + [0] => 0 + [1] => 0 + [2] => 0 + [3] => 0 + [4] => 0 + [5] => 0 + [6] => 63 + [7] => 128 + [8] => 0 + [9] => 0 + [10] => 192 + [11] => 0 + [12] => 170 + [13] => 171 + [14] => 62 + [15] => 170 + [16] => 0 + [17] => 0 + [18] => 65 + [19] => 200 +) diff --git a/tests/ModbusMasterUdp/output/test.fc2.php.html b/tests/ModbusMasterUdp/output/test.fc2.php.html new file mode 100644 index 0000000..5baae72 --- /dev/null +++ b/tests/ModbusMasterUdp/output/test.fc2.php.html @@ -0,0 +1,7 @@ +Test should pass when %IX0.0==FALSE and %IX0.1==TRUE +array(2) { + [0]=> + bool(false) + [1]=> + bool(true) +} diff --git a/tests/ModbusMasterUdp/output/test.fc26.php.html b/tests/ModbusMasterUdp/output/test.fc26.php.html new file mode 100644 index 0000000..7991aa8 --- /dev/null +++ b/tests/ModbusMasterUdp/output/test.fc26.php.html @@ -0,0 +1 @@ +writeMultipleRegister (FC26): DONE \ No newline at end of file diff --git a/tests/ModbusMasterUdp/output/test.fc26bind.php.html b/tests/ModbusMasterUdp/output/test.fc26bind.php.html new file mode 100644 index 0000000..7991aa8 --- /dev/null +++ b/tests/ModbusMasterUdp/output/test.fc26bind.php.html @@ -0,0 +1 @@ +writeMultipleRegister (FC26): DONE \ No newline at end of file diff --git a/tests/ModbusMasterUdp/output/test.fc6fc3.php.html b/tests/ModbusMasterUdp/output/test.fc6fc3.php.html new file mode 100644 index 0000000..6102dcd --- /dev/null +++ b/tests/ModbusMasterUdp/output/test.fc6fc3.php.html @@ -0,0 +1,5 @@ +Array +( + [0] => 207 + [1] => 199 +) diff --git a/tests/ModbusMasterUdp/ref/test.fc15fc1.php.html b/tests/ModbusMasterUdp/ref/test.fc15fc1.php.html new file mode 100644 index 0000000..55a3de0 --- /dev/null +++ b/tests/ModbusMasterUdp/ref/test.fc15fc1.php.html @@ -0,0 +1,66 @@ +array(32) { + [0]=> + bool(true) + [1]=> + bool(false) + [2]=> + bool(true) + [3]=> + bool(true) + [4]=> + bool(false) + [5]=> + bool(true) + [6]=> + bool(true) + [7]=> + bool(true) + [8]=> + bool(true) + [9]=> + bool(true) + [10]=> + bool(true) + [11]=> + bool(true) + [12]=> + bool(false) + [13]=> + bool(false) + [14]=> + bool(false) + [15]=> + bool(false) + [16]=> + bool(false) + [17]=> + bool(false) + [18]=> + bool(false) + [19]=> + bool(false) + [20]=> + bool(true) + [21]=> + bool(true) + [22]=> + bool(true) + [23]=> + bool(true) + [24]=> + bool(true) + [25]=> + bool(true) + [26]=> + bool(true) + [27]=> + bool(true) + [28]=> + bool(true) + [29]=> + bool(true) + [30]=> + bool(true) + [31]=> + bool(true) +} diff --git a/tests/ModbusMasterUdp/ref/test.fc16fc3.php.html b/tests/ModbusMasterUdp/ref/test.fc16fc3.php.html index c3e4836..00dd046 100644 --- a/tests/ModbusMasterUdp/ref/test.fc16fc3.php.html +++ b/tests/ModbusMasterUdp/ref/test.fc16fc3.php.html @@ -62,7 +62,7 @@ Array [10] => 192 [11] => 0 [12] => 170 - [13] => 170 + [13] => 171 [14] => 62 [15] => 170 [16] => 0 diff --git a/tests/ModbusMasterUdp/ref/test.fc2.php.html b/tests/ModbusMasterUdp/ref/test.fc2.php.html new file mode 100644 index 0000000..5baae72 --- /dev/null +++ b/tests/ModbusMasterUdp/ref/test.fc2.php.html @@ -0,0 +1,7 @@ +Test should pass when %IX0.0==FALSE and %IX0.1==TRUE +array(2) { + [0]=> + bool(false) + [1]=> + bool(true) +} diff --git a/tests/ModbusMasterUdp/ref/test.fc6fc3.php.html b/tests/ModbusMasterUdp/ref/test.fc6fc3.php.html new file mode 100644 index 0000000..6102dcd --- /dev/null +++ b/tests/ModbusMasterUdp/ref/test.fc6fc3.php.html @@ -0,0 +1,5 @@ +Array +( + [0] => 207 + [1] => 199 +) diff --git a/tests/ModbusMasterUdp/test.fc15fc1.php b/tests/ModbusMasterUdp/test.fc15fc1.php index 090bdcb..5a7d8c4 100644 --- a/tests/ModbusMasterUdp/test.fc15fc1.php +++ b/tests/ModbusMasterUdp/test.fc15fc1.php @@ -12,11 +12,11 @@ $data = array(1, 0, TRUE, TRUE, 0, 1, TRUE, TRUE, 1, 1, TRUE, TRUE, 1, 1, TRUE, TRUE); // Write data - FC 15 $modbus->writeMultipleCoils(0, 12288, $data); -echo $modbus->status; -$modbus->status = ""; -echo "\n\n"; +//echo $modbus->status; +//$modbus->status = ""; +//echo "\n\n"; // Read data - FC 1 $recData = $modbus->readCoils(0, 12288, 32); -echo $modbus->status; -echo "\n\n"; +//echo $modbus->status; +//echo "\n\n"; var_dump($recData); \ No newline at end of file diff --git a/tests/ModbusMasterUdp/test.fc2.php b/tests/ModbusMasterUdp/test.fc2.php new file mode 100644 index 0000000..3c73077 --- /dev/null +++ b/tests/ModbusMasterUdp/test.fc2.php @@ -0,0 +1,14 @@ +readInputDiscretes(0, 0, 2); + +var_dump($recData); \ No newline at end of file diff --git a/tests/ModbusMasterUdp/test.fc6fc3.php b/tests/ModbusMasterUdp/test.fc6fc3.php new file mode 100644 index 0000000..03c39f5 --- /dev/null +++ b/tests/ModbusMasterUdp/test.fc6fc3.php @@ -0,0 +1,15 @@ +writeSingleRegister(0, 12288, $data, $dataTypes); +// Read data - FC3 +$recData = $modbus->readMultipleRegisters(0, 12288, 1); +print_r($recData); diff --git a/tests/PhpType/output/test.bytes2mixed.php.html b/tests/PhpType/output/test.bytes2mixed.php.html new file mode 100644 index 0000000..952bc9d --- /dev/null +++ b/tests/PhpType/output/test.bytes2mixed.php.html @@ -0,0 +1 @@ +32098
0
0
-1
-25000
25000
\ No newline at end of file diff --git a/tests/PhpType/output/test.bytes2real.php.html b/tests/PhpType/output/test.bytes2real.php.html new file mode 100644 index 0000000..7d44edb --- /dev/null +++ b/tests/PhpType/output/test.bytes2real.php.html @@ -0,0 +1 @@ +1000
2000
1.25
\ No newline at end of file diff --git a/tests/PhpType/output/test.bytes2signedint.php.html b/tests/PhpType/output/test.bytes2signedint.php.html new file mode 100644 index 0000000..a2b10ea --- /dev/null +++ b/tests/PhpType/output/test.bytes2signedint.php.html @@ -0,0 +1 @@ +-1
0
1
-2147483648
2147483647
diff --git a/tests/PhpType/output/test.bytes2string.php.html b/tests/PhpType/output/test.bytes2string.php.html new file mode 100644 index 0000000..31bbf09 --- /dev/null +++ b/tests/PhpType/output/test.bytes2string.php.html @@ -0,0 +1 @@ +eHll oowlr!da
Hello world!
\ No newline at end of file diff --git a/tests/PhpType/output/test.bytes2unsignedint.php.html b/tests/PhpType/output/test.bytes2unsignedint.php.html new file mode 100644 index 0000000..29be8ee --- /dev/null +++ b/tests/PhpType/output/test.bytes2unsignedint.php.html @@ -0,0 +1,6 @@ +float(4294967295) +
int(0) +
int(1) +
float(2147483648) +
int(2147483647) +
diff --git a/tests/PhpType/output/test.strangearray.size.php.html b/tests/PhpType/output/test.strangearray.size.php.html new file mode 100644 index 0000000..d0e619d --- /dev/null +++ b/tests/PhpType/output/test.strangearray.size.php.html @@ -0,0 +1 @@ +Exception 'Data are not in array 2 or 4 bytes'
25602
Exception 'Data are not in array 2 or 4 bytes'
25602
Exception 'Data are not in array 2 or 4 bytes'
\ No newline at end of file diff --git a/tests/PhpType/output/test.strangearray.textarray.php.html b/tests/PhpType/output/test.strangearray.textarray.php.html new file mode 100644 index 0000000..734d099 --- /dev/null +++ b/tests/PhpType/output/test.strangearray.textarray.php.html @@ -0,0 +1 @@ +Exception 'Data are not numeric' \ No newline at end of file diff --git a/tests/config.bat b/tests/config.bat index 5560180..ef49dfc 100644 --- a/tests/config.bat +++ b/tests/config.bat @@ -1,4 +1,4 @@ -set php=c:\Program_Files\xampplite\php\php.exe +set php=c:\Program_Files\xampp\php\php.exe rem set php=C:\PHP\versions\php-5.2.6-Win32\php.exe -d auto_prepend_file=C:\PHP\locale.php set diff="diff.exe" rem set testUri=http://localHost/nette/_trunk/tests diff --git a/tests/config.php b/tests/config.php index e9133a3..f458917 100644 --- a/tests/config.php +++ b/tests/config.php @@ -1,4 +1,3 @@ \ No newline at end of file + $test_host_ip = "192.168.1.105"; + $test_bind_client_ip = "192.168.1.106"; \ No newline at end of file diff --git a/tutorials/Phpmodbus/Phpmodbus.pkg b/tutorials/Phpmodbus/Phpmodbus.pkg index 2ef74ff..1bb1318 100644 --- a/tutorials/Phpmodbus/Phpmodbus.pkg +++ b/tutorials/Phpmodbus/Phpmodbus.pkg @@ -22,7 +22,9 @@ The library implements: FC 1: read multiple coils + FC 2: read input discretes FC 3: read multiple registers + FC 6: write single register FC 15: write multiple coils FC 16: write multiple registers FC 23: read write registers @@ -32,9 +34,6 @@ For more about Modbus protocol see [{@link http://www.modbus.org}] or [{@link http://en.wikipedia.org/wiki/Modbus Wiki}] - - Developed with support of {@link http://www.wago.com}. - Install @@ -104,6 +103,15 @@ catch (Exception $e) { {@example example_fc1.php} + + FC2 - read input discretes + + FC2 functionality example + + + {@example example_fc2.php} + + FC3 - read mutliple registers @@ -113,6 +121,15 @@ catch (Exception $e) { {@example example_fc3.php} + + FC6 - write single register + + FC6 functionality example + + + {@example example_fc6.php} + + FC15 - write mutliple coils