Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

BUG: stream_select interrupted by an incoming signal #151

Open
netoscz opened this issue Sep 22, 2023 · 7 comments
Open

BUG: stream_select interrupted by an incoming signal #151

netoscz opened this issue Sep 22, 2023 · 7 comments
Labels

Comments

@netoscz
Copy link

netoscz commented Sep 22, 2023

I use this example script to communicate with Solax X3 G4 on COM port using RS485/ETH converter a then using modbus RTU over TCP protocol:

<?php

use ModbusTcpClient\Network\BinaryStreamConnection;
use ModbusTcpClient\Packet\ModbusFunction\ReadHoldingRegistersRequest;
use ModbusTcpClient\Packet\RtuConverter;
use ModbusTcpClient\Utils\Packet;

require '../vendor/autoload.php';

$connection = BinaryStreamConnection::getBuilder()
    ->setPort(myPort)
    ->setHost('myIP')
    ->setReadTimeoutSec(3) // increase read timeout to 3 seconds
    ->setIsCompleteCallback(function ($binaryData, $streamIndex) {
        return Packet::isCompleteLengthRTU($binaryData);
    })
    ->build();

$startAddress = 182;
$quantity = 1;
$slaveId = 1; // RTU packet slave id equivalent is Modbus TCP unitId

$tcpPacket = new ReadHoldingRegistersRequest($startAddress, $quantity, $slaveId);
$rtuPacket = RtuConverter::toRtu($tcpPacket);

try {
    $binaryData = $connection->connect()->sendAndReceive($rtuPacket);
    echo 'RTU Binary received (in hex):   ' . unpack('H*', $binaryData)[1] . PHP_EOL;

    $response = RtuConverter::fromRtu($binaryData);
    echo 'Parsed packet (in hex):     ' . $response->toHex() . PHP_EOL;
    echo 'Data parsed from packet (bytes):' . PHP_EOL;
    print_r($response->getData());

} catch (Exception $exception) {
    echo 'An exception occurred' . PHP_EOL;
    echo $exception->getMessage() . PHP_EOL;
    echo $exception->getTraceAsString() . PHP_EOL;
} finally {
    $connection->close();
}
?>
  • Environment:
  • OS: Linux 5.10.0-vch1-amd64 x86_64
  • PHP version: 8.2.7
  • Library version 3.4.0

If I try to insert the same input data into any Windows EXE program used to test modbus RTU over TCP communication, then there is no problem, everything communicates as it should. But if I use them in the PHP code, see above, the result is always the error "An exception occurred stream_select interrupted by an incoming signal".

Specifically:
An exception occurred stream_select interrupted by an incoming signal #0 /home/www/xxx.cz/www/fve.xxx.cz/vendor/aldas/modbus-tcp-client/src/Network/BinaryStreamConnection.php(67): ModbusTcpClient\Network\BinaryStreamConnection->receiveFrom() #1 /home/www/xxx.cz/www/fve.xxx.cz/vendor/aldas/modbus-tcp-client/src/Network/BinaryStreamConnection.php(90): ModbusTcpClient\Network\BinaryStreamConnection->receive() #2 /home/www/xxx.cz/www/fve.xxx.cz/ote/rtu.php(27): ModbusTcpClient\Network\BinaryStreamConnection->sendAndReceive() #3 {main}

It looks like a library bug. Please help.

@netoscz netoscz added the bug label Sep 22, 2023
@aldas
Copy link
Owner

aldas commented Sep 22, 2023

#150 (comment) or #150 (comment) maybe this helps

@netoscz
Copy link
Author

netoscz commented Sep 22, 2023

Unfortunately the thread ends with words "no luck :/". In the end, the problem was not solved. But do you think that this is not a problem of the library as such? But then I'm already desperate, where to look for the error elsewhere, when other programs connect to the inverter fine.

@netoscz
Copy link
Author

netoscz commented Sep 22, 2023

The administrator of my VPS analyzed the situation on his side and wrote me the following: I tried to trace the system calls of the process that handled the running of the modbus3.php script, and I found that a connection was successfully established with the IP address MyIP, port MyPort. The process then sent 8 bytes of data on this connection and waited 300 milliseconds for a response, which did not arrive within this time limit. According to the files that were worked with subsequently (IOException.php, ModbusException.php), I conclude that the used library considers it an error condition and no longer waits.

I therefore recommend checking whether the connection and data transfer can be implemented in such a short time, and possibly increase the time limit.

Then I tried setting ->setDelayRead(5000_000) so I tried editing that piece of code in StreamHandler.php. Both without success.

@aldas
Copy link
Owner

aldas commented Sep 22, 2023

ok, could you first try with https://www.modbusdriver.com/modpoll.html and see if it works or not. This is to verify if this mainly PHP/this library problem or something bigger.

That inverter manual says about timeouts:
image

From https://gbc-solino.cz/wp-content/uploads/2022/07/Hybrid-X1X3-G4-ModbusTCPRTU-V3.21-English_0622-public-version.pdf page 8

after that I have modified your example to add more waits between steps and added logger to see debug output.

<?php

use ModbusTcpClient\Network\BinaryStreamConnection;
use ModbusTcpClient\Packet\ModbusFunction\ReadHoldingRegistersRequest;
use ModbusTcpClient\Packet\RtuConverter;
use ModbusTcpClient\Utils\Packet;

require __DIR__ . '/../vendor/autoload.php';
require __DIR__ . '/logger.php';

$connection = BinaryStreamConnection::getBuilder()
    ->setPort(5020) // FIXME to correct port
    ->setHost('myIP')
    ->setReadTimeoutSec(3) // increase read timeout to 3 seconds
    ->setIsCompleteCallback(function ($binaryData, $streamIndex) {
        return Packet::isCompleteLengthRTU($binaryData);
    })
    ->setLogger(new EchoLogger())
    ->build();

$startAddress = 182;
$quantity = 1;
$slaveId = 1; // RTU packet slave id equivalent is Modbus TCP unitId

$tcpPacket = new ReadHoldingRegistersRequest($startAddress, $quantity, $slaveId);
$rtuPacket = RtuConverter::toRtu($tcpPacket);

try {
    $connection->connect();
    usleep(200_000); // wait 200ms after connecting

    $connection->send($rtuPacket);
    usleep(300_000); // wait 500ms after send the packet, try different wait times here.
    $binaryData = $connection->receive();
    echo 'RTU Binary received (in hex):   ' . unpack('H*', $binaryData)[1] . PHP_EOL;

    $response = RtuConverter::fromRtu($binaryData);
    echo 'Parsed packet (in hex):     ' . $response->toHex() . PHP_EOL;
    echo 'Data parsed from packet (bytes):' . PHP_EOL;
    print_r($response->getData());

} catch (Exception $exception) {
    echo 'An exception occurred' . PHP_EOL;
    echo $exception->getMessage() . PHP_EOL;
    echo $exception->getTraceAsString() . PHP_EOL;
} finally {
    $connection->close();
}

@aldas
Copy link
Owner

aldas commented Sep 22, 2023

@netoscz
Copy link
Author

netoscz commented Sep 22, 2023

Hello, thanks for your care but it still fails. I use program PowerHud Modbus Tester and everything works perfectly in it. It connects fine and reads the register value with a refresh rate of 1s. It works like a charm. Unfortunately, the PHP script using the modbus-tcp-client library still does not work. Still the same error:

An exception occurred stream_select interrupted by an incoming signal #0 /home/www/xxx.cz/www/fve.bilek.cz/vendor/aldas/modbus-tcp-client/src/Network/BinaryStreamConnection.php(67): ModbusTcpClient\Network\BinaryStreamConnection->receiveFrom() #1 /home/www/bilek.cz/www/fve.xxx.cz/ote/modbus4.php(37): ModbusTcpClient\Network\BinaryStreamConnection->receive() #2 {main}

I tried this sleep values:

`try {
$connection->connect();
usleep(2000_000); // wait 2000ms after connecting

$connection->send($rtuPacket);
usleep(5000_000); // wait 5000ms after send the packet, try different wait times here.
$binaryData = $connection->receive();
echo 'RTU Binary received (in hex):   ' . unpack('H*', $binaryData)[1] . PHP_EOL;`

Unfortunately, I couldn't use logger.php because I don't understand how the path should work
require DIR . '/logger.php';

I don't have a logger.php file in the same directory from which I run my test script. Moreover, I did not find such a file anywhere in the library structure.

@netoscz
Copy link
Author

netoscz commented Sep 22, 2023

I can also tell you that I previously tried modbus TCP (ie not RTU) communication using a wifi dongle in my inverter. The script using your library ran fine. The problem arose only after that when I connected the same inverter via the COM port RS485 serial line via the RS485/ETH Waveshare converter to the ethernet part connected by a cable to the router and using the new modbus RTU over TCP. But I repeat that even this RTU over TCP communication works without problems in the external program.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants