diff --git a/Phpmodbus/IecType.php b/Phpmodbus/IecType.php index 9beb696..74c1314 100644 --- a/Phpmodbus/IecType.php +++ b/Phpmodbus/IecType.php @@ -1,12 +1,12 @@ > 8) & 0x00FF) . self::iecBYTE(($value & 0x00FF)); } @@ -62,7 +62,7 @@ function iecINT($value) { * @return value IEC-1131 INT data type * */ - function iecDINT($value, $endianness = 0) { + public static function iecDINT($value, $endianness = 0) { // result with right endianness return self::endianness($value, $endianness); } @@ -76,7 +76,7 @@ function iecDINT($value, $endianness = 0) { * @param value endianness defines endian codding (little endian == 0, big endian == 1) * @return value IEC-1131 REAL data type */ - function iecREAL($value, $endianness = 0) { + public static function iecREAL($value, $endianness = 0) { // iecREAL representation $real = self::float2iecReal($value); // result with right endianness @@ -95,7 +95,7 @@ function iecREAL($value, $endianness = 0) { * @param float value to be converted * @return value IEC REAL data type */ - private function float2iecReal($value) { + private static function float2iecReal($value) { // get float binary string $float = pack("f", $value); // set 32-bit unsigned integer of the float @@ -113,7 +113,7 @@ private function float2iecReal($value) { * @param bool $endianness * @return int */ - private function endianness($value, $endianness = 0) { + private static function endianness($value, $endianness = 0) { if ($endianness == 0) return self::iecBYTE(($value >> 8) & 0x000000FF) . diff --git a/Phpmodbus/ModbusMaster.php b/Phpmodbus/ModbusMaster.php index 738892a..afb82b4 100644 --- a/Phpmodbus/ModbusMaster.php +++ b/Phpmodbus/ModbusMaster.php @@ -1,12 +1,13 @@ socket_protocol = $protocol; $this->host = $host; + $this->explicit = false; } /** @@ -76,6 +83,12 @@ function __toString() { * @return bool */ private function connect(){ + if($this->explicit == false){ + $this->connectInternal(); + } + } + + private function connectInternal(){ // Create a protocol specific socket if ($this->socket_protocol == "TCP"){ // TCP socket @@ -96,6 +109,8 @@ private function connect(){ $this->status .= "Bound\n"; } } + // Socket settings + socket_set_option($this->sock, SOL_SOCKET, SO_SNDTIMEO, array('sec' => 1, 'usec' => 0)); // Connect the socket $result = @socket_connect($this->sock, $this->host, $this->port); if ($result === false) { @@ -112,7 +127,14 @@ private function connect(){ * * Disconnect the socket */ - private function disconnect(){ + + private function disconnect(){ + if($this->explicit == false){ + $this->disconnectInternal(); + } + } + + private function disconnectInternal(){ socket_close($this->sock); $this->status .= "Disconnected\n"; } @@ -203,6 +225,15 @@ private function responseCode($packet){ } } + function connectExplicit(){ + $this->explicit = true; + $this->connectInternal(); + } + + function disconnectExplicit(){ + $this->explicit = false; + $this->disconnectInternal(); + } /** * readCoils * @@ -508,6 +539,308 @@ private function readMultipleRegistersParser($packet){ return $data; } + /** + * readMultipleInputRegisters + * + * Modbus function FC 4(0x04) - Read Multiple Input 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. + * @param int $quantity Amounth of the data to be read from device. + * @return false|Array Success flag or array of received data. + */ + function readMultipleInputRegisters($unitId, $reference, $quantity){ + $this->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 + * + * Modbus function FC6(0x06) - Write Single Register. + * + * This function writes {@link $data} single word value 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 writeSingleRegister($unitId, $reference, $data, $dataTypes){ + $this->status .= "writeSingleRegister: START\n"; + // connect + $this->connect(); + // send FC6 + $packet = $this->writeSingleRegisterPacketBuilder($unitId, $reference, $data, $dataTypes); + $this->status .= $this->printPacket($packet); + $this->send($packet); + // receive response + $rpacket = $this->rec(); + $this->status .= $this->printPacket($rpacket); + // parse packet + $this->writeSingleRegisterParser($rpacket); + // disconnect + $this->disconnect(); + $this->status .= "writeSingleRegister: DONE\n"; + return true; + } + + + /** + * fc6 + * + * Alias to {@link writeSingleRegister} method + * + * @param int $unitId + * @param int $reference + * @param array $data + * @param array $dataTypes + * @return bool + */ + function fc6($unitId, $reference, $data, $dataTypes){ + return $this->writeSingleRegister($unitId, $reference, $data, $dataTypes); + } + + + /** + * writeSingleRegisterPacketBuilder + * + * Packet builder FC6 - WRITE single register + * + * @param int $unitId + * @param int $reference + * @param array $data + * @param array $dataTypes + * @return string + */ + private function writeSingleRegisterPacketBuilder($unitId, $reference, $data, $dataTypes){ + $dataLen = 0; + // build data section + $buffer1 = ""; + foreach($data as $key=>$dataitem) { + $buffer1 .= iecType::iecINT($dataitem); // register values x + $dataLen += 2; + break; + } + // build body + $buffer2 = ""; + $buffer2 .= iecType::iecBYTE(6); // FC6 = 6(0x06) + $buffer2 .= iecType::iecINT($reference); // refnumber = 12288 + $dataLen += 3; + // build header + $buffer3 = ''; + $buffer3 .= iecType::iecINT(rand(0,65000)); // transaction ID + $buffer3 .= iecType::iecINT(0); // protocol ID + $buffer3 .= iecType::iecINT($dataLen + 1); // lenght + $buffer3 .= iecType::iecBYTE($unitId); //unit ID + + // return packet string + return $buffer3. $buffer2. $buffer1; + } + + /** + * writeSingleRegisterParser + * + * FC6 response parser + * + * @param string $packet + * @return bool + */ + private function writeSingleRegisterParser($packet){ + $this->responseCode($packet); + return true; + } + + /** * writeMultipleCoils * @@ -525,7 +858,7 @@ function writeMultipleCoils($unitId, $reference, $data){ $this->status .= "writeMultipleCoils: START\n"; // connect $this->connect(); - // send FC16 + // send FC15 $packet = $this->writeMultipleCoilsPacketBuilder($unitId, $reference, $data); $this->status .= $this->printPacket($packet); $this->send($packet); @@ -740,7 +1073,7 @@ private function writeMultipleRegisterParser($packet){ $this->responseCode($packet); return true; } - + /** * readWriteRegisters * diff --git a/Phpmodbus/PhpType.php b/Phpmodbus/PhpType.php index 97670a9..5552e61 100644 --- a/Phpmodbus/PhpType.php +++ b/Phpmodbus/PhpType.php @@ -1,12 +1,12 @@ readInputDiscretes(0, 12288, 12); + // read 2 input bits from address 0x0 (Wago input image) + $recData = $modbus->readInputDiscretes(0, 0, 2); } catch (Exception $e) { // Print error information if any 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/examples/example_fc6.php b/examples/example_fc6.php new file mode 100644 index 0000000..4db6b04 --- /dev/null +++ b/examples/example_fc6.php @@ -0,0 +1,26 @@ +writeSingleRegister(0, 12288, $data, $dataTypes); +} +catch (Exception $e) { + // Print error information if any + echo $modbus; + echo $e; + exit; +} + +// Print status information +echo $modbus; + +?> \ No newline at end of file diff --git a/license.txt b/license.txt index edea02a..4a2550a 100644 --- a/license.txt +++ b/license.txt @@ -1,10 +1,10 @@ The Phpmodbus License, Version 1 ============================ -Copyright (c) 2004, 2011 Jan Krakora, Wago (http://www.wago.com) +Copyright (c) 2004, 2013 Jan Krakora 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 (the "Author") for the use of Phpmodbus (the "Software"). By obtaining, using and/or copying the Software, you agree that you have read, understood, and will comply with the terms and conditions of this license. diff --git a/tests/Codesys/TEST.EXP b/tests/Codesys/TEST.EXP new file mode 100644 index 0000000..3e6f226 --- /dev/null +++ b/tests/Codesys/TEST.EXP @@ -0,0 +1,256 @@ + + +(* @NESTEDCOMMENTS := 'Yes' *) +(* @PATH := '' *) +(* @OBJECTFLAGS := '0, 8' *) +(* @SYMFILEFLAGS := '2048' *) +PROGRAM PLC_PRG +VAR + (* BOOL, COIL *) + COIL1 AT %MX0.0 : BOOL := 0; + COIL2 AT %MX0.1 : BOOL := 0; + COIL3 AT %MX0.2 : BOOL := 0; + COIL4 AT %MX0.3 : BOOL := 0; + COIL5 AT %MX0.4 : BOOL := 0; + COIL6 AT %MX0.5 : BOOL := 0; + COIL7 AT %MX0.6 : BOOL := 0; + COIL8 AT %MX0.7 : BOOL := 0; + + (* BYTE *) + BYTE1 AT %MB0 : BYTE := 0; + BYTE2 AT %MB1 : BYTE := 0; + BYTE3 AT %MB2 : BYTE := 0; + BYTE4 AT %MB3 : BYTE := 0; + BYTE5 AT %MB4 : BYTE := 0; + + (* INT *) + INT1 AT %MW0 : INT := 0; + INT2 AT %MW1 : INT := 0; + INT3 AT %MW2 : INT := 0; + INT4 AT %MW3 : INT := 0; + INT5 AT %MW4 : INT := 0; + + (* WORD *) + WORD1 AT %MW0 : WORD := 0; + WORD2 AT %MW1 : WORD := 0; + WORD3 AT %MW2 : WORD := 0; + WORD4 AT %MW3 : WORD := 0; + WORD5 AT %MW4 : WORD := 0; + + (* DINT *) + DINT1 AT %MD0 : DINT := 0; + DINT2 AT %MD1 : DINT := 0; + DINT3 AT %MD2 : DINT := 0; + DINT4 AT %MD3 : DINT := 0; + DINT5 AT %MD4 : DINT := 0; + + (* DWORD *) + DWORD1 AT %MD0 : DWORD := 0; + DWORD2 AT %MD1 : DWORD := 0; + DWORD3 AT %MD2 : DWORD := 0; + DWORD4 AT %MD3 : DWORD := 0; + DWORD5 AT %MD4 : DWORD := 0; + + (* REAL *) + REAL1 AT %MD0 : REAL := 0; + REAL2 AT %MD1 : REAL := 0; + REAL3 AT %MD2 : REAL := 0; + REAL4 AT %MD3 : REAL := 0; + REAL5 AT %MD4 : REAL := 0; + + (* String *) + STRING1 AT %MW0 : STRING := 'Hello word!!!'; +END_VAR + +(* @END_DECLARATION := '0' *) +(* Something to do *) +; +END_PROGRAM + +(* @NESTEDCOMMENTS := 'Yes' *) +(* @GLOBAL_VARIABLE_LIST := 'Global_Variables' *) +(* @PATH := '' *) +(* @OBJECTFLAGS := '0, 8' *) +(* @SYMFILEFLAGS := '2048' *) +VAR_GLOBAL +END_VAR + +(* @OBJECT_END := 'Global_Variables' *) +(* @CONNECTIONS := Global_Variables +FILENAME : '' +FILETIME : 0 +EXPORT : 0 +NUMOFCONNECTIONS : 0 +*) + +(* @NESTEDCOMMENTS := 'Yes' *) +(* @GLOBAL_VARIABLE_LIST := 'Variable_Configuration' *) +(* @PATH := '' *) +(* @OBJECTFLAGS := '0, 8' *) +(* @SYMFILEFLAGS := '2048' *) +VAR_CONFIG +END_VAR + +(* @OBJECT_END := 'Variable_Configuration' *) +(* @CONNECTIONS := Variable_Configuration +FILENAME : '' +FILETIME : 0 +EXPORT : 0 +NUMOFCONNECTIONS : 0 +*) + + +_ALARMCONFIG +_ALARMCONFIGNEXTTEXTID : 10002 +_ALARMCONFIGFORMATS : 'HH$':$'mm$':$'ss','dd$'-$'MM$'-$'yyyy' +_ALARMCLASSLIST : 1 +_ALARMCLASSID : 0 +_ALARMCLASSACKTYPE : 0 +_ALARMCLASSNAME : 'DEFAULT' +_ALARMCLASSDESCRIPTION : '' +_ALARMCLASSBGCOLORS : 16777215,16777215,16777215 +_ALARMCLASSTEXTCOLORS : 3394560,255,16711680 +_ALARMCLASSBITMAPS : '','','' +_ALARMACTIONLIST : 0 +(* @ALARMCLASSRESETCOLORS := '_ALARMCLASSRESETCOLORS: 33023,16777215' *) +(* @ALARMCLASSRESETBITMAP := '_ALARMCLASSRESETBITMAP: $'$'' *) +_ALARMGROUPLISTNAME : 'System' +_ALARMGROUPPATH : 'System' +_ALARMGROUPLIST : 0 +_VISUALSETTINGSFLAGS : 0,0,0,0 +_VISUALSETTINGSFLAGS : '','','' +_VISUALSETTINGSDYNTEXTFILECOUNT : 0 + +(* @ALARMCONFIGFLAGS := '_ALARMCONFIGFLAGS: 0' *) +(* @ALARMCONFIGGLOBALDB_STR := '_ALARMCONFIGGLOBALDB_STRINGS: $'$',$'$',$'$',$'$'' *) +(* @ALARMCONFIGGLOBALDB_NUM := '_ALARMCONFIGGLOBALDB_NUMBERS: 0,0' *) +_END_ALARMCONFIG + + +LIBRARY +Standard.lib 2.12.10 14:48:34 +(* @LIBRARYSYMFILEINFO := '0' *) +NumOfPOUs: 26 +ASCIIBYTE_TO_STRING: 2048 +CONCAT: 0 +CTD: 0 +CTU: 0 +CTUD: 0 +DELETE: 0 +F_TRIG: 0 +FIND: 0 +INSERT: 0 +LEFT: 0 +LEN: 0 +MID: 0 +R_TRIG: 0 +REAL_STATE: 2048 +REPLACE: 0 +RIGHT: 0 +RS: 0 +RTC: 0 +SEMA: 0 +SR: 0 +STANDARD_VERSION: 2048 +STRING_COMPARE: 2048 +STRING_TO_ASCIIBYTE: 2048 +TOF: 0 +TON: 0 +TP: 0 +NumOfGVLs: 1 +'Global Variables 0': 0 +END_LIBRARY + +LIBRARY +SYSLIBCALLBACK.LIB 2.12.10 14:48:32 +(* @LIBRARYSYMFILEINFO := '0' *) +NumOfPOUs: 2 +SysCallbackRegister: 0 +SysCallbackUnregister: 0 +NumOfGVLs: 2 +Globale_Variablen: 0 +Version: 0 +END_LIBRARY + +PLC_CONFIGURATION +_GLOBAL +_VERSION: 3 +_AUTOADR: 0 +_CHECKADR: 0 +_SAVECONFIGFILESINPROJECT: 0 +_END_GLOBAL + +_MODULE: '3S' +_SECTION_NAME: 'Root' +_INDEX_IN_PARENT: '-1' +_MODULE_NAME: 'Hardware configuration' +_NODE_ID: -1 +_IECIN: %IB0 +_IECOUT: %QB0 +_IECDIAG: %MB0 +_DOWNLOAD: 1 +_EXCLUDEFROMAUTOADR: 0 +_COMMENT: '' + +_MODULE: '3S' +_SECTION_NAME: 'K_Bus' +_INDEX_IN_PARENT: '1' +_MODULE_NAME: 'K-Bus' +_NODE_ID: 0 +_IECIN: %IB0 +_IECOUT: %QB0 +_IECDIAG: %MB0 +_DOWNLOAD: 1 +_EXCLUDEFROMAUTOADR: 0 +_COMMENT: '' +_END_MODULE + +_MODULE: '3S' +_SECTION_NAME: 'FB_VARS' +_INDEX_IN_PARENT: '2' +_MODULE_NAME: 'Fieldbus variables' +_NODE_ID: 1 +_IECIN: %IB0 +_IECOUT: %QB0 +_IECDIAG: %MB0 +_DOWNLOAD: 1 +_EXCLUDEFROMAUTOADR: 0 +_COMMENT: '' +_END_MODULE +_END_MODULE +PLC_END + + +RESOURCE +{event_task : 'start','Called when program starts','','FUNCTION systemevent: DWORD VAR_INPUT dwEvent: DWORD; dwFilter: DWORD; dwOwner: DWORD; END_VAR '}{event_task_info : 0,1,11986} +{event_task : 'stop','Called when program stops','','FUNCTION systemevent: DWORD VAR_INPUT dwEvent: DWORD; dwFilter: DWORD; dwOwner: DWORD; END_VAR '}{event_task_info : 0,2,11986} +{event_task : 'before_reset','Called before reset takes place','','FUNCTION systemevent: DWORD VAR_INPUT dwEvent: DWORD; dwFilter: DWORD; dwOwner: DWORD; END_VAR '}{event_task_info : 0,3,11986} +{event_task : 'after_reset','Called after reset took place','','FUNCTION systemevent: DWORD VAR_INPUT dwEvent: DWORD; dwFilter: DWORD; dwOwner: DWORD; END_VAR '}{event_task_info : 0,4,11986} +{event_task : 'shutdown','Called before shutdown is performed (Firmware update over ethernet)','','FUNCTION systemevent: DWORD VAR_INPUT dwEvent: DWORD; dwFilter: DWORD; dwOwner: DWORD; END_VAR '}{event_task_info : 0,5,11986} +{event_task : 'excpt_watchdog','Software watchdog of IEC-task expired','','FUNCTION systemevent: DWORD VAR_INPUT dwEvent: DWORD; dwFilter: DWORD; dwOwner: DWORD; END_VAR '}{event_task_info : 0,7,11986} +{event_task : 'excpt_fieldbus','Fieldbus error','','FUNCTION systemevent: DWORD VAR_INPUT dwEvent: DWORD; dwFilter: DWORD; dwOwner: DWORD; END_VAR '}{event_task_info : 0,9,11986} +{event_task : 'excpt_ioupdate','KBus error','','FUNCTION systemevent: DWORD VAR_INPUT dwEvent: DWORD; dwFilter: DWORD; dwOwner: DWORD; END_VAR '}{event_task_info : 0,10,11986} +{event_task : 'excpt_dividebyzero','Division by zero. Only integer operations!','','FUNCTION systemevent: DWORD VAR_INPUT dwEvent: DWORD; dwFilter: DWORD; dwOwner: DWORD; END_VAR '}{event_task_info : 0,18,11986} +{event_task : 'excpt_noncontinuable','Exception handler','','FUNCTION systemevent: DWORD VAR_INPUT dwEvent: DWORD; dwFilter: DWORD; dwOwner: DWORD; END_VAR '}{event_task_info : 0,20,11986} +{event_task : 'after_reading_inputs','Called after reading of inputs','','FUNCTION systemevent: DWORD VAR_INPUT dwEvent: DWORD; dwFilter: DWORD; dwOwner: DWORD; END_VAR '}{event_task_info : 0,28,11986} +{event_task : 'before_writing_outputs','Called before writing of outputs','','FUNCTION systemevent: DWORD VAR_INPUT dwEvent: DWORD; dwFilter: DWORD; dwOwner: DWORD; END_VAR '}{event_task_info : 0,29,11986} +{event_task : 'debug_loop','Debug loop at breakpoint','','FUNCTION systemevent: DWORD VAR_INPUT dwEvent: DWORD; dwFilter: DWORD; dwOwner: DWORD; END_VAR '}{event_task_info : 0,31,11986} +{event_task : 'online_change','Is called after CodeInit() at Online-Change','','FUNCTION systemevent: DWORD VAR_INPUT dwEvent: DWORD; dwFilter: DWORD; dwOwner: DWORD; END_VAR '}{event_task_info : 0,33,11986} +{event_task : 'before_download','Is called before the Download starts','','FUNCTION systemevent: DWORD VAR_INPUT dwEvent: DWORD; dwFilter: DWORD; dwOwner: DWORD; END_VAR '}{event_task_info : 0,34,11986} +{event_task : 'event_login','Is called before the login service is performed','','FUNCTION systemevent: DWORD VAR_INPUT dwEvent: DWORD; dwFilter: DWORD; dwOwner: DWORD; END_VAR '}{event_task_info : 0,501,11986} +{event_task : 'eth_overload','Ethernet Overload','','FUNCTION systemevent: DWORD VAR_INPUT dwEvent: DWORD; dwFilter: DWORD; dwOwner: DWORD; END_VAR '}{event_task_info : 0,750,11986} +{event_task : 'eth_network_ready','Is called directly after the Network and the PLC are initialised','','FUNCTION systemevent: DWORD VAR_INPUT dwEvent: DWORD; dwFilter: DWORD; dwOwner: DWORD; END_VAR '}{event_task_info : 0,751,11986} +{event_task : 'blink_code','New blink code / Blink code cleared ( Call STATUS_GET_LAST_ERROR for details )','','FUNCTION systemevent: DWORD VAR_INPUT dwEvent: DWORD; dwFilter: DWORD; dwOwner: DWORD; END_VAR '}{event_task_info : 0,752,11986} +{event_task : 'interrupt_0','Interrupt Real Time Clock (every second)','','FUNCTION systemevent: DWORD VAR_INPUT dwEvent: DWORD; dwFilter: DWORD; dwOwner: DWORD; END_VAR '}{event_task_info : 0,1000,11986} + +END_RESOURCE + + +_WORKSPACE +_GLOBALVISUALSETTINGS +_VISUALSETTINGSFLAGS : 0,0,0,0 +_VISUALSETTINGSFLAGS : '','','' +_VISUALSETTINGSDYNTEXTFILECOUNT : 0 +_VISUALBITMAPLISTCOUNT : 0 +_END_GLOBALVISUALSETTINGS +_END_WORKSPACE diff --git a/tests/Codesys/_make_exp.cmd b/tests/Codesys/_make_exp.cmd new file mode 100644 index 0000000..415af58 --- /dev/null +++ b/tests/Codesys/_make_exp.cmd @@ -0,0 +1,15 @@ +rem Create Codesys EXP file + +rem Build cmd file +set CODESYS="c:\Program Files (x86)\WAGO Software\CoDeSys V2.3\codesys.exe" +set PROJECT=test +del %PROJECT%.EXP +echo file open %PROJECT%.pro >> codesys_cmd_file.cmd +echo project export %PROJECT%.EXP >> codesys_cmd_file.cmd +rem echo file saveas %PROJECT%.lib internallib >> codesys_cmd_file.cmd +echo file close >> codesys_cmd_file.cmd +echo file quit >> codesys_cmd_file.cmd +%CODESYS% /noinfo /cmd codesys_cmd_file.cmd + +rem Clean all when finished +del codesys_cmd_file.cmd \ No newline at end of file diff --git a/tests/Codesys/test.pro b/tests/Codesys/test.pro new file mode 100644 index 0000000..6904c0c Binary files /dev/null and b/tests/Codesys/test.pro differ diff --git a/tests/IecType/ref/test.iecReal.php.html b/tests/IecType/ref/test.iecReal.php.html index 661237e..a195b00 100644 --- a/tests/IecType/ref/test.iecReal.php.html +++ b/tests/IecType/ref/test.iecReal.php.html @@ -1,12 +1,12 @@ -Endianing off
-0 --> Packet: 0000_0000_
-1 --> Packet: 0000_3f80_
--2 --> Packet: 0000_c000_
-0.333333333333 --> Packet: aaaa_3eaa_
-25 --> Packet: 0000_41c8_
-Endianing on
-0 --> Packet: 0000_0000_
-1 --> Packet: 3f80_0000_
--2 --> Packet: c000_0000_
-0.333333333333 --> Packet: 3eaa_aaaa_
-25 --> Packet: 41c8_0000_
\ No newline at end of file +Endianing off
+0 --> Packet: 0000_0000_
+1 --> Packet: 0000_3f80_
+-2 --> Packet: 0000_c000_
+0.333333333333 --> Packet: aaab_3eaa_
+25 --> Packet: 0000_41c8_
+Endianing on
+0 --> Packet: 0000_0000_
+1 --> Packet: 3f80_0000_
+-2 --> Packet: c000_0000_
+0.333333333333 --> Packet: 3eaa_aaab_
+25 --> Packet: 41c8_0000_
diff --git a/tests/IecType/test.iecReal.php b/tests/IecType/test.iecReal.php index f9ed82d..30495fd 100644 --- a/tests/IecType/test.iecReal.php +++ b/tests/IecType/test.iecReal.php @@ -7,7 +7,7 @@ "0" => 0, // -> 0000 0000 "1" => 1, // -> 3f80 0000 "2" => -2, // -> c000 0000 - "3" => 1/3, // -> 3eaa aaab + "3" => 0.333333333333, //1/3 -> 3eaa aaab "4" => 25 // -> 41c8 0000 ); diff --git a/tests/ModbusMaster/ref/test.tcp.socket_protocol_mismatch.php.html b/tests/ModbusMaster/ref/test.tcp.socket_protocol_mismatch.php.html index 294f1f5..b25cfe4 100644 --- a/tests/ModbusMaster/ref/test.tcp.socket_protocol_mismatch.php.html +++ b/tests/ModbusMaster/ref/test.tcp.socket_protocol_mismatch.php.html @@ -1,7 +1 @@ - -Fatal error: Uncaught exception 'Exception' with message 'Unknown socket protocol, should be 'TCP' or 'UDP'' in D:\Projects\20081010_phpmodbus\src\trunk\Phpmodbus\ModbusMaster.php:87 -Stack trace: -#0 D:\Projects\20081010_phpmodbus\src\trunk\Phpmodbus\ModbusMaster.php(654): ModbusMaster->connect() -#1 D:\Projects\20081010_phpmodbus\src\trunk\tests\ModbusMaster\test.tcp.socket_protocol_mismatch.php(13): ModbusMaster->readWriteRegisters(0, 12288, 6, 12288, Array, Array) -#2 {main} - thrown in D:\Projects\20081010_phpmodbus\src\trunk\Phpmodbus\ModbusMaster.php on line 87 +Caught exception: Unknown socket protocol, should be 'TCP' or 'UDP' diff --git a/tests/ModbusMaster/test.tcp.socket_protocol_mismatch.php b/tests/ModbusMaster/test.tcp.socket_protocol_mismatch.php index ed016b4..aa5f691 100644 --- a/tests/ModbusMaster/test.tcp.socket_protocol_mismatch.php +++ b/tests/ModbusMaster/test.tcp.socket_protocol_mismatch.php @@ -10,9 +10,13 @@ $dataTypes = array("REAL", "REAL", "REAL", "REAL"); // FC23 -$recData = $modbus->readWriteRegisters(0, 12288, 6, 12288, $data, $dataTypes); - +try { + $recData = $modbus->readWriteRegisters(0, 12288, 6, 12288, $data, $dataTypes); +} catch (Exception $e) { + echo 'Caught exception: ', $e->getMessage(), "\n"; + exit(); +} // Should through an Exception // Print status information -echo "Something wrong!"; \ No newline at end of file +echo "Should never reach this line!"; \ No newline at end of file diff --git a/tests/ModbusMasterUdp/ref/test.fc15fc1.php.html b/tests/ModbusMasterUdp/ref/test.fc15fc1.php.html new file mode 100644 index 0000000..55a3de0 --- /dev/null +++ b/tests/ModbusMasterUdp/ref/test.fc15fc1.php.html @@ -0,0 +1,66 @@ +array(32) { + [0]=> + bool(true) + [1]=> + bool(false) + [2]=> + bool(true) + [3]=> + bool(true) + [4]=> + bool(false) + [5]=> + bool(true) + [6]=> + bool(true) + [7]=> + bool(true) + [8]=> + bool(true) + [9]=> + bool(true) + [10]=> + bool(true) + [11]=> + bool(true) + [12]=> + bool(false) + [13]=> + bool(false) + [14]=> + bool(false) + [15]=> + bool(false) + [16]=> + bool(false) + [17]=> + bool(false) + [18]=> + bool(false) + [19]=> + bool(false) + [20]=> + bool(true) + [21]=> + bool(true) + [22]=> + bool(true) + [23]=> + bool(true) + [24]=> + bool(true) + [25]=> + bool(true) + [26]=> + bool(true) + [27]=> + bool(true) + [28]=> + bool(true) + [29]=> + bool(true) + [30]=> + bool(true) + [31]=> + bool(true) +} diff --git a/tests/ModbusMasterUdp/ref/test.fc16fc3.php.html b/tests/ModbusMasterUdp/ref/test.fc16fc3.php.html index c3e4836..00dd046 100644 --- a/tests/ModbusMasterUdp/ref/test.fc16fc3.php.html +++ b/tests/ModbusMasterUdp/ref/test.fc16fc3.php.html @@ -62,7 +62,7 @@ [10] => 192 [11] => 0 [12] => 170 - [13] => 170 + [13] => 171 [14] => 62 [15] => 170 [16] => 0 diff --git a/tests/ModbusMasterUdp/ref/test.fc2.php.html b/tests/ModbusMasterUdp/ref/test.fc2.php.html new file mode 100644 index 0000000..5baae72 --- /dev/null +++ b/tests/ModbusMasterUdp/ref/test.fc2.php.html @@ -0,0 +1,7 @@ +Test should pass when %IX0.0==FALSE and %IX0.1==TRUE +array(2) { + [0]=> + bool(false) + [1]=> + bool(true) +} diff --git a/tests/ModbusMasterUdp/ref/test.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/ref/test.fc6fc3.php.html b/tests/ModbusMasterUdp/ref/test.fc6fc3.php.html new file mode 100644 index 0000000..6102dcd --- /dev/null +++ b/tests/ModbusMasterUdp/ref/test.fc6fc3.php.html @@ -0,0 +1,5 @@ +Array +( + [0] => 207 + [1] => 199 +) diff --git a/tests/ModbusMasterUdp/test.fc15fc1.php b/tests/ModbusMasterUdp/test.fc15fc1.php index 090bdcb..5a7d8c4 100644 --- a/tests/ModbusMasterUdp/test.fc15fc1.php +++ b/tests/ModbusMasterUdp/test.fc15fc1.php @@ -12,11 +12,11 @@ 1, 1, TRUE, TRUE, 1, 1, TRUE, TRUE); // Write data - FC 15 $modbus->writeMultipleCoils(0, 12288, $data); -echo $modbus->status; -$modbus->status = ""; -echo "\n\n"; +//echo $modbus->status; +//$modbus->status = ""; +//echo "\n\n"; // Read data - FC 1 $recData = $modbus->readCoils(0, 12288, 32); -echo $modbus->status; -echo "\n\n"; +//echo $modbus->status; +//echo "\n\n"; var_dump($recData); \ No newline at end of file diff --git a/tests/ModbusMasterUdp/test.fc2.php b/tests/ModbusMasterUdp/test.fc2.php new file mode 100644 index 0000000..3c73077 --- /dev/null +++ b/tests/ModbusMasterUdp/test.fc2.php @@ -0,0 +1,14 @@ +readInputDiscretes(0, 0, 2); + +var_dump($recData); \ No newline at end of file diff --git a/tests/ModbusMasterUdp/test.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/ModbusMasterUdp/test.fc6fc3.php b/tests/ModbusMasterUdp/test.fc6fc3.php new file mode 100644 index 0000000..03c39f5 --- /dev/null +++ b/tests/ModbusMasterUdp/test.fc6fc3.php @@ -0,0 +1,15 @@ +writeSingleRegister(0, 12288, $data, $dataTypes); +// Read data - FC3 +$recData = $modbus->readMultipleRegisters(0, 12288, 1); +print_r($recData); diff --git a/tests/config.bat b/tests/config.bat index 5560180..ef49dfc 100644 --- a/tests/config.bat +++ b/tests/config.bat @@ -1,4 +1,4 @@ -set php=c:\Program_Files\xampplite\php\php.exe +set php=c:\Program_Files\xampp\php\php.exe rem set php=C:\PHP\versions\php-5.2.6-Win32\php.exe -d auto_prepend_file=C:\PHP\locale.php set diff="diff.exe" rem set testUri=http://localHost/nette/_trunk/tests diff --git a/tests/config.php b/tests/config.php index e9133a3..9c71b4a 100644 --- a/tests/config.php +++ b/tests/config.php @@ -1,4 +1,3 @@ \ No newline at end of file + $test_host_ip = "192.192.1.10"; + $test_bind_client_ip = "192.192.1.100"; \ No newline at end of file diff --git a/tutorials/Phpmodbus/Phpmodbus.pkg b/tutorials/Phpmodbus/Phpmodbus.pkg index 2ef74ff..d3e57ea 100644 --- a/tutorials/Phpmodbus/Phpmodbus.pkg +++ b/tutorials/Phpmodbus/Phpmodbus.pkg @@ -22,7 +22,11 @@ The library implements: 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 FC 23: read write registers @@ -32,9 +36,6 @@ For more about Modbus protocol see [{@link http://www.modbus.org}] or [{@link http://en.wikipedia.org/wiki/Modbus Wiki}] - - Developed with support of {@link http://www.wago.com}. - Install @@ -104,6 +105,15 @@ catch (Exception $e) { {@example example_fc1.php} + + FC2 - read input discretes + + FC2 functionality example + + + {@example example_fc2.php} + + FC3 - read mutliple registers @@ -113,6 +123,33 @@ 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 + + FC6 functionality example + + + {@example example_fc6.php} + + FC15 - write mutliple coils