2025-03-20 22:40:01 +01:00
|
|
|
# Serial port support for ReactPHP
|
|
|
|
|
|
|
|
> [!NOTE]
|
|
|
|
> Only Linux is supported for now. Feel free to contribute support for additional platforms.
|
|
|
|
|
|
|
|
## Installing
|
|
|
|
|
|
|
|
```bash
|
|
|
|
$ composer require noccylabs/react-serial:@dev
|
|
|
|
```
|
|
|
|
|
|
|
|
## Using
|
|
|
|
|
|
|
|
The `SerialFactory` is really a *SerialStreamFactory*. Its `open()` method returns a promise
|
|
|
|
that will resolve with a duplex stream for the port.
|
|
|
|
|
|
|
|
```php
|
|
|
|
$serial = new SerialFactory();
|
|
|
|
$serial->open("/dev/ttyUSB0", 115200)
|
2025-03-21 13:49:37 +01:00
|
|
|
->then(function (DuplexStreamInterface $stream) { ... });
|
2025-03-20 22:40:01 +01:00
|
|
|
```
|
|
|
|
|
|
|
|
You may find that you need line buffering, in which case you should wrap the stream in a
|
|
|
|
`LineBufferedDuplexStream`. The wrapped stream will emit the same `data` and `close` events
|
|
|
|
as the original stream, but it will also emit a `line` event once a full line has been
|
|
|
|
received. If you give it a `$promptPattern` in the constructor it will also emit a `prompt`
|
|
|
|
event whenever a matching prompt is detected, and with `$bufferOutput` you will also get
|
|
|
|
an `output` event with all the `line`s emitted since the last `prompt`.
|
|
|
|
|
|
|
|
```php
|
2025-03-21 13:49:37 +01:00
|
|
|
// Wrap our stream and use '#> ' as the prompt pattern.
|
|
|
|
$shell = new LineBufferedDuplexStream($stream, promptPattern: '/\#\> /', bufferOutput:true);
|
|
|
|
|
|
|
|
// Prepare the commands to execute, in order. These are the commands you would use
|
|
|
|
// on an OpenWRT router to configure the WiFi password for the "main" WiFi interface.
|
|
|
|
$commands = [
|
|
|
|
'uci set wireless.main.key="pennyisafreeloader"',
|
|
|
|
'uci commit wireless',
|
|
|
|
'wifi restart',
|
|
|
|
];
|
|
|
|
|
|
|
|
// Execute the next command once we get a prompt
|
|
|
|
$shell->on("prompt", function () use ($shell, &$commands) {
|
|
|
|
$command = array_shift($commands);
|
|
|
|
if (!$command) {
|
|
|
|
// Closing the wrapper closes the stream
|
|
|
|
$shell->close();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
echo $command."\n";
|
|
|
|
$shell->write($command."\n");
|
|
|
|
});
|
|
|
|
|
|
|
|
// Receives all the output lines from the last command.
|
|
|
|
$shell->on("output", function(array $lines) {
|
|
|
|
echo " ".join("\n ",$lines)."\n";
|
|
|
|
});
|
|
|
|
|
|
|
|
// write "echo" to the shell on our fictive device to get a fresh prompt
|
|
|
|
$shell->write("echo\n");
|
2025-03-20 22:40:01 +01:00
|
|
|
```
|