PHP code example of hamzi / portflow
1. Go to this page and download the library: Download hamzi/portflow library . Choose the download type require .
2. Extract the ZIP file and open the index.php.
3. Add this code to the index.php.
<?php
require_once('vendor/autoload.php');
/* Start to develop here. Best regards https://php-download.com/ */
hamzi / portflow example snippets
use Hamzi\PortFlow\Domain\Events\ProductScanned;
class HandleBarcodeScan
{
public function handle(ProductScanned $event): void
{
$product = Product::where('barcode', $event->barcode)->firstOrFail();
// process $product ...
}
}
Event::listen(ProductScanned::class, HandleBarcodeScan::class);
// config/portflow.php
'default_driver' => 'raw-json',
'driver_options' => [
'raw-json' => [
'delimiter' => "\n",
'max_bytes' => 16384, // rolling buffer ceiling
],
],
'mappings' => [
[
'driver' => 'raw-json',
'payload_field' => 'type',
'equals' => 'barcode.scan',
'event' => ProductScanned::class,
'event_payload_field' => 'barcode',
],
],
$bytes = PortFlow::print('receipts.order', ['order' => $order]);
// $bytes can be sent directly to the printer via Web Serial
use Hamzi\PortFlow\Infrastructure\Printing\EscPosBuilder;
$bytes = (new EscPosBuilder)
->align('center')
->bold()
->text('ACME STORE')
->bold(false)
->divider()
->align('left')
->text('Item 1 ................. $9.99')
->text('Item 2 ................. $4.50')
->divider()
->bold()
->text('TOTAL ................. $14.49')
->bold(false)
->feed(3)
->cut()
->bytes();
$frame->payload['weight'] // "12.500"
$frame->payload['segments'] // ["12.500", "kg", "SCALE-A1"]
$frame->payload['raw'] // "12.500;kg;SCALE-A1"
PortFlow::encode('rs232', ['TARE', '0', 'RESET']);
// → "TARE,0,RESET\n"
// config/portflow.php
'drivers' => [
'my-scale' => \App\SerialDrivers\MyScaleDriver::class,
],
use Hamzi\PortFlow\Domain\Contracts\SerialDriver;
use Hamzi\PortFlow\Domain\DTO\SerialFrame;
final class MyModbusDriver implements SerialDriver
{
public function name(): string
{
return 'modbus';
}
public function configure(array $options = []): void
{
// Store $options for use in parse/encode
}
public function encodeOutbound(array|string $payload): string
{
// Serialize $payload to device-specific bytes
return is_string($payload) ? $payload : json_encode($payload);
}
/** @return array<int, SerialFrame> */
public function parseInbound(string $chunk, array $context = []): array
{
return [
SerialFrame::now($this->name(), ['data' => $chunk], $context),
];
}
}
PortFlow::registerDriver('modbus', MyModbusDriver::class);
use Hamzi\PortFlow\Domain\Contracts\SerialEvent;
final class WeightReceived implements SerialEvent
{
public function __construct(
public readonly string $value,
public readonly array $context = [],
) {}
}
'backend' => [
'allowed_devices' => [
'/dev/ttyUSB0',
'/dev/ttyACM*',
'COM*',
'\\\\.\\COM*',
],
'default_chunk_bytes' => 256,
'default_read_sleep_us' => 20000,
],
// config/portflow.php
'mappings' => [
// Fire ProductScanned when a raw-json frame has type = "barcode.scan"
[
'driver' => 'raw-json',
'payload_field' => 'type',
'equals' => 'barcode.scan',
'event' => ProductScanned::class,
'event_payload_field' => 'barcode',
],
// Match every ESC/POS frame (no payload filter)
[
'driver' => 'escpos',
'event' => ProductScanned::class,
'event_payload_field' => 'barcode',
],
// Persist weight readings directly to an Eloquent model
[
'driver' => 'rs232',
'model' => \App\Models\WeightReading::class,
'field_map' => [
'value' => 'weight', // model column => payload key
'unit' => 'segments.1',
],
],
],
// config/portflow.php (or .env)
'queue_routing' => env('PORTFLOW_QUEUE_ROUTING', false),
$bytes = PortFlow::print('receipts.order', ['order' => $order]);
// Send $bytes to the printer via Web Serial write() or a TCP socket
use Hamzi\PortFlow\Domain\Services\IoTFrameBuffer;
$buffer = new IoTFrameBuffer(delimiter: "\n", maxBytes: 8192);
$frames = $buffer->push("partial-"); // → []
$frames = $buffer->push("data\n"); // → ["partial-data"]
// Flush any incomplete frame before closing the connection
$remainder = $buffer->flushRemainder();
// config/portflow.php
return [
/*
|--------------------------------------------------------------------------
| Default Driver
|--------------------------------------------------------------------------
*/
'default_driver' => env('PORTFLOW_DEFAULT_DRIVER', 'raw-json'),
/*
|--------------------------------------------------------------------------
| Ingest Endpoint
|--------------------------------------------------------------------------
*/
'ingest_path' => env('PORTFLOW_INGEST_PATH', '/portflow/ingest'),
/*
|--------------------------------------------------------------------------
| Ingest Middleware
|--------------------------------------------------------------------------
| Do NOT add TrimStrings or ConvertEmptyStringsToNull — they corrupt
| binary delimiters (\n, \r\n) in serial chunk data.
*/
'ingest_middleware' => ['web'],
/*
|--------------------------------------------------------------------------
| Security
|--------------------------------------------------------------------------
*/
'max_chunk_bytes' => env('PORTFLOW_MAX_CHUNK_BYTES', 16384),
'ingest_rate_limit' => env('PORTFLOW_RATE_LIMIT', 60),
/*
|--------------------------------------------------------------------------
| Queue Routing
|--------------------------------------------------------------------------
| Set to true to dispatch SerialFrames via the queue instead of
| processing them synchronously inside the HTTP request cycle.
*/
'queue_routing' => env('PORTFLOW_QUEUE_ROUTING', false),
/*
|--------------------------------------------------------------------------
| Drivers
|--------------------------------------------------------------------------
*/
'drivers' => [
'raw-json' => \Hamzi\PortFlow\Infrastructure\Drivers\RawJsonDriver::class,
'escpos' => \Hamzi\PortFlow\Infrastructure\Drivers\EscPosDriver::class,
'rs232' => \Hamzi\PortFlow\Infrastructure\Drivers\Rs232Driver::class,
],
/*
|--------------------------------------------------------------------------
| Driver Options
|--------------------------------------------------------------------------
*/
'driver_options' => [
'raw-json' => [
'delimiter' => "\n",
'max_bytes' => 16384,
],
'rs232' => [
'delimiter' => "\n",
],
'escpos' => [],
],
/*
|--------------------------------------------------------------------------
| Mappings
|--------------------------------------------------------------------------
| Automatically route frames to Events or Eloquent models.
| Supported keys per mapping:
| driver — match only frames from this driver (optional)
| payload_field — payload key to match on (optional)
| equals — expected value of payload_field (optional)
| event — fully-qualified event class to dispatch
| event_payload_field — payload key passed as first constructor arg
| model — Eloquent model class to create
| field_map — [ 'column' => 'payload_key' ]
*/
'mappings' => [
[
'driver' => 'raw-json',
'payload_field' => 'type',
'equals' => 'barcode.scan',
'event' => \Hamzi\PortFlow\Domain\Events\ProductScanned::class,
'event_payload_field' => 'barcode',
],
[
'driver' => 'escpos',
'event' => \Hamzi\PortFlow\Domain\Events\ProductScanned::class,
'event_payload_field' => 'barcode',
],
],
];
[
'barcode' => '4006381333931',
'raw' => '4006381333931\r',
'length' => 13,
]
'default_driver' => 'barcode-line',
'driver_options' => [
'barcode-line' => [
'delimiter' => "\n",
'strip_prefix' => [],
'strip_suffix' => ["\r", "\n", "\t"],
],
],
[
'tag' => '7A005B0FF8D6',
'raw' => '7A005B0FF8D6\r\n',
'raw_hex' => '023741303035423046463844360D0A03',
'format' => 'stx-etx-ascii',
]
'driver_options' => [
'rfid-ascii' => [
'stx' => "\x02",
'etx' => "\x03",
'uppercase' => true,
],
],
[
'packet_type' => 7,
'packet_type_name' => 'ack',
'address_hex' => 'FFFFFFFF',
'data_hex' => '00',
'checksum' => 11,
'checksum_calculated' => 11,
'checksum_valid' => true,
'raw_hex' => 'EF01FFFFFFFF07000300000B',
]
'driver_options' => [
'fingerprint-packet' => [
'start_code_hex' => 'EF01',
],
],
bash
php artisan vendor:publish --tag=portflow-config
bash
php artisan vendor:publish --tag=portflow-assets
bash
php artisan vendor:publish --tag=portflow-stubs
bash
php artisan portflow:make-driver MyScale
# creates app/SerialDrivers/MyScaleDriver.php
php artisan portflow:make-driver Modbus --namespace="App\\Hardware\\Drivers"
# creates app/Hardware/Drivers/ModbusDriver.php
bash
php artisan portflow:listen /dev/ttyUSB0 --driver=barcode-line --baud=115200
bash
php artisan portflow:listen COM3 --driver=barcode-line --baud=115200
bash
php artisan queue:work
bash
composer analyse