Foreword
I believe that many PHP programmers have encountered a thorny problem, how does PHP communicate with PLC.
As a very popular programming language, PHP covers almost all the advantages of web services, but because of its biased nature of web services, its appeal for local functionalization is weak compared to its expansion.
When you use PHP to do industrial control systems, such as WCS and MES, you will find this point even more. Sometimes a simple requirement will basically make you close to collapse. For example, “how to communicate with PLC” is a good example .
In the field of industrial control, there are hundreds of PLCs and PLC protocols, and if you search for related keywords in Github, you will find that there is no PHP extension for PLC, even the standard extension of OPCUA. .
I think it is necessary to provide a channel for PHP to communicate with PLC. Since I am also a developer of industrial automation systems, including MES and WCS, both use the PHP+Workerman-based architecture, so this demand is even more urgent.
Solution
LECPServer can become a very good communication bridge between PHP and PLC.
The full name of LECPServer is Leanboard Equipment Communication Proxy Server. It is a high-performance industrial configuration service software developed based on the JLean framework. Through this configuration software, 90% of the PLCs on the market can be linked, and the reading and writing of PLCs can be communicated through the HTTP protocol, enabling users to Ability to connect, manage, monitor and control different automation devices and software applications through one intuitive user interface.
Since LECPServer is also based on the architecture of Web services, as long as the client can make a Request through HTTP POST, it can naturally communicate with the PLC, which of course includes PHP, a language platform for Web services.
Installation and Environment
First of all, you can go to the official website to download the latest version of LECPServer
https://www.lecpserver.com/downloads/LECPServer.zip
LECPServer is free of installation, it can be run directly in the folder, and the following supporting environment is required for operation
- Microsoft .NET Framework 4.6.1 or above
- Visual C++ Redistributable Packages for Visual Studio 2013
I also put the download link below
Microsoft .NET Framework 4.6.1 Download .NET Framework 4.6.1 Web Installer
https://dotnet.microsoft.com/download/dotnet-framework/thank-you/net461-web-installer
Visual C++ Redistributable Packages for Visual Studio 2013
https://www.microsoft.com/zh-cn/download/details.aspx?id=40784
After the installation is complete, double-click LECPServer.exe to start the program
Example
We take the PLC connected to Omron CP1H as an example to demonstrate how to communicate with Omron CP1H through LECPServer.
We connect Omron CP1H via Ethernet, the IP of the PLC is set to 192.168.3.20, and the IP of the machine is set to 192.168.3.202
Through the configuration interface of LECPServer, configure the corresponding parameters, as shown in the figure:
Then click Apply, when you see that the list in the device column is green, it means that the PLC has been formally connected successfully
At this time, we can use HTTP POST debugging tools, such as POSTMAN, HTTP Debug to test whether it can read and write normally. Here we choose the HTTP debugger that comes with LECPServer.
We first send the plc_read_node command to check the value of D0000
{
"action": "plc_read_node",
"node": "NODES.CP1H.D0000"
}
// 返回
{
"errcode": 0,
"errmsg": "",
"rtval": [
0
]
}
It means that the length of node D0000 is 1, and the first value is 0. We try to change the value of D0000 through the command plc_write_node
{
"action": "plc_write_node",
"node": "NODES.CP1H.D0000",
"value": [
998
]
}
// 返回
{
"errcode": 0,
"errmsg": ""
}
No error is returned, which means that the value of D0000 has been successfully changed, and then we can verify whether the change is successful through the plc_read_node command
{
"action": "plc_read_node",
"node": "NODES.CP1H.D0000"
}
// 返回
{
"errcode": 0,
"errmsg": "",
"rtval": [
998
]
}
At this point, our preparatory work has been completed, and the next step is the coding stage of PHP.
PHP source code
For the PHP sample here, we use PHP7.1 + Workerman to complete, and the FastCGI method is basically similar.
directly on the code
<?php
use Workerman\Worker;
use Workerman\Mysql;
use \Workerman\Lib\Timer;
use \Workerman\Protocols\Http;
use \Workerman\Protocols\Http\Response;
use \Workerman\WebServer;
// http client functions using curl extension
function curl_http_request($url, $type, $data = ""){
$ch = curl_init();
$timeout = 1;
curl_setopt( $ch , CURLOPT_TIMEOUT, $timeout );
curl_setopt( $ch , CURLOPT_CONNECTTIMEOUT_MS, 200);
curl_setopt( $ch , CURLOPT_HEADER, false);
curl_setopt( $ch , CURLOPT_URL, $url);
curl_setopt( $ch , CURLOPT_RETURNTRANSFER, 1);
if($type == "POST"){
curl_setopt( $ch , CURLOPT_POST, 1);
curl_setopt($ch,CURLOPT_HTTPHEADER,array('Content-Type: application/json'));
curl_setopt( $ch , CURLOPT_POSTFIELDS, $data);
}else{
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, 0); // Checks on the source of authentication certificates
curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 1); // Check whether the SSL encryption algorithm exists from the certificate
curl_setopt($curl, CURLOPT_SSLVERSION, 3);
}
$output = curl_exec($ch);
curl_close($ch);
if($output!=""){
$val = json_decode($output,true);
return $val;
}else{
return null;
}
}
// Start a worker and start a timer in it to read and write the PLC point D0000 every 500ms
$client_worker = new Worker();
$client_worker->name = "plc reader";
$client_worker->count = 1;
// service start
$client_worker->onWorkerStart = function($worker) {
// Count the value from 80 and increment
$count = 80;
Timer::add(0.5, function() use(&$count)
{
echo "Start reading the value of PLC D0000 \r\n";
$rtval = curl_http_request("http://192.168.3.20:8088", "POST", '{"action":"plc_read_node", "node":"NODES.CP1H.D0000"}');
echo "PLC D0000 read successfully ";
echo json_encode($rtval) . "\r\n";
echo "Start writing the value of PLC D0000 \r\n";
$rtval = curl_http_request("http://192.168.3.20:8088", "POST", '{"action":"plc_write_node", "node":"NODES.CP1H.D0000", "value":[' . $count . ']}');
echo "PLC D0000 writing completed ";
echo json_encode($rtval) . "\r\n";
$count ++ ;
});
};
if(!defined('GLOBAL_START')){
Worker::runAll();
}
?>
The running effect is as follows. It can be seen that the PLC is read and written normally by the PHP program.