-
Notifications
You must be signed in to change notification settings - Fork 56
/
example_cli_poller.php
77 lines (64 loc) · 3.27 KB
/
example_cli_poller.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
<?php
if (php_sapi_name() !== 'cli') {
echo 'Should be used only in command line interface';
return;
}
require __DIR__ . '/../vendor/autoload.php';
use ModbusTcpClient\Composer\Read\ReadRegistersBuilder;
use ModbusTcpClient\Utils\Packet;
$requests = ReadRegistersBuilder::newReadHoldingRegisters('tcp://127.0.0.1:5022')
->bit(278, 5, 'dirchange1_status')
->int16(256, 'room2_temp_wo')
// will be split into 2 requests as 1 request can return only range of 124 registers max
->uint16(453, 'gen1_fuel_rate_wo')
// will be another request as uri is different for subsequent string register
->useUri('tcp://127.0.0.1:5023')
->int16(270, 'room7_temp_wo', function ($value) {
return $value ? $value / 10 : $value; // transform value after extraction
})
->build(); // returns array of 3 requests
// Install: 'composer require react/socket:^1.11'
// NB: install PHP extension ('ev', 'event' or 'uv') if the concurrent socket connections are more than 1024.
$loop = React\EventLoop\Loop::get();
$n = 60;
$loop->addPeriodicTimer(1.0, function () use ($loop, &$n, $requests) {
echo microtime(true) . ": TICK! remaining {$n} seconds" . PHP_EOL;
foreach ($requests as $request) {
$connector = new React\Socket\Connector($loop, array(
'dns' => false,
'timeout' => 0.2
));
$connector->connect($request->getUri())->then(
function (React\Socket\ConnectionInterface $connection) use ($request) {
$receivedData = b'';
echo microtime(true) . ": connected to {$request->getUri()}" . PHP_EOL;
$connection->write($request);
// wait for response event
$connection->on('data', function ($data) use ($connection, $request, &$receivedData) {
// there are rare cases when MODBUS packet is received by multiple fragmented TCP packets and it could
// take PHP multiple reads from stream to get full packet. So we concatenate data and check if all that
// we have received makes a complete modbus packet.
// NB: `Packet::isCompleteLength` is suitable only for modbus TCP packets
$receivedData .= $data;
if (Packet::isCompleteLength($receivedData)) {
echo microtime(true) . ": uri: {$request->getUri()}, complete response: " . print_r($request->parse($receivedData), true) . PHP_EOL;
$connection->end();
} else {
echo microtime(true) . ": uri: {$request->getUri()}, partial response: " . print_r($data, true) . PHP_EOL;
}
});
$connection->on('error', function ($data) use ($connection, $request) {
echo microtime(true) . ": uri: {$request->getUri()}, Error during connection! error: " . print_r($data, true) . PHP_EOL;
$connection->end();
});
},
function (Exception $error) use ($request) {
echo microtime(true) . ": uri: {$request->getUri()}, failed to connect! error: " . $error->getMessage() . PHP_EOL;
});
}
if ($n <= 0) {
$loop->stop();
}
$n--;
});
$loop->run();