diff --git a/Phpmodbus/ModbusMaster.php b/Phpmodbus/ModbusMaster.php index 18451ca..e115d11 100644 --- a/Phpmodbus/ModbusMaster.php +++ b/Phpmodbus/ModbusMaster.php @@ -1,12 +1,12 @@ status .= "readMultipleInputRegisters: START\n"; + // connect + $this->connect(); + // send FC 4 + $packet = $this->readMultipleInputRegistersPacketBuilder($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->readMultipleInputRegistersParser($rpacket); + // disconnect + $this->disconnect(); + $this->status .= "readMultipleInputRegisters: DONE\n"; + // return + return $receivedData; + } + + /** + * fc4 + * + * Alias to {@link readMultipleInputRegisters} method. + * + * @param int $unitId + * @param int $reference + * @param int $quantity + * @return false|Array + */ + function fc4($unitId, $reference, $quantity){ + return $this->readMultipleInputRegisters($unitId, $reference, $quantity); + } + + /** + * readMultipleInputRegistersPacketBuilder + * + * Packet FC 4 builder - read multiple input registers + * + * @param int $unitId + * @param int $reference + * @param int $quantity + * @return string + */ + private function readMultipleInputRegistersPacketBuilder($unitId, $reference, $quantity){ + $dataLen = 0; + // build data section + $buffer1 = ""; + // build body + $buffer2 = ""; + $buffer2 .= iecType::iecBYTE(4); // FC 4 = 4(0x04) + // 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; + } + + /** + * readMultipleInputRegistersParser + * + * FC 4 response parser + * + * @param string $packet + * @return array + */ + private function readMultipleInputRegistersParser($packet){ + $data = array(); + // check Response code + $this->responseCode($packet); + // get data + for($i=0;$istatus .= "writeSingleCoil: START\n"; + // connect + $this->connect(); + // send FC5 + $packet = $this->writeSingleCoilPacketBuilder($unitId, $reference, $data); + $this->status .= $this->printPacket($packet); + $this->send($packet); + // receive response + $rpacket = $this->rec(); + $this->status .= $this->printPacket($rpacket); + // parse packet + $this->writeSingleCoilParser($rpacket); + // disconnect + $this->disconnect(); + $this->status .= "writeSingleCoil: DONE\n"; + return true; + } + + + /** + * fc5 + * + * Alias to {@link writeSingleCoil} method + * + * @param int $unitId + * @param int $reference + * @param array $data + * @param array $dataTypes + * @return bool + */ + function fc5($unitId, $reference, $data, $dataTypes){ + return $this->writeSingleCoil($unitId, $reference, $data, $dataTypes); + } + + + /** + * writeSingleCoilPacketBuilder + * + * Packet builder FC5 - WRITE single register + * + * @param int $unitId + * @param int $reference + * @param array $data + * @param array $dataTypes + * @return string + */ + private function writeSingleCoilPacketBuilder($unitId, $reference, $data){ + $dataLen = 0; + // build data section + $buffer1 = ""; + foreach($data as $key=>$dataitem) { + if($dataitem == TRUE){ + $buffer1 = iecType::iecINT(0xFF00); + } else { + $buffer1 = iecType::iecINT(0x0000); + }; + }; + $dataLen += 2; + // build body + $buffer2 = ""; + $buffer2 .= iecType::iecBYTE(5); // FC5 = 5(0x05) + $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; + } + + /** + * writeSingleCoilParser + * + * FC5 response parser + * + * @param string $packet + * @return bool + */ + private function writeSingleCoilParser($packet){ + $this->responseCode($packet); + return true; + } + /** * writeSingleRegister * diff --git a/README.md b/README.md index 7795e78..c189d18 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ phpmodbus ========= This project deals with an implementation of the basic functionality of the Modbus TCP and UDP based protocol using PHP. -It's a copy of the releases from the project page over at [Google Code](https://code.google.com/p/phpmodbus/) with +It's a copy of the releases from the project page over at [Google Code](https://code.google.com/p/phpmodbus/) with composer support added. Features @@ -11,6 +11,8 @@ Features * FC1 - Read coils * FC2 - Read input discretes * FC3 - Read holding registers + * FC4 - Read holding input registers + * FC5 - Write single coil * FC6 - Write single register * FC15 - Write multiple coils * FC16 - Write multiple registers @@ -21,10 +23,10 @@ Example ```php // Modbus master UDP - $modbus = new ModbusMaster("192.168.1.1", "UDP"); + $modbus = new ModbusMaster("192.168.1.1", "UDP"); // Read multiple registers try { - $recData = $modbus->readMultipleRegisters(0, 12288, 5); + $recData = $modbus->readMultipleRegisters(0, 12288, 5); } catch (Exception $e) { // Print error information if any @@ -35,3 +37,8 @@ Example // Print data in string format echo PhpType::bytes2string($recData); ``` + +For more see [documentation][] or [FAQ][]. + +[documentation]: https://code.google.com/p/phpmodbus/downloads/list +[FAQ]: https://code.google.com/p/phpmodbus/wiki/FAQ diff --git a/examples/example_fc4.php b/examples/example_fc4.php new file mode 100644 index 0000000..cb75cf9 --- /dev/null +++ b/examples/example_fc4.php @@ -0,0 +1,19 @@ +readMultipleInputRegisters(0, 0, 2); +} +catch (Exception $e) { + // Print error information if any + echo $modbus; + echo $e; + exit; +} + +var_dump($recData); \ No newline at end of file diff --git a/examples/example_fc5.php b/examples/example_fc5.php new file mode 100644 index 0000000..764a805 --- /dev/null +++ b/examples/example_fc5.php @@ -0,0 +1,24 @@ +writeSingleCoil(0, 12288, $data_true); + $modbus->writeSingleCoil(0, 12289, $data_false); + $modbus->writeSingleCoil(0, 12290, $data_true); + $modbus->writeSingleCoil(0, 12291, $data_false); +} +catch (Exception $e) { + // Print error information if any + echo $modbus; + echo $e; + exit; +} diff --git a/tests/ModbusMasterUdp/ref/test.fc4.php.html b/tests/ModbusMasterUdp/ref/test.fc4.php.html new file mode 100644 index 0000000..4cbe5ae --- /dev/null +++ b/tests/ModbusMasterUdp/ref/test.fc4.php.html @@ -0,0 +1,11 @@ +Test should pass when %IX0.0==FALSE and %IX0.1==TRUE +array(4) { + [0]=> + int(0) + [1]=> + int(2) + [2]=> + int(0) + [3]=> + int(0) +} diff --git a/tests/ModbusMasterUdp/ref/test.fc5.php.html b/tests/ModbusMasterUdp/ref/test.fc5.php.html new file mode 100644 index 0000000..a6a24be --- /dev/null +++ b/tests/ModbusMasterUdp/ref/test.fc5.php.html @@ -0,0 +1,5 @@ +Array +( + [0] => 0 + [1] => 5 +) diff --git a/tests/ModbusMasterUdp/test.fc4.php b/tests/ModbusMasterUdp/test.fc4.php new file mode 100644 index 0000000..dee4929 --- /dev/null +++ b/tests/ModbusMasterUdp/test.fc4.php @@ -0,0 +1,14 @@ +readMultipleInputRegisters(0, 0, 2); + +var_dump($recData); \ No newline at end of file diff --git a/tests/ModbusMasterUdp/test.fc5.php b/tests/ModbusMasterUdp/test.fc5.php new file mode 100644 index 0000000..95e6f92 --- /dev/null +++ b/tests/ModbusMasterUdp/test.fc5.php @@ -0,0 +1,23 @@ +writeSingleRegister(0, 12288, array(0), array('WORD')); + +// Write single coil - FC5 +$modbus->writeSingleCoil(0, 12288, $data_true); +$modbus->writeSingleCoil(0, 12289, $data_false); +$modbus->writeSingleCoil(0, 12290, $data_true); +$modbus->writeSingleCoil(0, 12291, $data_false); + +// Read data - FC3 +$recData = $modbus->readMultipleRegisters(0, 12288, 1); +print_r($recData); diff --git a/tests/config.php b/tests/config.php index f458917..9c71b4a 100644 --- a/tests/config.php +++ b/tests/config.php @@ -1,3 +1,3 @@ FC 1: read multiple coils FC 2: read input discretes FC 3: read multiple registers + FC 4: read multiple input registers + FC 5: write single coil FC 6: write single register FC 15: write multiple coils FC 16: write multiple registers @@ -121,6 +123,24 @@ catch (Exception $e) { {@example example_fc3.php} + + FC4 - read multiple input registers + + FC4 functionality example + + + {@example example_fc4.php} + + + + FC5 - write single coil + + FC5 functionality example + + + {@example example_fc5.php} + + FC6 - write single register