8 Commits
Author SHA1 Message Date
John Long c5c65f8088 0.5 Release
--HG--
rename : tests/ModbusMasterUdp/output/test.fc16fc3.php.html => tests/ModbusMaster/ref/test.tcp.fc16fc3.php.html
rename : tests/ModbusMasterUdp/output/test.fc26.php.html => tests/ModbusMaster/ref/test.tcp.fc26.php.html
rename : tests/ModbusMasterUdp/output/test.fc16fc3.php.html => tests/ModbusMaster/ref/test.udp.fc16fc3.php.html
rename : tests/ModbusMasterUdp/output/test.fc26.php.html => tests/ModbusMaster/ref/test.udp.fc26.php.html
rename : tests/ModbusMasterUdp/output/test.fc16fc3.php.html => tests/ModbusMasterTcp/ref/test.fc16fc3.php.html
rename : tests/ModbusMasterUdp/output/test.fc26.php.html => tests/ModbusMasterTcp/ref/test.fc26.php.html
2013-06-14 07:42:17 -05:00
John Long 6c999a7450 Added tag 0.4.1 for changeset 1e09b0da7d8c 2013-06-14 07:40:52 -05:00
John Long 82c6fcf1d1 0.4.1 2013-06-14 07:40:48 -05:00
John Long 94772fcd7c Added tag 0.4 for changeset bdf8b3f414c4 2013-06-14 07:39:18 -05:00
John Long 71f36c3063 0.4 Release 2013-06-14 07:39:15 -05:00
John Long 89b18aea02 Added tag 0.3 for changeset a7f90c18859d 2013-06-14 07:38:17 -05:00
John Long da9731662c 0.3 Release 2013-06-14 07:38:13 -05:00
John Long fbb70f23e5 Added tag 0.2 for changeset a88b5a87fb4c 2013-06-14 07:33:02 -05:00
49 changed files with 2217 additions and 1045 deletions
+4
View File
@@ -0,0 +1,4 @@
a88b5a87fb4cd49f16ce72062cce19d55f1fbf98 0.2
a7f90c18859d31922bdd8c61299e2790f5e2eb1a 0.3
bdf8b3f414c4d08fc0edf9fd1953f55db26e4bac 0.4
1e09b0da7d8c62a9a292ee51540feac9de4c1222 0.4.1
+10 -55
View File
@@ -1,12 +1,12 @@
<?php <?php
/** /**
* Phpmodbus Copyright (c) 2004, 2009 Jan Krakora, WAGO Kontakttechnik GmbH & Co. KG (http://www.wago.com) * Phpmodbus Copyright (c) 2004, 2010 Jan Krakora, WAGO Kontakttechnik GmbH & Co. KG (http://www.wago.com)
* *
* This source file is subject to the "PhpModbus license" that is bundled * This source file is subject to the "PhpModbus license" that is bundled
* with this package in the file license.txt. * with this package in the file license.txt.
* *
* @author Jan Krakora * @author Jan Krakora
* @copyright Copyright (c) 2004, 2009 Jan Krakora, WAGO Kontakttechnik GmbH & Co. KG (http://www.wago.com) * @copyright Copyright (c) 2004, 2010 Jan Krakora, WAGO Kontakttechnik GmbH & Co. KG (http://www.wago.com)
* @license PhpModbus license * @license PhpModbus license
* @category Phpmodbus * @category Phpmodbus
* @package Phpmodbus * @package Phpmodbus
@@ -20,7 +20,7 @@
* data types to a IEC data type. * data types to a IEC data type.
* *
* @author Jan Krakora * @author Jan Krakora
* @copyright Copyright (c) 2004, 2009 Jan Krakora, WAGO Kontakttechnik GmbH & Co. KG (http://www.wago.com) * @copyright Copyright (c) 2004, 2010 Jan Krakora, WAGO Kontakttechnik GmbH & Co. KG (http://www.wago.com)
* @package Phpmodbus * @package Phpmodbus
*/ */
class IecType { class IecType {
@@ -89,63 +89,18 @@ class IecType {
* This function converts float value to IEC-1131 REAL single precision form. * This function converts float value to IEC-1131 REAL single precision form.
* *
* For more see [{@link http://en.wikipedia.org/wiki/Single_precision Single precision on Wiki}] or * For more see [{@link http://en.wikipedia.org/wiki/Single_precision Single precision on Wiki}] or
* [{@link http://de.php.net/manual/en/function.base-convert.php PHP base_convert function commentary}, Todd Stokes @ Georgia Tech 21-Nov-2007]* * [{@link http://de.php.net/manual/en/function.base-convert.php PHP base_convert function commentary}, Todd Stokes @ Georgia Tech 21-Nov-2007] or
* [{@link http://www.php.net/manual/en/function.pack.php PHP pack/unpack functionality}]
* *
* @param float value to be converted * @param float value to be converted
* @return value IEC REAL data type * @return value IEC REAL data type
*/ */
private function float2iecReal($value) { private function float2iecReal($value) {
$bias = 128; // get float binary string
$cnst = 281; // 1 (carry bit) + 127 + 1 + 126 + 24 + 2 (round bits) $float = pack("f", $value);
$two_power_x = array(1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, // set 32-bit unsigned integer of the float
4096, 8192, 16384, 32768, 65536, 131072, 262144, 524288, 1048576, $w = unpack("L", $float);
2097152, 4194304); return $w[1];
//convert and seperate input to integer and decimal parts
$val = abs($value);
$intpart = floor($val);
$decpart = $val - $intpart;
//convert integer part
for ($i=0;$i<$cnst;$i++) $real_significand_bin[$i] = 0;
$i = $bias;
while ((($intpart / 2) != 0) && ($i >= 0))
{
$real_significand_bin[$i] = $intpart % 2;
if (($intpart % 2) == 0) $intpart = $intpart / 2;
else $intpart = $intpart / 2 - 0.5;
$i -= 1;
}
//convert decimal part
$i = $bias+1;
while (($decpart > 0) && ($i < $cnst))
{
$decpart *= 2;
if ($decpart >= 1) {
$real_significand_bin[$i] = 1;
$decpart --;
$i++;
}
else
{
$real_significand_bin[i] = 0;
$i++;
}
}
//obtain exponent value
$i = 0;
//find most significant bit of significand
while (($i < $cnst) && ($real_significand_bin[$i] != 1)) $i++;
//
$index_exp = $i;
$real_exponent = 128 - $index_exp;
if ($real_exponent < -126) return 0;
if (($real_exponent > 127)&&($real_float>0)) return 0x7F7FFFFF;
if (($real_exponent > 127)&&($real_float<0)) return 0xFF7FFFFF;
for ($i=0; $i<23; $i++)
$real_significand = $real_significand + $real_significand_bin[$index_exp+1+$i] * $two_power_x[22-$i];
// return
if ($value<0) $w = 0x80000000 + ($real_significand & 0x7FFFFF) + ((($real_exponent+127)<<23) & 0x7F800000);
else $w = ($real_significand & 0x7FFFFF) + ((($real_exponent+127)<<23) & 0x7F800000);
return $w;
} }
/** /**
+798
View File
@@ -0,0 +1,798 @@
<?php
/**
* Phpmodbus Copyright (c) 2004, 2012 Jan Krakora
*
* This source file is subject to the "PhpModbus license" that is bundled
* with this package in the file license.txt.
*
*
* @copyright Copyright (c) 2004, 2012 Jan Krakora
* @license PhpModbus license
* @category Phpmodbus
* @tutorial Phpmodbus.pkg
* @package Phpmodbus
* @version $id$
*
*/
require_once dirname(__FILE__) . '/IecType.php';
require_once dirname(__FILE__) . '/PhpType.php';
/**
* ModbusMaster
*
* This class deals with the MODBUS master
*
* Implemented MODBUS master functions:
* - FC 1: read coils
* - FC 3: read multiple registers
* - FC 15: write multiple coils
* - FC 16: write multiple registers
* - FC 23: read write registers
*
* @author Jan Krakora
* @copyright Copyright (c) 2004, 2012 Jan Krakora
* @package Phpmodbus
*
*/
class ModbusMaster {
private $sock;
public $host = "192.168.1.1";
public $port = "502";
public $client = "";
public $client_port = "502";
public $status;
public $timeout_sec = 5; // Timeout 5 sec
public $endianess = 0; // Endianess codding (little endian == 0, big endian == 1)
public $socket_protocol = "UDP"; // Socket protocol (TCP, UDP)
/**
* ModbusMaster
*
* This is the constructor that defines {@link $host} IP address of the object.
*
* @param String $host An IP address of a Modbus TCP device. E.g. "192.168.1.1"
* @param String $protocol Socket protocol (TCP, UDP)
*/
function ModbusMaster($host, $protocol){
$this->socket_protocol = $protocol;
$this->host = $host;
}
/**
* __toString
*
* Magic method
*/
function __toString() {
return "<pre>" . $this->status . "</pre>";
}
/**
* 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.</br>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.</br>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<ord($packet[8]);$i++){
$data[$i] = ord($packet[9+$i]);
}
// get bool values to array
$data_bolean_array = array();
$di = 0;
foreach($data as $value){
for($i=0;$i<8;$i++){
if($di > $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;$i<ord($packet[8]);$i++){
$data[$i] = ord($packet[9+$i]);
}
return $data;
}
/**
* 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 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<count($data);$i++) {
if((($i % 8) == 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<ord($packet[8]);$i++){
$data[$i] = ord($packet[9+$i]);
}
return $data;
}
/**
* byte2hex
*
* Parse data and get it to the Hex form
*
* @param char $value
* @return string
*/
private function byte2hex($value){
$h = dechex(($value >> 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;$i<strlen($packet);$i++){
$str .= $this->byte2hex(ord($packet[$i]));
}
$str .= "\n";
return $str;
}
}
+49
View File
@@ -0,0 +1,49 @@
<?php
/**
* Phpmodbus Copyright (c) 2004, 2012 Jan Krakora
*
* This source file is subject to the "PhpModbus license" that is bundled
* with this package in the file license.txt.
*
*
* @copyright Copyright (c) 2004, 2012 Jan Krakora
* @license PhpModbus license
* @category Phpmodbus
* @tutorial Phpmodbus.pkg
* @package Phpmodbus
* @version $id$
*
*/
require_once dirname(__FILE__) . '/ModbusMaster.php';
/**
* ModbusMasterTcp
*
* This class deals with the MODBUS master using TCP. Extends ModbusMaster class.
*
* Implemented MODBUS functions:
* - FC 1: read coils
* - FC 3: read multiple registers
* - FC 15: write multiple coils
* - FC 16: write multiple registers
* - FC 23: read write registers
*
* @author Jan Krakora
* @copyright Copyright (c) 2004, 2012 Jan Krakora
* @package Phpmodbus
*
*/
class ModbusMasterTcp extends ModbusMaster {
/**
* ModbusMasterTcp
*
* This is the constructor that defines {@link $host} IP address of the object.
*
* @param String $host An IP address of a Modbus TCP device. E.g. "192.168.1.1".
*/
function ModbusMasterTcp($host){
$this->host = $host;
$this->socket_protocol = "TCP";
}
}
+11 -518
View File
@@ -1,12 +1,12 @@
<?php <?php
/** /**
* Phpmodbus Copyright (c) 2004, 2009 Jan Krakora, WAGO Kontakttechnik GmbH & Co. KG (http://www.wago.com) * Phpmodbus Copyright (c) 2004, 2012 Jan Krakora
* *
* This source file is subject to the "PhpModbus license" that is bundled * This source file is subject to the "PhpModbus license" that is bundled
* with this package in the file license.txt. * with this package in the file license.txt.
* *
* *
* @copyright Copyright (c) 2004, 2009 Jan Krakora, WAGO Kontakttechnik GmbH & Co. KG (http://www.wago.com) * @copyright Copyright (c) 2004, 2012 Jan Krakora
* @license PhpModbus license * @license PhpModbus license
* @category Phpmodbus * @category Phpmodbus
* @tutorial Phpmodbus.pkg * @tutorial Phpmodbus.pkg
@@ -15,543 +15,36 @@
* *
*/ */
require_once dirname(__FILE__) . '/IecType.php'; require_once dirname(__FILE__) . '/ModbusMaster.php';
require_once dirname(__FILE__) . '/PhpType.php';
/** /**
* ModbusMasterUdp * ModbusMasterUdp
* *
* This class deals with the MODBUS master using UDP stack. * This class deals with the MODBUS master using UDP stack.
* *
* Implemented MODBUS functions: * Implemented MODBUS master functions:
* - FC 1: read coils
* - FC 3: read multiple registers * - FC 3: read multiple registers
* - FC 15: write multiple coils
* - FC 16: write multiple registers * - FC 16: write multiple registers
* - FC 23: read write registers * - FC 23: read write registers
* *
* @author Jan Krakora * @author Jan Krakora
* @copyright Copyright (c) 2004, 2009 Jan Krakora, WAGO Kontakttechnik GmbH & Co. KG (http://www.wago.com) * @copyright Copyright (c) 2004, 2012 Jan Krakora
* @package Phpmodbus * @package Phpmodbus
* *
*/ */
class ModbusMasterUdp { class ModbusMasterUdp extends ModbusMaster {
var $sock;
var $port = "502";
var $host = "192.168.1.1";
var $errstr;
var $status;
var $timeout_sec = 5; // 5 sec
var $endianess = 0; // defines endian codding (little endian == 0, big endian == 1)
/** /**
* Modbus * ModbusMasterUdp
* *
* This is the constructor that defines {@link $host} IP address of the object. * This is the constructor that defines {@link $host} IP address of the object.
* *
* @param String $host An IP address of a Modbus TCP device. E.g. "192.168.1.1". * @param String $host An IP address of a Modbus UDP device. E.g. "192.168.1.1".
*/ */
function ModbusMasterUdp($host){ function ModbusMasterUdp($host){
$this->host = $host; $this->host = $host;
} $this->socket_protocol = "UDP";
/**
* connect
*
* Connect the socket
*
* @return bool
*/
private function connect(){
// UDP socket
$this->sock = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP);
// connect
$result = @socket_connect($this->sock, $this->host, $this->port);
if ($result === false) {
$this->errstr .= "socket_connect() failed.</br>Reason: ($result) " .
socket_strerror(socket_last_error($this->sock));
return false;
} else {
$this->status .= "Connected</br>";
return true;
} }
} }
/**
* disconnect
*
* Disconnect the socket
*/
private function disconnect(){
socket_close($this->sock);
$this->status .= "Disconnected</br>";
}
/**
* send
*
* Send the packet via Modbus
*
* @param string $packet
*/
private function send($packet){
socket_write($this->sock, $packet, strlen($packet));
$this->status .= "Send</br>";
}
/**
* 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 received data</br>";
if (in_array($this->sock, $readsocks)) {
while (@socket_recv($this->sock, $rec, 2000, 0)) {
$this->status .= "Received</br>";
return $rec;
}
$lastAccess = time();
} else {
if (time()-$lastAccess >= $this->timeout_sec) {
$this->errstr .= "Watchdog time expired [ " .
$this->timeout_sec . " sec]!!! Connection to " .
$this->host . " is not established.";
return false;
}
}
$readsocks[] = $this->sock;
}
}
/**
* responseCode
*
* Check the Modbus response code
*
* @param string $packet
* @return bool
*/
private function responseCode($packet){
if(($packet[7] & 0x80) > 0) {
$this->errstr .= "Modbus response error code:" . ord($packet[8]);
return false;
}
else
{
$this->status .= "Modbus response error code: NOERROR</br>";
return true;
}
}
/**
* 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->errstr = "";
$this->status = "readMultipleRegisters: START</br>";
// connect
if(!$this->connect())
return false;
// send FC 3
$packet = $this->readMultipleRegistersPacketBuilder($unitId, $reference, $quantity);
$this->status .= $this->printPacket($packet);
$this->send($packet);
// receive response
$rpacket = $this->rec();
if(!$rpacket)
return false;
$this->status .= $this->printPacket($rpacket);
// parse packet
$receivedData = $this->readMultipleRegistersParser($rpacket);
if(!$receivedData)
return false;
// disconnect
$this->disconnect();
$this->status .= "readMultipleRegisters: DONE</br>";
// 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 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();
// if not exception
if(!$this->responseCode($packet))
return false;
// get data
for($i=0;$i<ord($packet[8]);$i++){
$data[$i] = ord($packet[9+$i]);
}
return $data;
}
/**
* 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->errstr = "";
$this->status = "writeMultipleRegister: START</br>";
// connect
if(!$this->connect())
return false;
// send FC16
$packet = $this->writeMultipleRegisterPacketBuilder($unitId, $reference, $data, $dataTypes);
$this->status .= $this->printPacket($packet);
$this->send($packet);
// receive response
$rpacket = $this->rec();
if(!$rpacket)
return false;
$this->status .= $this->printPacket($rpacket);
// parse packet
if(!$this->writeMultipleRegisterParser($rpacket))
return false;
// disconnect
$this->disconnect();
$this->status .= "writeMultipleRegister: DONE</br>";
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, $endianess); // register values x
$dataLen += 4;
}
elseif($dataTypes[$key]=="REAL") {
$buffer1 .= iecType::iecREAL($dataitem, $endianess); // 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){
if(!$this->responseCode($rpacket))
return false;
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->errstr = "";
$this->status = "readWriteRegisters: START</br>";
// connect
if(!$this->connect())
return false;
// send FC23
$packet = $this->readWriteRegistersPacketBuilder($unitId, $referenceRead, $quantity, $referenceWrite, $data, $dataTypes);
$this->status .= $this->printPacket($packet);
$this->send($packet);
// receive response
$rpacket = $this->rec();
if(!$rpacket)
return false;
$this->status .= $this->printPacket($rpacket);
// parse packet
$receivedData = $this->readWriteRegistersParser($rpacket);
if(!$receivedData)
return false;
// disconnect
$this->disconnect();
$this->status .= "writeMultipleRegister: DONE</br>";
// 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, $endianess); // register values x
$dataLen += 4;
}
elseif($dataTypes[$key]=="REAL") {
$buffer1 .= iecType::iecREAL($dataitem, $endianess); // 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<ord($packet[8]);$i++){
$data[$i] = ord($packet[9+$i]);
}
return $data;
}
/**
* byte2hex
*
* Parse data and get it to the Hex form
*
* @param char $value
* @return string
*/
private function byte2hex($value){
$h = dechex(($value >> 4) & 0x0F);
$l = dechex($value & 0x0F);
return "$h$l";
}
/**
* printPacket
*
* Print whole packet in the hex form
*
* @param string $packet
* @return string
*/
private function printPacket($packet){
$str = "";
$str .= "Packet: ";
for($i=0;$i<strlen($packet);$i++){
$str .= $this->byte2hex(ord($packet[$i]));
}
$str .= "</br>";
return $str;
}
}
?>
+68 -38
View File
@@ -1,12 +1,12 @@
<? <?php
/** /**
* Phpmodbus Copyright (c) 2004, 2009 Jan Krakora, WAGO Kontakttechnik GmbH & Co. KG (http://www.wago.com) * Phpmodbus Copyright (c) 2004, 2010 Jan Krakora, WAGO Kontakttechnik GmbH & Co. KG (http://www.wago.com)
* *
* This source file is subject to the "PhpModbus license" that is bundled * This source file is subject to the "PhpModbus license" that is bundled
* with this package in the file license.txt. * with this package in the file license.txt.
* *
* @author Jan Krakora * @author Jan Krakora
* @copyright Copyright (c) 2004, 2009 Jan Krakora, WAGO Kontakttechnik GmbH & Co. KG (http://www.wago.com) * @copyright Copyright (c) 2004, 2010 Jan Krakora, WAGO Kontakttechnik GmbH & Co. KG (http://www.wago.com)
* @license PhpModbus license * @license PhpModbus license
* @category Phpmodbus * @category Phpmodbus
* @package Phpmodbus * @package Phpmodbus
@@ -21,7 +21,7 @@
* (array of bytes) to the PHP data type, i.e. signed int, unsigned int and float. * (array of bytes) to the PHP data type, i.e. signed int, unsigned int and float.
* *
* @author Jan Krakora * @author Jan Krakora
* @copyright Copyright (c) 2004, 2009 Jan Krakora, WAGO Kontakttechnik GmbH & Co. KG (http://www.wago.com) * @copyright Copyright (c) 2004, 2010 Jan Krakora, WAGO Kontakttechnik GmbH & Co. KG (http://www.wago.com)
* @package Phpmodbus * @package Phpmodbus
* *
*/ */
@@ -95,44 +95,65 @@ class PhpType {
return self::dword2unsignedInt($int); return self::dword2unsignedInt($int);
} }
/**
* bytes2string
*
* The function converts an values array to the string. The function detects
* the end of the string by 0x00 character as defined by string standards.
*
* @param array $values
* @param bool $endianness
* @return string
*/
public static function bytes2string($values, $endianness = 0) {
// Prepare string variable
$str = "";
// Parse the received data word array
for($i=0;$i<count($values);$i+=2) {
if ($endianness) {
if($values[$i] != 0)
$str .= chr($values[$i]);
else
break;
if($values[$i+1] != 0)
$str .= chr($values[$i+1]);
else
break;
}
else {
if($values[$i+1] != 0)
$str .= chr($values[$i+1]);
else
break;
if($values[$i] != 0)
$str .= chr($values[$i]);
else
break;
}
}
// return string
return $str;
}
/** /**
* real2float * real2float
* *
* This function converts a value in IEC-1131 REAL single precision form to float. * This function converts a value in IEC-1131 REAL single precision form to float.
* *
* For more see [{@link http://en.wikipedia.org/wiki/Single_precision Single precision on Wiki}] or * For more see [{@link http://en.wikipedia.org/wiki/Single_precision Single precision on Wiki}] or
* [{@link http://de.php.net/manual/en/function.base-convert.php PHP base_convert function commentary}, Todd Stokes @ Georgia Tech 21-Nov-2007] * [{@link http://de.php.net/manual/en/function.base-convert.php PHP base_convert function commentary}, Todd Stokes @ Georgia Tech 21-Nov-2007] or
* [{@link http://www.php.net/manual/en/function.pack.php PHP pack/unpack functionality}]
* *
* @param value value in IEC REAL data type to be converted * @param value value in IEC REAL data type to be converted
* @return float float value * @return float float value
*/ */
private static function real2float($value) { private static function real2float($value) {
$two_pow_minus_x = array( // get unsigned long
1, 0.5, 0.25, 0.125, 0.0625, 0.03125, 0.015625, $ulong = pack("L", $value);
0.0078125, 0.00390625, 0.001953125, 0.0009765625, // set float
0.00048828125, 0.000244140625, 0.0001220703125, $float = unpack("f", $ulong);
0.00006103515625, 0.000030517578125, 0.0000152587890625,
0.00000762939453125, 0.000003814697265625, 0.0000019073486328125, return $float[1];
0.00000095367431640625, 0.000000476837158203125,
0.0000002384185791015625, 0.00000011920928955078125);
// get sign, mantisa, exponent
$real_mantisa = $value & 0x7FFFFF | 0x800000;
$real_exponent = ($value>>23) & 0xFF;
$real_sign = ($value>>31) & 0x01;
$bin_exponent = $real_exponent - 127;
// decode value
if (( $bin_exponent >= -126) && ($bin_exponent <= 127)) {
// Mantissa decoding
for ($i=0; $i<24; $i++) {
if ($real_mantisa & 0x01)
$val += $two_pow_minus_x[23-$i];
$real_mantisa = $real_mantisa >> 1;
}
// Base
$val = $val * pow(2,$bin_exponent);
if (($real_sign == 1)) $val = -$val;
}
return (float)$val;
} }
/** /**
@@ -177,15 +198,24 @@ class PhpType {
*/ */
private static function checkData($data) { private static function checkData($data) {
// Check the data // Check the data
if (!is_array($data)) { if (!is_array($data) ||
throw new Exception('The input data should be an array of bytes.'); count($data)<2 ||
count($data)>4 ||
count($data)==3) {
throw new Exception('The input data should be an array of 2 or 4 bytes.');
} }
// Check the values to be number - must be // Fill the rest of array by zeroes
if (!is_numeric($data[0]) || !is_numeric($data[1])) { if (count($data) == 2) {
throw new Exception('Data are not numeric.'); $data[2] = 0;
$data[3] = 0;
}
// Check the values to be number
if (!is_numeric($data[0]) ||
!is_numeric($data[1]) ||
!is_numeric($data[2]) ||
!is_numeric($data[3])) {
throw new Exception('Data are not numeric or the array keys are not indexed by 0,1,2 and 3');
} }
if (!is_numeric($data[2])) $data[2] = 0;
if (!is_numeric($data[3])) $data[3] = 0;
return $data; return $data;
} }
+18 -24
View File
@@ -1,17 +1,24 @@
<?php <?php
require_once dirname(__FILE__) . './Phpmodbus/ModbusMasterUdp.php'; require_once dirname(__FILE__) . '/../Phpmodbus/ModbusMaster.php';
// Create Modbus object // Create Modbus object
$ip = "192.168.1.99"; $ip = "192.192.15.51";
$modbus = new ModbusMasterUdp($ip); $modbus = new ModbusMaster($ip, "UDP");
try {
// FC 3 // FC 3
$moduleId = 0; $moduleId = 0;
$reference = 12288; $reference = 12288;
$mw0address = 12288; $mw0address = 12288;
$quantity = 6; $quantity = 6;
$recData = $modbus->readMultipleRegisters($moduleId, $reference, $quantity); $recData = $modbus->readMultipleRegisters($moduleId, $reference, $quantity);
}
catch (Exception $e) {
echo $modbus;
echo $e;
exit;
}
?> ?>
<html> <html>
@@ -24,23 +31,14 @@ $recData = $modbus->readMultipleRegisters($moduleId, $reference, $quantity);
<h1>Dump of M-memory from WAGO 750-84x series coupler.</h1> <h1>Dump of M-memory from WAGO 750-84x series coupler.</h1>
<ul> <ul>
<li>PLC: 750-84x series</li> <li>PLC: 750-84x series</li>
<li>IP: <?=$ip?></li> <li>IP: <?php echo $ip?></li>
<li>Modbus module ID: <?=$moduleId?></li> <li>Modbus module ID: <?php echo $moduleId?></li>
<li>Modbus memory reference: <?=$reference?></li> <li>Modbus memory reference: <?php echo $reference?></li>
<li>Modbus memory quantity: <?=$quantity?></li> <li>Modbus memory quantity: <?php echo $quantity?></li>
</ul> </ul>
<h2>M-memory dump</h2> <h2>M-memory dump</h2>
<?php
if(!$recData) {
// Print error information if any
echo "</br>Error:</br>" . $modbus->errstr . "</br>";
}
else
{
?>
<table border="1px" width="400px"> <table border="1px" width="400px">
<tr> <tr>
<td>Modbus address</td> <td>Modbus address</td>
@@ -51,22 +49,18 @@ $recData = $modbus->readMultipleRegisters($moduleId, $reference, $quantity);
for($i=0;$i<count($recData);$i+=2) { for($i=0;$i<count($recData);$i+=2) {
?> ?>
<tr> <tr>
<td><?=$i+$reference?></td> <td><?php echo $i+$reference?></td>
<td>MW<?=($i + $reference - $mw0address)/2?></td> <td>MW<?php echo ($i + $reference - $mw0address)/2?></td>
<td><?=($recData[$i] << 8)+ $recData[$i+1]?></td> <td><?php echo ($recData[$i] << 8)+ $recData[$i+1]?></td>
</tr> </tr>
<?php <?php
} }
?> ?>
</table> </table>
<?php
}
?>
<h2>Modbus class status</h2> <h2>Modbus class status</h2>
<?php <?php
echo $modbus->status; echo $modbus;
?> ?>
</body> </body>
+19 -13
View File
@@ -1,55 +1,61 @@
<?php <?php
require_once dirname(__FILE__) . './Phpmodbus/ModbusMasterUdp.php'; require_once dirname(__FILE__) . '/../Phpmodbus/ModbusMaster.php';
// Create Modbus object // Create Modbus object
$modbus = new ModbusMasterUdp("192.168.1.99"); $modbus = new ModbusMaster("192.192.15.51", "UDP");
try {
// FC 3 // FC 3
// read 10 words (20 bytes) from device ID=0, address=12288 // read 10 words (20 bytes) from device ID=0, address=12288
$recData = $modbus->readMultipleRegisters(0, 12288, 10); $recData = $modbus->readMultipleRegisters(0, 12288, 10);
}
if(!$recData) { catch (Exception $e) {
// Print error information if any // Print error information if any
echo "</br>Error:</br>" . $modbus->errstr . "</br>"; echo $modbus;
echo $e;
exit; exit;
} }
// Received data // Received data
echo "<h1>Received Data</h1>"; echo "<h1>Received Data</h1>\n";
print_r($recData); print_r($recData);
// Conversion // Conversion
echo "<h2>32 bits types</h2>"; echo "<h2>32 bits types</h2>\n";
// Chunk the data array to set of 4 bytes // Chunk the data array to set of 4 bytes
$values = array_chunk($recData, 4); $values = array_chunk($recData, 4);
// Get float from REAL interpretation // Get float from REAL interpretation
echo "<h3>REAL to Float</h3>"; echo "<h3>REAL to Float</h3>\n";
foreach($values as $bytes) foreach($values as $bytes)
echo PhpType::bytes2float($bytes) . "</br>"; echo PhpType::bytes2float($bytes) . "</br>";
// Get integer from DINT interpretation // Get integer from DINT interpretation
echo "<h3>DINT to integer </h3>"; echo "<h3>DINT to integer </h3>\n";
foreach($values as $bytes) foreach($values as $bytes)
echo PhpType::bytes2signedInt($bytes) . "</br>"; echo PhpType::bytes2signedInt($bytes) . "</br>";
// Get integer of float from DINT interpretation // Get integer of float from DINT interpretation
echo "<h3>DWORD to integer (or float) </h3>"; echo "<h3>DWORD to integer (or float) </h3>\n";
foreach($values as $bytes) foreach($values as $bytes)
echo PhpType::bytes2unsignedInt($bytes) . "</br>"; echo PhpType::bytes2unsignedInt($bytes) . "</br>";
echo "<h2>16 bit types</h2>"; echo "<h2>16 bit types</h2>\n";
// Chunk the data array to set of 4 bytes // Chunk the data array to set of 4 bytes
$values = array_chunk($recData, 2); $values = array_chunk($recData, 2);
// Get signed integer from INT interpretation // Get signed integer from INT interpretation
echo "<h3>INT to integer </h3>"; echo "<h3>INT to integer </h3>\n";
foreach($values as $bytes) foreach($values as $bytes)
echo PhpType::bytes2signedInt($bytes) . "</br>"; echo PhpType::bytes2signedInt($bytes) . "</br>";
// Get unsigned integer from WORD interpretation // Get unsigned integer from WORD interpretation
echo "<h3>WORD to integer </h3>"; echo "<h3>WORD to integer </h3>\n";
foreach($values as $bytes) foreach($values as $bytes)
echo PhpType::bytes2unsignedInt($bytes) . "</br>"; echo PhpType::bytes2unsignedInt($bytes) . "</br>";
// Get string from STRING interpretation
echo "<h3>STRING to string </h3>\n";
echo PhpType::bytes2string($recData) . "</br>";
?> ?>
+25
View File
@@ -0,0 +1,25 @@
<?php
require_once dirname(__FILE__) . '/../Phpmodbus/ModbusMaster.php';
// Create Modbus object
$modbus = new ModbusMaster("192.192.15.51", "UDP");
try {
// FC 1
$recData = $modbus->readCoils(0, 12288, 12);
}
catch (Exception $e) {
// Print error information if any
echo $modbus;
echo $e;
exit;
}
// Print status information
echo "</br>Status:</br>" . $modbus;
// Print read data
echo "</br>Data:</br>";
var_dump($recData);
echo "</br>";
+26
View File
@@ -0,0 +1,26 @@
<?php
require_once dirname(__FILE__) . '/../Phpmodbus/ModbusMaster.php';
// Create Modbus object
$modbus = new ModbusMaster("192.192.15.51", "UDP");
// Data to be writen
$data = array(TRUE, FALSE, TRUE, TRUE, FALSE, TRUE, TRUE, TRUE,
TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE,
FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE,
TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE);
try {
// FC15
$modbus->writeMultipleCoils(0, 12288, $data);
}
catch (Exception $e) {
// Print error information if any
echo $modbus;
echo $e;
exit;
}
// Print status information
echo $modbus;
+12 -7
View File
@@ -1,21 +1,26 @@
<?php <?php
require_once dirname(__FILE__) . './Phpmodbus/ModbusMasterUdp.php'; require_once dirname(__FILE__) . '/../Phpmodbus/ModbusMaster.php';
// Create Modbus object // Create Modbus object
$modbus = new ModbusMasterUdp("192.168.1.99"); $modbus = new ModbusMaster("192.192.15.51", "UDP");
// Data to be writen // Data to be writen
$data = array(1000, 2000, 3.0); $data = array(10, -1000, 2000, 3.0);
$dataTypes = array("INT", "DINT", "REAL"); $dataTypes = array("WORD", "INT", "DINT", "REAL");
try {
// FC16 // FC16
if(!$modbus->writeMultipleRegister(0, 12288, $data, $dataTypes)) { $modbus->writeMultipleRegister(0, 12288, $data, $dataTypes);
}
catch (Exception $e) {
// Print error information if any // Print error information if any
echo "</br>Error:</br>" . $modbus->errstr . "</br>"; echo $modbus;
echo $e;
exit;
} }
// Print status information // Print status information
echo "</br>Status:</br>" . $modbus->status . "</br>"; echo $modbus;
?> ?>
+14 -9
View File
@@ -1,26 +1,31 @@
<?php <?php
require_once dirname(__FILE__) . './Phpmodbus/ModbusMasterUdp.php'; require_once dirname(__FILE__) . '/../Phpmodbus/ModbusMaster.php';
// Create Modbus object // Create Modbus object
$modbus = new ModbusMasterUdp("192.168.1.99"); $modbus = new ModbusMaster("192.192.15.51", "UDP");
// Data to be writen // Data to be writen
$data = array(1000, 2000, 3.0); $data = array(10, -1000, 2000, 3.0);
$dataTypes = array("INT", "DINT", "REAL"); $dataTypes = array("WORD", "INT", "DINT", "REAL");
try {
// FC23 // FC23
$recData = $modbus->readWriteRegisters(0, 12288, 6, 12288, $data, $dataTypes); $recData = $modbus->readWriteRegisters(0, 12288, 6, 12288, $data, $dataTypes);
}
if(!$recData) { catch (Exception $e) {
// Print error information if any // Print error information if any
echo "</br>Error:</br>" . $modbus->errstr . "</br>"; echo $modbus;
echo $e;
exit;
} }
// Print status information // Print status information
echo "</br>Status:</br>" . $modbus->status . "</br>"; echo "</br>Status:</br>" . $modbus;
// Print read data // Print read data
echo "</br>Data:</br>"; print_r($recData); echo "</br>"; echo "</br>Data:</br>";
print_r($recData);
echo "</br>";
?> ?>
+12 -7
View File
@@ -1,21 +1,26 @@
<?php <?php
require_once dirname(__FILE__) . './Phpmodbus/ModbusMasterUdp.php'; require_once dirname(__FILE__) . '/../Phpmodbus/ModbusMaster.php';
// Create Modbus object // Create Modbus object
$modbus = new ModbusMasterUdp("192.168.1.99"); $modbus = new ModbusMaster("192.192.15.51", "UDP");
try {
// FC 3 // FC 3
$recData = $modbus->readMultipleRegisters(0, 12288, 6); $recData = $modbus->readMultipleRegisters(0, 12288, 6);
}
if(!$recData) { catch (Exception $e) {
// Print error information if any // Print error information if any
echo "</br>Error:</br>" . $modbus->errstr . "</br>"; echo $modbus;
echo $e;
exit;
} }
// Print status information // Print status information
echo "</br>Status:</br>" . $modbus->status . "</br>"; echo "</br>Status:</br>" . $modbus;
// Print read data // Print read data
echo "</br>Data:</br>"; print_r($recData); echo "</br>"; echo "</br>Data:</br>";
print_r($recData);
echo "</br>";
?> ?>
+1 -1
View File
@@ -1,7 +1,7 @@
The Phpmodbus License, Version 1 The Phpmodbus License, Version 1
============================ ============================
Copyright (c) 2004, 2008 Jan Krakora, Wago (http://www.wago.com) Copyright (c) 2004, 2011 Jan Krakora, Wago (http://www.wago.com)
All rights reserved. All rights reserved.
This license is a legal agreement between you and Jan Krakora, Wago (the "Author") This license is a legal agreement between you and Jan Krakora, Wago (the "Author")
-19
View File
@@ -1,19 +0,0 @@
Copyright (c) 2004, 2009 Jan Krakora, Wago (http://www.wago.com)
All rights reserved.
Phpmodbus library
####################
Phpmodbus for PHP is a small and easy-to-use Modbus UDP master library. For more
see project at http://phpmodbus.googlecode.com
Release notes
===============
0.1 -> 0.2.r20
---------------
+ Added new class for conversion from received bytes to PHP data types (PhpType class)
+ Added new data conversion using PhpType example
+ Added new alias methods fc3, fc16 and fc23 (ModbusMasterUdp class)
* Fixed problems with the endianess when data written (IecType class)
* Improved commentaries for documentation
+12 -1
View File
@@ -1 +1,12 @@
Endianing off <hr>0 --> Packet: 0000_0000_</br>1 --> Packet: 0000_3f80_</br>-2 --> Packet: 0000_c000_</br>0.333333333333 --> Packet: aaaa_3eaa_</br>25 --> Packet: 0000_41c8_</br>Endianing on <hr>0 --> Packet: 0000_0000_</br>1 --> Packet: 3f80_0000_</br>-2 --> Packet: c000_0000_</br>0.333333333333 --> Packet: 3eaa_aaaa_</br>25 --> Packet: 41c8_0000_</br> Endianing off <hr>
0 --> Packet: 0000_0000_<br>
1 --> Packet: 0000_3f80_<br>
-2 --> Packet: 0000_c000_<br>
0.333333333333 --> Packet: aaaa_3eaa_<br>
25 --> Packet: 0000_41c8_<br>
Endianing on <hr>
0 --> Packet: 0000_0000_<br>
1 --> Packet: 3f80_0000_<br>
-2 --> Packet: c000_0000_<br>
0.333333333333 --> Packet: 3eaa_aaaa_<br>
25 --> Packet: 41c8_0000_<br>
+5 -5
View File
@@ -25,26 +25,26 @@ function printPacket($packet){
if($i % 2) if($i % 2)
$str .= "_"; $str .= "_";
} }
$str .= "</br>"; $str .= "<br>\n";
return $str; return $str;
} }
echo "Endianing off <hr>"; echo "Endianing off <hr>\n";
// Print mixed values // Print mixed values
for($i=0;$i<count($data);$i++) { for($i=0;$i<count($data);$i++) {
echo $data[$i] . " --> "; echo $data[$i] . " --> ";
$v = IecType::iecREAL($data[$i], 0); $v = IecType::iecREAL($data[$i], 0);
echo printPacket($v); echo printPacket($v);
"<br>"; "<br>\n";
} }
echo "Endianing on <hr>"; echo "Endianing on <hr>\n";
// Print mixed values // Print mixed values
for($i=0;$i<count($data);$i++) { for($i=0;$i<count($data);$i++) {
echo $data[$i] . " --> "; echo $data[$i] . " --> ";
$v = IecType::iecREAL($data[$i], 1); $v = IecType::iecREAL($data[$i], 1);
echo printPacket($v); echo printPacket($v);
"<br>"; "<br>\n";
} }
?> ?>
+11
View File
@@ -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
@@ -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
)
@@ -0,0 +1 @@
writeMultipleRegister (FC26): DONE
@@ -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
@@ -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
)
@@ -0,0 +1 @@
writeMultipleRegister (FC26): DONE
+44
View File
@@ -0,0 +1,44 @@
<?php
require_once dirname(__FILE__) . '/../../Phpmodbus/ModbusMaster.php';
require_once dirname(__FILE__) . '/../config.php';
// Create Modbus object
$modbus = new ModbusMaster($test_host_ip, "TCP");
// Data to be writen - BYTE
$data = array(0, 1, 1, pow(2,8)-1, pow(2,8)-1);
$dataTypes = array("BYTE", "BYTE", "BYTE", "BYTE", "BYTE");
// 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 - 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);
?>
+24
View File
@@ -0,0 +1,24 @@
<?php
require_once dirname(__FILE__) . '/../../Phpmodbus/ModbusMaster.php';
require_once dirname(__FILE__) . '/../config.php';
// Create Modbus object
$modbus = new ModbusMaster($test_host_ip, "TCP");
// Data to be writen
$data = array(1000, 2000, 1.250, 1.250);
$dataTypes = array("REAL", "REAL", "REAL", "REAL");
// FC23
$recData = $modbus->readWriteRegisters(0, 12288, 6, 12288, $data, $dataTypes);
if(!$recData) {
// Print error information if any
echo "</br>Error:</br>" . $modbus->errstr . "</br>";
//
exit();
}
// Print status information
echo "writeMultipleRegister (FC26): DONE";
?>
@@ -0,0 +1,18 @@
<?php
require_once dirname(__FILE__) . '/../../Phpmodbus/ModbusMaster.php';
require_once dirname(__FILE__) . '/../config.php';
// Create Modbus object
$modbus = new ModbusMaster($test_host_ip, "Mismatch");
// Data to be writen
$data = array(1000, 2000, 1.250, 1.250);
$dataTypes = array("REAL", "REAL", "REAL", "REAL");
// FC23
$recData = $modbus->readWriteRegisters(0, 12288, 6, 12288, $data, $dataTypes);
// Should through an Exception
// Print status information
echo "Something wrong!";
+44
View File
@@ -0,0 +1,44 @@
<?php
require_once dirname(__FILE__) . '/../../Phpmodbus/ModbusMaster.php';
require_once dirname(__FILE__) . '/../config.php';
// Create Modbus object
$modbus = new ModbusMaster($test_host_ip, "UDP");
// Data to be writen - BYTE
$data = array(0, 1, 1, pow(2,8)-1, pow(2,8)-1);
$dataTypes = array("BYTE", "BYTE", "BYTE", "BYTE", "BYTE");
// 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 - 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);
?>
+24
View File
@@ -0,0 +1,24 @@
<?php
require_once dirname(__FILE__) . '/../../Phpmodbus/ModbusMaster.php';
require_once dirname(__FILE__) . '/../config.php';
// Create Modbus object
$modbus = new ModbusMaster($test_host_ip, "UDP");
// Data to be writen
$data = array(1000, 2000, 1.250, 1.250);
$dataTypes = array("REAL", "REAL", "REAL", "REAL");
// FC23
$recData = $modbus->readWriteRegisters(0, 12288, 6, 12288, $data, $dataTypes);
if(!$recData) {
// Print error information if any
echo "</br>Error:</br>" . $modbus->errstr . "</br>";
//
exit();
}
// Print status information
echo "writeMultipleRegister (FC26): DONE";
?>
+11
View File
@@ -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
@@ -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
)
@@ -0,0 +1 @@
writeMultipleRegister (FC26): DONE
+44
View File
@@ -0,0 +1,44 @@
<?php
require_once dirname(__FILE__) . '/../../Phpmodbus/ModbusMasterTcp.php';
require_once dirname(__FILE__) . '/../config.php';
// Create Modbus object
$modbus = new ModbusMasterTcp($test_host_ip);
// Data to be writen - BYTE
$data = array(0, 1, 1, pow(2,8)-1, pow(2,8)-1);
$dataTypes = array("BYTE", "BYTE", "BYTE", "BYTE", "BYTE");
// 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 - 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);
?>
+24
View File
@@ -0,0 +1,24 @@
<?php
require_once dirname(__FILE__) . '/../../Phpmodbus/ModbusMasterTcp.php';
require_once dirname(__FILE__) . '/../config.php';
// Create Modbus object
$modbus = new ModbusMasterTcp($test_host_ip);
// Data to be writen
$data = array(1000, 2000, 1.250, 1.250);
$dataTypes = array("REAL", "REAL", "REAL", "REAL");
// FC23
$recData = $modbus->readWriteRegisters(0, 12288, 6, 12288, $data, $dataTypes);
if(!$recData) {
// Print error information if any
echo "</br>Error:</br>" . $modbus->errstr . "</br>";
//
exit();
}
// Print status information
echo "writeMultipleRegister (FC26): DONE";
?>
@@ -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
)
@@ -0,0 +1 @@
writeMultipleRegister (FC26): DONE
+22
View File
@@ -0,0 +1,22 @@
<?php
require_once dirname(__FILE__) . '/../../Phpmodbus/ModbusMasterUdp.php';
require_once dirname(__FILE__) . '/../config.php';
// Create Modbus object
$modbus = new ModbusMasterUdp($test_host_ip);
// Data to be writen - BOOL array
$data = array(1, 0, TRUE, TRUE, 0, 1, TRUE, TRUE,
1, 1, TRUE, TRUE, 0, 0, FALSE, FALSE,
0, 0, FALSE, FALSE, 1, 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";
// Read data - FC 1
$recData = $modbus->readCoils(0, 12288, 32);
echo $modbus->status;
echo "\n\n";
var_dump($recData);
+1 -1
View File
@@ -3,7 +3,7 @@ require_once dirname(__FILE__) . '/../../Phpmodbus/ModbusMasterUdp.php';
require_once dirname(__FILE__) . '/../config.php'; require_once dirname(__FILE__) . '/../config.php';
// Create Modbus object // Create Modbus object
$modbus = new ModbusMasterUdp($testip); $modbus = new ModbusMasterUdp($test_host_ip);
// Data to be writen - BYTE // Data to be writen - BYTE
$data = array(0, 1, 1, pow(2,8)-1, pow(2,8)-1); $data = array(0, 1, 1, pow(2,8)-1, pow(2,8)-1);
@@ -0,0 +1,45 @@
<?php
require_once dirname(__FILE__) . '/../../Phpmodbus/ModbusMasterUdp.php';
require_once dirname(__FILE__) . '/../config.php';
// Create Modbus object
$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);
$dataTypes = array("BYTE", "BYTE", "BYTE", "BYTE", "BYTE");
// 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 - 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);
?>
+1 -1
View File
@@ -3,7 +3,7 @@ require_once dirname(__FILE__) . '/../../Phpmodbus/ModbusMasterUdp.php';
require_once dirname(__FILE__) . '/../config.php'; require_once dirname(__FILE__) . '/../config.php';
// Create Modbus object // Create Modbus object
$modbus = new ModbusMasterUdp($testip); $modbus = new ModbusMasterUdp($test_host_ip);
// Data to be writen // Data to be writen
$data = array(1000, 2000, 1.250, 1.250); $data = array(1000, 2000, 1.250, 1.250);
+25
View File
@@ -0,0 +1,25 @@
<?php
require_once dirname(__FILE__) . '/../../Phpmodbus/ModbusMasterUdp.php';
require_once dirname(__FILE__) . '/../config.php';
// Create Modbus object
$modbus = new ModbusMasterUdp($test_host_ip);
$modbus->client = $test_bind_client_ip;
// Data to be writen
$data = array(1000, 2000, 1.250, 1.250);
$dataTypes = array("REAL", "REAL", "REAL", "REAL");
// FC23
$recData = $modbus->readWriteRegisters(0, 12288, 6, 12288, $data, $dataTypes);
if(!$recData) {
// Print error information if any
echo "</br>Error:</br>" . $modbus->errstr . "</br>";
//
exit();
}
// Print status information
echo "writeMultipleRegister (FC26): DONE";
?>
@@ -0,0 +1 @@
eHll oowlr!da<br>Hello world!<br>
@@ -0,0 +1 @@
Exception 'Data are not in array 2 or 4 bytes'<br>25602<br>Exception 'Data are not in array 2 or 4 bytes'<br>25602<br>Exception 'Data are not in array 2 or 4 bytes'<br>
@@ -0,0 +1 @@
Exception 'Data are not numeric'
+28
View File
@@ -0,0 +1,28 @@
<?php
require_once dirname(__FILE__) . '/../../Phpmodbus/ModbusMasterUdp.php';
// Received bytes interpreting 3 REAL values (6 words)
$data = array( // String "Hello word!"
0x48, //H
0x65, //e
0x6c, //l
0x6c, //l
0x6f, //o
0x20, //
0x77, //w
0x6f, //o
0x72, //r
0x6c, //l
0x64, //d
0x21, //!
0x00, //\0
0x61, //a
0x61 //a
);
// Print string interpretation of the values
echo PhpType::bytes2string($data) . "<br>";
echo PhpType::bytes2string($data, true) . "<br>";
?>
+44
View File
@@ -0,0 +1,44 @@
<?php
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
require_once dirname(__FILE__) . '/../../Phpmodbus/ModbusMasterUdp.php';
// Received bytes interpreting Mixed values
$data = Array (
"0" => 100, // 32098 (DINT)
"1" => 2,
"2" => 0,
"3" => 0,
"4" => 100, // 32098 (DINT)
"5" => 2
);
// Print mixed values
try {
echo PhpType::bytes2unsignedInt(array_slice($data, 0, 1)) . "<br>";
} catch(Exception $e) {
echo "Exception 'Data are not in array 2 or 4 bytes'". "<br>";
}
try {
echo PhpType::bytes2unsignedInt(array_slice($data, 0, 2)). "<br>";
} catch(Exception $e) {
echo "Exception 'Data are not in array 2 or 4 bytes'". "<br>";
}
try {
echo PhpType::bytes2unsignedInt(array_slice($data, 0, 3)). "<br>";
} catch(Exception $e) {
echo "Exception 'Data are not in array 2 or 4 bytes'". "<br>";
}
try {
echo PhpType::bytes2unsignedInt(array_slice($data, 0, 4)). "<br>";
} catch(Exception $e) {
echo "Exception 'Data are not in array 2 or 4 bytes'". "<br>";
}
try {
echo PhpType::bytes2unsignedInt(array_slice($data, 0, 5)). "<br>";
} catch(Exception $e) {
echo "Exception 'Data are not in array 2 or 4 bytes'". "<br>";
}
?>
@@ -0,0 +1,22 @@
<?php
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
require_once dirname(__FILE__) . '/../../Phpmodbus/ModbusMasterUdp.php';
// Received bytes interpreting Mixed values
$data = Array (
"0" => 100, // 32098 (DINT)
"1" => "e",
"2" => 0,
"3" => 0
);
// Print mixed values
try {
echo PhpType::bytes2unsignedInt(array_slice($data, 0, 4));
} catch(Exception $e) {
echo "Exception 'Data are not numeric'";
}
?>
+4 -4
View File
@@ -1,5 +1,5 @@
set php=C:\Programme\xampplite\php\php.exe set php=c:\Program_Files\xampplite\php\php.exe
rem set php=C:\PHP\versions\php-5.2.6-Win32\php.exe -d auto_prepend_file=C:\PHP\locale.php rem set php=C:\PHP\versions\php-5.2.6-Win32\php.exe -d auto_prepend_file=C:\PHP\locale.php
set diff="C:\Program Files\Octave\msys\bin\diff.exe" set diff="diff.exe"
set testUri=http://localHost/nette/_trunk/tests rem set testUri=http://localHost/nette/_trunk/tests
set wget=wget.exe rem set wget=wget.exe
+2 -1
View File
@@ -1,3 +1,4 @@
<?php <?php
$testip = "192.168.1.15"; $test_host_ip = "192.192.15.51";
$test_bind_client_ip = "192.192.15.113";
?> ?>
+67 -15
View File
@@ -7,7 +7,7 @@
<author> <author>
Jan Krakora Jan Krakora
<authorblurb> <authorblurb>
{@link mailto:jak.krakora@wago.com email} {@link mailto:krakora.jan@googlemail.com email}
</authorblurb> </authorblurb>
</author> </author>
</refsynopsisdiv> </refsynopsisdiv>
@@ -16,12 +16,14 @@
<title>Introduction</title> <title>Introduction</title>
<para> <para>
Phpmodbus is a PHP library for the Modbus protocol. The library implements 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.
</para> </para>
<para> <para>
The library implements: The library implements:
<itemizedlist> <itemizedlist>
<listitem><para>FC 1: read multiple coils</para></listitem>
<listitem><para>FC 3: read multiple registers</para></listitem> <listitem><para>FC 3: read multiple registers</para></listitem>
<listitem><para>FC 15: write multiple coils</para></listitem>
<listitem><para>FC 16: write multiple registers</para></listitem> <listitem><para>FC 16: write multiple registers</para></listitem>
<listitem><para>FC 23: read write registers</para></listitem> <listitem><para>FC 23: read write registers</para></listitem>
</itemizedlist> </itemizedlist>
@@ -34,8 +36,8 @@
Developed with support of <graphic fileref="wago_logo.png"/> {@link http://www.wago.com}. Developed with support of <graphic fileref="wago_logo.png"/> {@link http://www.wago.com}.
</note> </note>
</refsect1> </refsect1>
<refsect1 id="{@id intro}"> <refsect1 id="{@id install}">
<title>Installation</title> <title>Install</title>
<para> <para>
At the first, it is supposed an PHP solution has been already installed on At the first, it is supposed an PHP solution has been already installed on
your server (LAMP, WAMP, MSS+CGI etc.). your server (LAMP, WAMP, MSS+CGI etc.).
@@ -44,25 +46,46 @@
Copy the Phpmodbus library to your PHP project folder. Copy the Phpmodbus library to your PHP project folder.
</para> </para>
<para> <para>
Create a PHP script and assign the library using Create a PHP script and assign the library using require_once() command
<programlisting role="ini"> <programlisting role="c">
<![CDATA[ require_once dirname(__FILE__) . './Phpmodbus/ModbusMasterUdp.php'; ]]> <![CDATA[require_once dirname(__FILE__) . '/Phpmodbus/ModbusMaster.php'; ]]>
</programlisting> </programlisting>
</para> </para>
<para> <para>
To create the Modbus master object, that will communicate with a Modbus slave To create UDP Modbus master object communicating to an modbus slave
at IP address 192.168.1.1, write e.g. at IP address 192.168.1.1 write
<programlisting role="ini"> <programlisting role="c" linenumbering="numbered" startinglinenumber="2">
<![CDATA[ $modbus = new ModbusMasterUdp("192.168.1.1"); ]]> <![CDATA[ $modbus = new ModbusMaster("192.168.1.1", "UDP"); ]]>
</programlisting> </programlisting>
</para> </para>
<para> <para>
To read 5 words (10 bytes) located at the memory beginning at address = 12288 of To create TCP Modbus master use
the devide with Modbus ID=0 use <programlisting role="c" linenumbering="numbered" startinglinenumber="2">
<programlisting role="ini"> <![CDATA[ $modbus = new ModbusMaster("192.168.1.1", "TCP"); ]]>
<![CDATA[ $recData = $modbus->readMultipleRegisters(0, 12288, 5); ]]>
</programlisting> </programlisting>
</para> </para>
<para>
To read 5 words (10 bytes) from the device ID=0 and its memory address 12288
use try-catch method call
<programlisting role="c" linenumbering="numbered" startinglinenumber="3">
<![CDATA[try {
// Function processing
$recData = $modbus->readMultipleRegisters(0, 12288, 5);
}
catch (Exception $e) {
// Exception processing, e.g. print error information
echo $modbus;
echo $e;
exit;
}]]>
</programlisting>
</para>
<para>
To process the function byte stream, use conversion to PHP types in
</para>
<programlisting role="c" linenumbering="numbered" startinglinenumber="15">
<![CDATA[echo PhpType::bytes2string($recData); ]]>
</programlisting>
<para> <para>
For other examples see sections bellow. For other examples see sections bellow.
</para> </para>
@@ -72,6 +95,15 @@
<para> <para>
This section presents library features and examples This section presents library features and examples
</para> </para>
<refsect2 id="{@id example_fc1}">
<title>FC1 - read mutliple coils</title>
<para>
FC1 functionality example
</para>
<para>
{@example example_fc1.php}
</para>
</refsect2>
<refsect2 id="{@id example_fc3}"> <refsect2 id="{@id example_fc3}">
<title>FC3 - read mutliple registers</title> <title>FC3 - read mutliple registers</title>
<para> <para>
@@ -81,6 +113,15 @@
{@example example_fc3.php} {@example example_fc3.php}
</para> </para>
</refsect2> </refsect2>
<refsect2 id="{@id example_fc15}">
<title>FC15 - write mutliple coils</title>
<para>
FC15 functionality example
</para>
<para>
{@example example_fc15.php}
</para>
</refsect2>
<refsect2 id="{@id example_fc16}"> <refsect2 id="{@id example_fc16}">
<title>FC16 - write mutliple registers</title> <title>FC16 - write mutliple registers</title>
<para> <para>
@@ -118,4 +159,15 @@
</para> </para>
</refsect2> </refsect2>
</refsect1> </refsect1>
<refsect1 id="{@id back_comp}">
<title>Back compatibility</title>
<para>
This version is back compatible to the last versions. Just use
<programlisting role="c">
<![CDATA[require_once dirname(__FILE__) . '/Phpmodbus/ModbusMasterUdp.php';
$modbus = new ModbusMasterUdp("192.168.1.1");
// ... ]]>
</programlisting>
</para>
</refsect1>
</refentry> </refentry>