Skip to content

Commit 08be340

Browse files
committed
Updates
1 parent 26485c8 commit 08be340

File tree

2 files changed

+399
-2
lines changed

2 files changed

+399
-2
lines changed

README.md

Lines changed: 396 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,396 @@
1+
# RevolutionPi
2+
3+
This package provides a comprehensive abstraction for interacting with Revolution Pi hardware (and virtualized devices)
4+
within a PHP application. It enables process image access, IO control, LED control, serial port management, and
5+
more, with a convenient and flexible API.
6+
7+
The package has specific support for Laravel, and Laravel Zero. It can also be used with plain PHP, although some
8+
functionality such as the auto-generation commands will not be available.
9+
10+
The package works with the built-in PHP 8.2 on the Debian Bookworm image shipped in the RevolutionPi. No extra
11+
extensions or configuration changes are required.
12+
13+
## Features
14+
15+
- **ProcessImage**: Full read/write access to PiControl variables.
16+
- **Trait-based interface**: Add Revolution Pi capabilities to your own app classes via the `RevolutionPi` trait.
17+
- **LED support**: Control and read RevPi device LEDs (color, position).
18+
- **Serial communications**: Robust non-blocking serial port abstraction for baud rate, parity, stop/data bits, flags
19+
- **Monitor/Observer**: Register IO monitor callbacks for change detection.
20+
- **Magic method & attribute support**: Easy, expressive access to IO variables, matching your PiCtory configuration.
21+
- **Remote (WebSocket/RPC) and Virtual device support**.
22+
23+
---
24+
25+
## Table of Contents
26+
27+
- [Installation](#installation)
28+
- [Simplified interface](#simplified-interface)
29+
- [Accessing IO variables](#accessing-io-variables)
30+
- [Monitoring IO variables](#monitoring-io-variables)
31+
- [Process image](#process-image-low-level)
32+
- [LED control](#led-control)
33+
- [Serial port access](#serial-port-access)
34+
- [Low-level interface](#low-level-interface)
35+
- [Hardware devices (PiControl, Terminal)](#hardware-devices-picontrol-terminal)
36+
- [ProcessImage interface](#processimage-interface)
37+
- [SerialPort interface](#serialport-interface)
38+
- [Monitoring with custom monitors](#monitoring-with-custom-monitors)
39+
- [Remote module usage](#remote-module-usage)
40+
- [Deployment](#deployment)
41+
- [Example: Polling and running the event loop](#example-polling-and-running-the-event-loop)
42+
- [CLI Commands](#cli-commands)
43+
- [License](#license)
44+
45+
---
46+
47+
## Installation
48+
49+
**Require with Composer**
50+
51+
```
52+
composer require flat3/revpi
53+
```
54+
55+
Out of the box `revpi` pulls in only the required packages.
56+
57+
**To include the PHP class generator**
58+
59+
```
60+
composer require --dev nette/php-generator
61+
```
62+
63+
**To include websocket support**
64+
65+
```
66+
composer require amphp/websocket-server amphp/websocket-client
67+
```
68+
69+
---
70+
71+
## Quick start
72+
73+
`flat3/revpi` makes heavy use of the Laravel service container. All concrete implementations can be resolved from
74+
interfaces. Code should either be run *on* the RevolutionPi device, or via an IDE that can run code remotely like
75+
PhpStorm.
76+
77+
```php
78+
use Flat3\RevPi\Interfaces\Module;
79+
use Flat3\RevPi\Led\LedColour;
80+
use Flat3\RevPi\Led\LedPosition;
81+
82+
$pi = app(Module::class); // Resolved from the interface to the correct module type
83+
84+
$pi->led(LedPosition::A1)->set(LedColour::Red);
85+
print_r($pi->led(LedPosition::A1)->get());
86+
```
87+
88+
---
89+
90+
## Simplified Interface
91+
92+
It's recommended to generate a device-specific class from your exported PiCtory JSON. This provides IDE auto-completion
93+
for all IO variables as strongly typed methods and documented properties.
94+
95+
1. **Export your configuration from the PiCtory web interface as a project file**
96+
(e.g. `pictory.rsc`)
97+
98+
2. **Generate the PHP class**
99+
100+
```bash
101+
php artisan revpi:generate pictory.rsc MyPi
102+
```
103+
104+
This creates `app/MyPi.php`.
105+
106+
3. **Use your class**
107+
108+
```php
109+
use Flat3\RevPi\Interfaces\Module;
110+
use Flat3\RevPi\Led\LedColour;
111+
use Flat3\RevPi\Led\LedPosition;
112+
use Flat3\RevPi\Monitors\DigitalMonitor;
113+
use Flat3\RevPi\SerialPort\BaudRate;
114+
use Flat3\RevPi\SerialPort\LocalFlag;
115+
use Illuminate\Console\Command;
116+
use Revolt\EventLoop;
117+
118+
$pi = new \App\MyPi;
119+
120+
// Create an instance of the serial port that loops the input back to the output
121+
$port = $pi->serialPort();
122+
$port->setSpeed(BaudRate::B576000);
123+
$port->clearFlag(LocalFlag::CanonicalInput);
124+
$port->onReadable(function (string $data) use ($port) {
125+
$port->write($data);
126+
});
127+
128+
// Monitor the core temperature, writing updated values to the serial port
129+
$pi->Core_Temperature()->monitor(new DigitalMonitor, function ($value) use ($port) {
130+
$port->write($value."\n");
131+
});
132+
133+
// Start polling
134+
$pi->module()->resume();
135+
136+
// Start the event loop
137+
EventLoop::run();
138+
```
139+
140+
### Accessing IO Variables
141+
142+
Assuming your PiCtory-exported class has an input named `input1` and an output named `output1`:
143+
144+
```php
145+
$pi = new \App\MyPi;
146+
147+
// Read input (as property)
148+
$level = $pi->input1; // int|bool
149+
150+
// Or as a method (returns InputIO object)
151+
$input = $pi->input1();
152+
$currentValue = $input->get();
153+
154+
// Read output
155+
$currentStatus = $pi->output1;
156+
157+
// Set output (as property)
158+
$pi->output1 = true;
159+
160+
// Or as a method (returns OutputIO object)
161+
$pi->output1()->set(1);
162+
163+
// Reset output to its default value
164+
$pi->output1()->reset();
165+
```
166+
167+
### Monitoring IO Variables
168+
169+
The `DigitalMonitor` will cause the callback to be called whenever the monitored value changes.
170+
171+
```php
172+
use Flat3\RevPi\Monitors\DigitalMonitor;
173+
174+
$pi = new \App\MyPi;
175+
176+
$pi->input1()->monitor(new DigitalMonitor, function($newValue) {
177+
// React to input1 changes
178+
logger("input1 changed: $newValue");
179+
});
180+
```
181+
182+
### Process Image (Low-Level)
183+
184+
Get the raw process image interface for advanced access:
185+
186+
```php
187+
$image = $pi->processImage();
188+
189+
$value = $image->readVariable('input1');
190+
$image->writeVariable('output1', 1);
191+
$dump = $image->dumpImage(); // Raw string of process image data
192+
$info = $image->getDeviceInfo(); // Information about the base module
193+
$infoList = $image->getDeviceInfoList(); // Information about all expansion modules
194+
```
195+
196+
### LED Control
197+
198+
```php
199+
use Flat3\RevPi\Led\LedColour;
200+
use Flat3\RevPi\Led\LedPosition;
201+
202+
// Set LED A1 to green
203+
$pi->led(LedPosition::A1)->set(LedColour::Green);
204+
205+
// Get current LED color (as enum)
206+
$current = $pi->led(LedPosition::A1)->get(); // LedColour instance
207+
208+
// Turn an LED off
209+
$pi->led(LedPosition::A1)->off();
210+
```
211+
212+
### Serial Port Access
213+
214+
```php
215+
use Flat3\RevPi\SerialPort\BaudRate;
216+
217+
// Open default serial port
218+
$port = $pi->serialPort();
219+
220+
// Or specify device path:
221+
$port = $pi->serialPort('/dev/ttyRS485-1');
222+
223+
// Configure the port:
224+
$port->setSpeed(BaudRate::B9600);
225+
$port->setParity(Parity::Even);
226+
$port->setDataBits(DataBits::CS8);
227+
228+
// Write and read
229+
$port->write("Hello, RevPi!");
230+
$response = $port->read(128); // up to 128 bytes
231+
232+
// Register event handler for readable data
233+
$port->onReadable(function($data) {
234+
echo "Serial received: $data\n";
235+
});
236+
237+
// Flush or break
238+
$port->flush(QueueSelector::Both);
239+
$port->break();
240+
```
241+
242+
---
243+
244+
## Low-level interface
245+
246+
### Hardware Devices (PiControl, Terminal)
247+
248+
You can inject or instantiate the underlying devices (see `Flat3\RevPi\Interfaces\Hardware\*`) for advanced operations,
249+
e.g. binary FFI device IO, custom IOCTLs, etc.
250+
251+
```php
252+
$picontrol = app(\Flat3\RevPi\Interfaces\Hardware\PiControl::class);
253+
$terminal = app(\Flat3\RevPi\Interfaces\Hardware\Terminal::class);
254+
```
255+
256+
### ProcessImage Interface
257+
258+
Everything required for direct process image manipulation:
259+
260+
```php
261+
$image = app(\Flat3\RevPi\Interfaces\ProcessImage::class);
262+
263+
$value = $image->readVariable('SomeName');
264+
$image->writeVariable('OtherVar', 123);
265+
```
266+
267+
### SerialPort Interface
268+
269+
Inject or use via the module interface.
270+
271+
```php
272+
$port = app(\Flat3\RevPi\Interfaces\SerialPort::class); // Usually you want $pi->serialPort(...)
273+
```
274+
275+
### Monitoring with Custom Monitors
276+
277+
If you want to create a custom monitor (beyond DigitalMonitor):
278+
279+
```php
280+
use Flat3\RevPi\Monitors\Monitor;
281+
282+
class MyMonitor extends Monitor {
283+
public function evaluate(mixed $next): bool {
284+
// Implement custom transition/action logic here
285+
// e.g. if crossing a threshold, fire webhook
286+
// Return true if the monitor has detected sufficient change
287+
}
288+
}
289+
290+
// Register:
291+
$pi->module()->monitor('input1', new MyMonitor, function($newValue) {
292+
// Callback logic
293+
});
294+
```
295+
296+
### Remote Module Usage
297+
298+
You can communicate with a *remote* RevPi device via a WebSocket.
299+
300+
```php
301+
use Flat3\RevPi\RevolutionPi;
302+
303+
$pi = new \App\MyPi;
304+
$pi->remote('ws://10.1.2.3:12873'); // Adding the remote call creates a connection to a device
305+
306+
// From now, other methods act remotely:
307+
$pi->output1 = 1;
308+
$status = $pi->input2;
309+
$pi->led(LedPosition::A1)->set(LedColour::Cyan);
310+
```
311+
312+
The remote device should listen for incoming connections, use `php artisan revpi:listen` to start the server.
313+
314+
Out of the box the package does not provide for authentication, or encryption. These can be added by creating a more
315+
complex websocket handshake object and passing it to the `remote` method. On the server-side, the basic `revpi:listen`
316+
code can be modified to support encryption and authentication.
317+
318+
---
319+
320+
## Deployment
321+
322+
The package has been specifically designed to work with [Laravel Zero](https://laravel-zero.com). Using this technique
323+
will convert your RevolutionPi project into a single executable file that can be started automatically when the base
324+
module boots up.
325+
326+
---
327+
328+
## Example: Polling and running the event loop
329+
330+
Typically you'll want to run your polling/event loop. The package provides an artisan command (see below) or call from
331+
code:
332+
333+
```php
334+
use Revolt\EventLoop;
335+
336+
$pi = new \App\MyPi;
337+
338+
$pi->repeat(1, function($pi) {
339+
// This is called every second
340+
logger("Current value is: " . $pi->input1);
341+
});
342+
343+
EventLoop::run();
344+
```
345+
346+
Or as a CLI command:
347+
348+
```bash
349+
php artisan revpi:run
350+
```
351+
352+
---
353+
354+
## CLI Commands
355+
356+
This package includes artisan commands (`php artisan revpi`):
357+
358+
- `revpi:generate <pictory.json> [class]`
359+
Generate a typed PHP class for your device from your pictory export.
360+
361+
- `revpi:run`
362+
Run your polling/event loop (call `resume()` and enter main loop).
363+
364+
- `revpi:led:get <position>`
365+
Display current color of the chosen LED.
366+
367+
- `revpi:led:set <position> <colour>`
368+
Set a given LED (positions: a1–a5; colors: off, red, green, orange, blue, magenta, cyan, white).
369+
370+
- `revpi:info`
371+
List available device(s) and their info/status.
372+
373+
- `revpi:dump <file>`
374+
Dump the current process image binary to a file.
375+
376+
- `revpi:listen [--address=0.0.0.0] [--port=12873]`
377+
Run the JSON-RPC/WS server for remote connections.
378+
379+
---
380+
381+
## License
382+
383+
[MIT](LICENSE)
384+
Flat3/RevPi, 2025.
385+
386+
---
387+
388+
## Further Reading
389+
390+
- [Revolution Pi Documentation](https://revolutionpi.com/)
391+
- [PiCtory Configuration Tool](https://revolutionpi.com/tutorials/pictory/)
392+
- [Laravel Documentation](https://laravel.com/docs/)
393+
- [Amp](https://amphp.org/)
394+
- [FFI Manual (PHP)](https://www.php.net/manual/en/book.ffi.php)
395+
396+
---

0 commit comments

Comments
 (0)