diff --git a/Phpmodbus/ModbusMaster.php b/Phpmodbus/ModbusMaster.php new file mode 100644 index 0000000..0a1997d --- /dev/null +++ b/Phpmodbus/ModbusMaster.php @@ -0,0 +1,798 @@ +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; + } +} diff --git a/Phpmodbus/ModbusMasterTcp.php b/Phpmodbus/ModbusMasterTcp.php new file mode 100644 index 0000000..38971da --- /dev/null +++ b/Phpmodbus/ModbusMasterTcp.php @@ -0,0 +1,49 @@ +host = $host; + $this->socket_protocol = "TCP"; + } +} diff --git a/Phpmodbus/ModbusMasterUdp.php b/Phpmodbus/ModbusMasterUdp.php index 2cb45f4..0fa4fa7 100644 --- a/Phpmodbus/ModbusMasterUdp.php +++ b/Phpmodbus/ModbusMasterUdp.php @@ -1,12 +1,12 @@ host = $host; - } - - /** - * __toString - * - * Magic method - */ - function __toString() { - return "
" . $this->status . "
"; - } - - /** - * connect - * - * Connect the socket - * - * @return bool - */ - private function connect(){ - // UDP socket - $this->sock = socket_create(AF_INET, SOCK_DGRAM, SOL_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 - $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; + $this->socket_protocol = "UDP"; } } - -?> \ No newline at end of file diff --git a/examples/example_750841_Mmemory.php b/examples/example_750841_Mmemory.php index 2d153a6..6039357 100644 --- a/examples/example_750841_Mmemory.php +++ b/examples/example_750841_Mmemory.php @@ -1,10 +1,10 @@ - - - - PhpModbus - - - Examples
- Tests
- Tutorials
- - diff --git a/tests/IecType/output/test.iecByte.php.html b/tests/IecType/output/test.iecByte.php.html deleted file mode 100644 index dc6e8a7..0000000 --- a/tests/IecType/output/test.iecByte.php.html +++ /dev/null @@ -1 +0,0 @@ -125
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 deleted file mode 100644 index 1abf31b..0000000 --- a/tests/IecType/output/test.iecDInt.php.html +++ /dev/null @@ -1 +0,0 @@ -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 deleted file mode 100644 index 583ad9b..0000000 --- a/tests/IecType/output/test.iecInt.php.html +++ /dev/null @@ -1 +0,0 @@ -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 deleted file mode 100644 index 31f8272..0000000 --- a/tests/IecType/output/test.iecReal.php.html +++ /dev/null @@ -1,12 +0,0 @@ -Endianing off
-0 --> Packet: 0000_0000_
-1 --> Packet: 0000_3f80_
--2 --> Packet: 0000_c000_
-0.33333333333333 --> Packet: aaab_3eaa_
-25 --> Packet: 0000_41c8_
-Endianing on
-0 --> Packet: 0000_0000_
-1 --> Packet: 3f80_0000_
--2 --> Packet: c000_0000_
-0.33333333333333 --> Packet: 3eaa_aaab_
-25 --> Packet: 41c8_0000_
diff --git a/tests/ModbusMaster/_test.bat b/tests/ModbusMaster/_test.bat new file mode 100644 index 0000000..8122004 --- /dev/null +++ b/tests/ModbusMaster/_test.bat @@ -0,0 +1,11 @@ +@echo off +call ../config.bat + +for %%f in (test.*.php) do %php% -q "%%f" > "output/%%f.html" + +cd output +for %%f in (*.html) do %diff% "%%f" ../ref/"%%f" +cd .. +pause + +@echo on \ No newline at end of file diff --git a/tests/ModbusMasterUdp/output/test.fc16fc3.php.html b/tests/ModbusMaster/ref/test.tcp.fc16fc3.php.html similarity index 100% rename from tests/ModbusMasterUdp/output/test.fc16fc3.php.html rename to tests/ModbusMaster/ref/test.tcp.fc16fc3.php.html diff --git a/tests/ModbusMasterUdp/output/test.fc26.php.html b/tests/ModbusMaster/ref/test.tcp.fc26.php.html similarity index 100% rename from tests/ModbusMasterUdp/output/test.fc26.php.html rename to tests/ModbusMaster/ref/test.tcp.fc26.php.html diff --git a/tests/ModbusMaster/ref/test.tcp.socket_protocol_mismatch.php.html b/tests/ModbusMaster/ref/test.tcp.socket_protocol_mismatch.php.html new file mode 100644 index 0000000..294f1f5 --- /dev/null +++ b/tests/ModbusMaster/ref/test.tcp.socket_protocol_mismatch.php.html @@ -0,0 +1,7 @@ + +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 diff --git a/tests/ModbusMaster/ref/test.udp.fc16fc3.php.html b/tests/ModbusMaster/ref/test.udp.fc16fc3.php.html new file mode 100644 index 0000000..00dd046 --- /dev/null +++ b/tests/ModbusMaster/ref/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/ref/test.udp.fc26.php.html b/tests/ModbusMaster/ref/test.udp.fc26.php.html new file mode 100644 index 0000000..7991aa8 --- /dev/null +++ b/tests/ModbusMaster/ref/test.udp.fc26.php.html @@ -0,0 +1 @@ +writeMultipleRegister (FC26): DONE \ No newline at end of file diff --git a/tests/ModbusMaster/test.tcp.fc16fc3.php b/tests/ModbusMaster/test.tcp.fc16fc3.php new file mode 100644 index 0000000..bd0b765 --- /dev/null +++ b/tests/ModbusMaster/test.tcp.fc16fc3.php @@ -0,0 +1,44 @@ +writeMultipleRegister(0, 12288, $data, $dataTypes); +// Read data - FC3 +$recData = $modbus->readMultipleRegisters(0, 12288, 5); +print_r($recData); + +// Data to be writen - INT +$data = array(0, 1, -1, pow(2,15)-1, -pow(2,15)); +$dataTypes = array("INT", "INT", "INT", "INT", "INT"); +// Write data - FC 16 +$modbus->writeMultipleRegister(0, 12288, $data, $dataTypes); +// Read data - FC3 +$recData = $modbus->readMultipleRegisters(0, 12288, 5); +print_r($recData); + +// Data to be writen - DINT +$data = array(0, 1, -1, pow(2,31)-1, -pow(2,31)); +$dataTypes = array("DINT", "DINT", "DINT", "DINT", "DINT"); +// Write data - FC 16 +$modbus->writeMultipleRegister(0, 12288, $data, $dataTypes); +// Read data - FC3 +$recData = $modbus->readMultipleRegisters(0, 12288, 10); +print_r($recData); + +// Data to be writen - REAL +$data = array(0, 1, -2, 1/3, 25); +$dataTypes = array("REAL", "REAL", "REAL", "REAL", "REAL"); +// Write data - FC 16 +$modbus->writeMultipleRegister(0, 12288, $data, $dataTypes); +// Read data - FC3 +$recData = $modbus->readMultipleRegisters(0, 12288, 10); +print_r($recData); + +?> \ No newline at end of file diff --git a/tests/ModbusMaster/test.tcp.fc26.php b/tests/ModbusMaster/test.tcp.fc26.php new file mode 100644 index 0000000..2c76b7f --- /dev/null +++ b/tests/ModbusMaster/test.tcp.fc26.php @@ -0,0 +1,24 @@ +readWriteRegisters(0, 12288, 6, 12288, $data, $dataTypes); + +if(!$recData) { + // Print error information if any + echo "
Error:
" . $modbus->errstr . "
"; + // + exit(); +} + +// Print status information +echo "writeMultipleRegister (FC26): DONE"; +?> \ No newline at end of file diff --git a/tests/ModbusMaster/test.tcp.socket_protocol_mismatch.php b/tests/ModbusMaster/test.tcp.socket_protocol_mismatch.php new file mode 100644 index 0000000..ed016b4 --- /dev/null +++ b/tests/ModbusMaster/test.tcp.socket_protocol_mismatch.php @@ -0,0 +1,18 @@ +readWriteRegisters(0, 12288, 6, 12288, $data, $dataTypes); + +// Should through an Exception + +// Print status information +echo "Something wrong!"; \ No newline at end of file diff --git a/tests/ModbusMaster/test.udp.fc16fc3.php b/tests/ModbusMaster/test.udp.fc16fc3.php new file mode 100644 index 0000000..20dee62 --- /dev/null +++ b/tests/ModbusMaster/test.udp.fc16fc3.php @@ -0,0 +1,44 @@ +writeMultipleRegister(0, 12288, $data, $dataTypes); +// Read data - FC3 +$recData = $modbus->readMultipleRegisters(0, 12288, 5); +print_r($recData); + +// Data to be writen - INT +$data = array(0, 1, -1, pow(2,15)-1, -pow(2,15)); +$dataTypes = array("INT", "INT", "INT", "INT", "INT"); +// Write data - FC 16 +$modbus->writeMultipleRegister(0, 12288, $data, $dataTypes); +// Read data - FC3 +$recData = $modbus->readMultipleRegisters(0, 12288, 5); +print_r($recData); + +// Data to be writen - DINT +$data = array(0, 1, -1, pow(2,31)-1, -pow(2,31)); +$dataTypes = array("DINT", "DINT", "DINT", "DINT", "DINT"); +// Write data - FC 16 +$modbus->writeMultipleRegister(0, 12288, $data, $dataTypes); +// Read data - FC3 +$recData = $modbus->readMultipleRegisters(0, 12288, 10); +print_r($recData); + +// Data to be writen - REAL +$data = array(0, 1, -2, 1/3, 25); +$dataTypes = array("REAL", "REAL", "REAL", "REAL", "REAL"); +// Write data - FC 16 +$modbus->writeMultipleRegister(0, 12288, $data, $dataTypes); +// Read data - FC3 +$recData = $modbus->readMultipleRegisters(0, 12288, 10); +print_r($recData); + +?> \ No newline at end of file diff --git a/tests/ModbusMaster/test.udp.fc26.php b/tests/ModbusMaster/test.udp.fc26.php new file mode 100644 index 0000000..02352ac --- /dev/null +++ b/tests/ModbusMaster/test.udp.fc26.php @@ -0,0 +1,24 @@ +readWriteRegisters(0, 12288, 6, 12288, $data, $dataTypes); + +if(!$recData) { + // Print error information if any + echo "
Error:
" . $modbus->errstr . "
"; + // + exit(); +} + +// Print status information +echo "writeMultipleRegister (FC26): DONE"; +?> \ No newline at end of file diff --git a/tests/ModbusMasterTcp/_test.bat b/tests/ModbusMasterTcp/_test.bat new file mode 100644 index 0000000..8122004 --- /dev/null +++ b/tests/ModbusMasterTcp/_test.bat @@ -0,0 +1,11 @@ +@echo off +call ../config.bat + +for %%f in (test.*.php) do %php% -q "%%f" > "output/%%f.html" + +cd output +for %%f in (*.html) do %diff% "%%f" ../ref/"%%f" +cd .. +pause + +@echo on \ No newline at end of file diff --git a/tests/ModbusMasterTcp/ref/test.fc16fc3.php.html b/tests/ModbusMasterTcp/ref/test.fc16fc3.php.html new file mode 100644 index 0000000..00dd046 --- /dev/null +++ b/tests/ModbusMasterTcp/ref/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/ref/test.fc26.php.html b/tests/ModbusMasterTcp/ref/test.fc26.php.html new file mode 100644 index 0000000..7991aa8 --- /dev/null +++ b/tests/ModbusMasterTcp/ref/test.fc26.php.html @@ -0,0 +1 @@ +writeMultipleRegister (FC26): DONE \ No newline at end of file diff --git a/tests/ModbusMasterTcp/test.fc16fc3.php b/tests/ModbusMasterTcp/test.fc16fc3.php new file mode 100644 index 0000000..2fc3ee2 --- /dev/null +++ b/tests/ModbusMasterTcp/test.fc16fc3.php @@ -0,0 +1,44 @@ +writeMultipleRegister(0, 12288, $data, $dataTypes); +// Read data - FC3 +$recData = $modbus->readMultipleRegisters(0, 12288, 5); +print_r($recData); + +// Data to be writen - INT +$data = array(0, 1, -1, pow(2,15)-1, -pow(2,15)); +$dataTypes = array("INT", "INT", "INT", "INT", "INT"); +// Write data - FC 16 +$modbus->writeMultipleRegister(0, 12288, $data, $dataTypes); +// Read data - FC3 +$recData = $modbus->readMultipleRegisters(0, 12288, 5); +print_r($recData); + +// Data to be writen - DINT +$data = array(0, 1, -1, pow(2,31)-1, -pow(2,31)); +$dataTypes = array("DINT", "DINT", "DINT", "DINT", "DINT"); +// Write data - FC 16 +$modbus->writeMultipleRegister(0, 12288, $data, $dataTypes); +// Read data - FC3 +$recData = $modbus->readMultipleRegisters(0, 12288, 10); +print_r($recData); + +// Data to be writen - REAL +$data = array(0, 1, -2, 1/3, 25); +$dataTypes = array("REAL", "REAL", "REAL", "REAL", "REAL"); +// Write data - FC 16 +$modbus->writeMultipleRegister(0, 12288, $data, $dataTypes); +// Read data - FC3 +$recData = $modbus->readMultipleRegisters(0, 12288, 10); +print_r($recData); + +?> \ No newline at end of file diff --git a/tests/ModbusMasterTcp/test.fc26.php b/tests/ModbusMasterTcp/test.fc26.php new file mode 100644 index 0000000..076ab22 --- /dev/null +++ b/tests/ModbusMasterTcp/test.fc26.php @@ -0,0 +1,24 @@ +readWriteRegisters(0, 12288, 6, 12288, $data, $dataTypes); + +if(!$recData) { + // Print error information if any + echo "
Error:
" . $modbus->errstr . "
"; + // + exit(); +} + +// Print status information +echo "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 deleted file mode 100644 index 9a6ca17..0000000 --- a/tests/ModbusMasterUdp/output/test.fc15fc1.php.html +++ /dev/null @@ -1,2 +0,0 @@ - -Fatal error: Call to undefined method ModbusMasterUdp::writeMultipleCoils() in D:\Projects\20081010_phpmodbus\src\trunk\tests\ModbusMasterUdp\test.fc15fc1.php on line 11 diff --git a/tests/ModbusMasterUdp/output/test.fc16fc3bind.php.html b/tests/ModbusMasterUdp/output/test.fc16fc3bind.php.html deleted file mode 100644 index 63d3aa0..0000000 --- a/tests/ModbusMasterUdp/output/test.fc16fc3bind.php.html +++ /dev/null @@ -1,11 +0,0 @@ - -Warning: socket_bind(): unable to bind address [0]: Požadovaná adresa není v tomto kontextu platná. - in D:\Projects\20081010_phpmodbus\src\trunk\Phpmodbus\ModbusMasterUdp.php on line 78 - -Fatal error: Uncaught exception 'Exception' with message 'socket_bind() failed.
Reason: ()Požadovaná adresa není v tomto kontextu platná. -' in D:\Projects\20081010_phpmodbus\src\trunk\Phpmodbus\ModbusMasterUdp.php:80 -Stack trace: -#0 D:\Projects\20081010_phpmodbus\src\trunk\Phpmodbus\ModbusMasterUdp.php(290): ModbusMasterUdp->connect() -#1 D:\Projects\20081010_phpmodbus\src\trunk\tests\ModbusMasterUdp\test.fc16fc3bind.php(13): ModbusMasterUdp->writeMultipleRegister(0, 12288, Array, Array) -#2 {main} - thrown in D:\Projects\20081010_phpmodbus\src\trunk\Phpmodbus\ModbusMasterUdp.php on line 80 diff --git a/tests/ModbusMasterUdp/output/test.fc26bind.php.html b/tests/ModbusMasterUdp/output/test.fc26bind.php.html deleted file mode 100644 index a1a8a23..0000000 --- a/tests/ModbusMasterUdp/output/test.fc26bind.php.html +++ /dev/null @@ -1,11 +0,0 @@ - -Warning: socket_bind(): unable to bind address [0]: Požadovaná adresa není v tomto kontextu platná. - in D:\Projects\20081010_phpmodbus\src\trunk\Phpmodbus\ModbusMasterUdp.php on line 78 - -Fatal error: Uncaught exception 'Exception' with message 'socket_bind() failed.
Reason: ()Požadovaná adresa není v tomto kontextu platná. -' in D:\Projects\20081010_phpmodbus\src\trunk\Phpmodbus\ModbusMasterUdp.php:80 -Stack trace: -#0 D:\Projects\20081010_phpmodbus\src\trunk\Phpmodbus\ModbusMasterUdp.php(410): ModbusMasterUdp->connect() -#1 D:\Projects\20081010_phpmodbus\src\trunk\tests\ModbusMasterUdp\test.fc26bind.php(14): ModbusMasterUdp->readWriteRegisters(0, 12288, 6, 12288, Array, Array) -#2 {main} - thrown in D:\Projects\20081010_phpmodbus\src\trunk\Phpmodbus\ModbusMasterUdp.php on line 80 diff --git a/tests/ModbusMasterUdp/test.fc15fc1.php b/tests/ModbusMasterUdp/test.fc15fc1.php index 5274123..090bdcb 100644 --- a/tests/ModbusMasterUdp/test.fc15fc1.php +++ b/tests/ModbusMasterUdp/test.fc15fc1.php @@ -3,7 +3,7 @@ require_once dirname(__FILE__) . '/../../Phpmodbus/ModbusMasterUdp.php'; require_once dirname(__FILE__) . '/../config.php'; // Create Modbus object -$modbus = new ModbusMasterUdp($testip); +$modbus = new ModbusMasterUdp($test_host_ip); // Data to be writen - BOOL array $data = array(1, 0, TRUE, TRUE, 0, 1, TRUE, TRUE, diff --git a/tests/ModbusMasterUdp/test.fc16fc3.php b/tests/ModbusMasterUdp/test.fc16fc3.php index fe0c565..dff33c7 100644 --- a/tests/ModbusMasterUdp/test.fc16fc3.php +++ b/tests/ModbusMasterUdp/test.fc16fc3.php @@ -3,7 +3,7 @@ require_once dirname(__FILE__) . '/../../Phpmodbus/ModbusMasterUdp.php'; require_once dirname(__FILE__) . '/../config.php'; // Create Modbus object -$modbus = new ModbusMasterUdp($testip); +$modbus = new ModbusMasterUdp($test_host_ip); // Data to be writen - BYTE $data = array(0, 1, 1, pow(2,8)-1, pow(2,8)-1); diff --git a/tests/ModbusMasterUdp/test.fc16fc3bind.php b/tests/ModbusMasterUdp/test.fc16fc3bind.php index c38edb4..5d3bed9 100644 --- a/tests/ModbusMasterUdp/test.fc16fc3bind.php +++ b/tests/ModbusMasterUdp/test.fc16fc3bind.php @@ -3,8 +3,8 @@ require_once dirname(__FILE__) . '/../../Phpmodbus/ModbusMasterUdp.php'; require_once dirname(__FILE__) . '/../config.php'; // Create Modbus object -$modbus = new ModbusMasterUdp($testip); -$modbus->client = "192.192.15.133"; +$modbus = new ModbusMasterUdp($test_host_ip); +$modbus->client = $test_bind_client_ip; // Data to be writen - BYTE $data = array(0, 1, 1, pow(2,8)-1, pow(2,8)-1); diff --git a/tests/ModbusMasterUdp/test.fc26.php b/tests/ModbusMasterUdp/test.fc26.php index ac5ec6d..1a889de 100644 --- a/tests/ModbusMasterUdp/test.fc26.php +++ b/tests/ModbusMasterUdp/test.fc26.php @@ -3,7 +3,7 @@ require_once dirname(__FILE__) . '/../../Phpmodbus/ModbusMasterUdp.php'; require_once dirname(__FILE__) . '/../config.php'; // Create Modbus object -$modbus = new ModbusMasterUdp($testip); +$modbus = new ModbusMasterUdp($test_host_ip); // Data to be writen $data = array(1000, 2000, 1.250, 1.250); diff --git a/tests/ModbusMasterUdp/test.fc26bind.php b/tests/ModbusMasterUdp/test.fc26bind.php index 8043f59..bf24f9e 100644 --- a/tests/ModbusMasterUdp/test.fc26bind.php +++ b/tests/ModbusMasterUdp/test.fc26bind.php @@ -3,8 +3,8 @@ require_once dirname(__FILE__) . '/../../Phpmodbus/ModbusMasterUdp.php'; require_once dirname(__FILE__) . '/../config.php'; // Create Modbus object -$modbus = new ModbusMasterUdp($testip); -$modbus->client = "192.192.15.133"; +$modbus = new ModbusMasterUdp($test_host_ip); +$modbus->client = $test_bind_client_ip; // Data to be writen $data = array(1000, 2000, 1.250, 1.250); diff --git a/tests/PhpType/output/test.bytes2mixed.php.html b/tests/PhpType/output/test.bytes2mixed.php.html deleted file mode 100644 index 952bc9d..0000000 --- a/tests/PhpType/output/test.bytes2mixed.php.html +++ /dev/null @@ -1 +0,0 @@ -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 deleted file mode 100644 index 7d44edb..0000000 --- a/tests/PhpType/output/test.bytes2real.php.html +++ /dev/null @@ -1 +0,0 @@ -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 deleted file mode 100644 index a2b10ea..0000000 --- a/tests/PhpType/output/test.bytes2signedint.php.html +++ /dev/null @@ -1 +0,0 @@ --1
0
1
-2147483648
2147483647
diff --git a/tests/PhpType/output/test.bytes2string.php.html b/tests/PhpType/output/test.bytes2string.php.html deleted file mode 100644 index 31bbf09..0000000 --- a/tests/PhpType/output/test.bytes2string.php.html +++ /dev/null @@ -1 +0,0 @@ -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 deleted file mode 100644 index 29be8ee..0000000 --- a/tests/PhpType/output/test.bytes2unsignedint.php.html +++ /dev/null @@ -1,6 +0,0 @@ -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 deleted file mode 100644 index d0e619d..0000000 --- a/tests/PhpType/output/test.strangearray.size.php.html +++ /dev/null @@ -1 +0,0 @@ -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 deleted file mode 100644 index 734d099..0000000 --- a/tests/PhpType/output/test.strangearray.textarray.php.html +++ /dev/null @@ -1 +0,0 @@ -Exception 'Data are not numeric' \ No newline at end of file diff --git a/tests/config.php b/tests/config.php index ba00e84..e9133a3 100644 --- a/tests/config.php +++ b/tests/config.php @@ -1,3 +1,4 @@ \ No newline at end of file diff --git a/tutorials/Phpmodbus/Phpmodbus.pkg b/tutorials/Phpmodbus/Phpmodbus.pkg index a1c5c09..2ef74ff 100644 --- a/tutorials/Phpmodbus/Phpmodbus.pkg +++ b/tutorials/Phpmodbus/Phpmodbus.pkg @@ -7,7 +7,7 @@ Jan Krakora - {@link mailto:jak.krakora@wago.com email} + {@link mailto:krakora.jan@googlemail.com email} @@ -16,7 +16,7 @@ Introduction Phpmodbus is a PHP library for the Modbus protocol. The library implements - Modbus UDP master class with subset of the most used Modbus commands. + Modbus TCP/UDP master class with subset of the most used Modbus commands. The library implements: @@ -36,8 +36,8 @@ Developed with support of {@link http://www.wago.com}. - - Installation + + Install At the first, it is supposed an PHP solution has been already installed on your server (LAMP, WAMP, MSS+CGI etc.). @@ -48,14 +48,20 @@ Create a PHP script and assign the library using require_once() command - - + + + + + To create UDP Modbus master object communicating to an modbus slave + e.g. at IP address 192.168.1.1 write + + + - To create the Modbus master object communicating to the 192.168.1.1 modbus slave - at IP address 192.168.1.1 write + To create TCP Modbus master use - + @@ -83,7 +89,7 @@ catch (Exception $e) { For other examples see sections bellow. - + Examples @@ -153,4 +159,15 @@ catch (Exception $e) { + + Back compatibility + + This version is back compatible to the last versions. Just use + + + + + \ No newline at end of file