Skip to content

Latest commit

 

History

History
254 lines (202 loc) · 11.7 KB

File metadata and controls

254 lines (202 loc) · 11.7 KB
eyebrow Docs · Getting started
lede Three layers of a Laravel-OPCUA application: the facade you call, the manager Laravel binds, and the optional daemon that holds OPC UA sessions across requests. Internalise this once.
see_also
href meta
../using-the-client/facade-vs-injection.md
5 min
href meta
../session-manager/overview.md
5 min
prev
label href
Quick start
./quick-start.md
next
label href
Upgrading
./upgrading.md

How laravel-opcua fits

Three concepts you need clear in your head before going deeper. This page is the orientation map.

1 — Three runtime layers

┌─────────────────────────────────────────────────────────────────────┐
│ Your Laravel application                                             │
│   - HTTP controllers                                                  │
│   - Console commands                                                  │
│   - Queue workers                                                     │
│   - Livewire components                                               │
│   - Listeners                                                         │
│                                                                       │
│   Opcua::read(...)   ←── facade                                       │
│   OpcuaManager::read(...)  ←── injected manager                       │
└─────────────────────────────────────────────────────────────────────┘
                                  │
                                  ▼
┌─────────────────────────────────────────────────────────────────────┐
│ OpcuaManager (container singleton)                                   │
│   - Resolves configuration                                            │
│   - Picks direct vs managed mode                                      │
│   - Wires logger / cache / event dispatcher from the container        │
│   - Caches connection instances per name                              │
└─────────────────────────────────────────────────────────────────────┘
                       │                              │
                       ▼ (direct mode)                ▼ (managed mode)
┌─────────────────────────────┐     ┌──────────────────────────────────┐
│ opcua-client                 │     │ ManagedClient ──IPC──→ daemon    │
│   ClientBuilder→Client       │     │   (opcua-session-manager)         │
│   Opens a session per use     │     │   Persistent sessions             │
└─────────────────────────────┘     └──────────────────────────────────┘
                       │                              │
                       └──────────────┬───────────────┘
                                       ▼
                           ┌─────────────────────┐
                           │ OPC UA server       │
                           │ (PLC, SCADA, …)     │
                           └─────────────────────┘

Three things to internalise:

  • Application code is always the same shape. Whether the underlying mode is direct or managed, the facade / manager API is identical. You write Opcua::read('ns=2;s=...') either way.
  • OpcuaManager is the integration layer. It owns configuration parsing, mode selection, lazy connection creation. Everything Laravel-specific lives in or around it.
  • The daemon is optional. Without it, every operation opens a fresh OPC UA session. With it, sessions live across HTTP requests — the whole point of using Laravel rather than a CLI tool.

2 — The two modes, in detail

Direct mode

When the daemon is not running (or OPCUA_SESSION_MANAGER_ENABLED=false), OpcuaManager creates a fresh Client per connection name on first use.

HTTP request 1
  Opcua::read('ns=2;s=...')
    → OpcuaManager::connection('default') (cached in Laravel container singleton)
    → If no Client cached: ClientBuilder::create()->setX()->...->connect()
    → Client::read(...)
    → Response
  (end of request — singleton state survives for next request only if process is long-lived)

HTTP request 2 (in PHP-FPM — fresh process)
  Same flow — Client was destroyed when the request worker recycled

PHP-FPM workers recycle the singleton between requests. The "caching in container" doesn't help across requests; it only helps within a single request that issues multiple OPC UA calls.

Cost: ~1 second OPC UA handshake per request worker. If your controller does several OPC UA operations in one request, they share the same session — no per-call handshake.

Managed mode

When the daemon is running, OpcuaManager creates a ManagedClient that speaks IPC with the daemon. The daemon holds the OPC UA session.

opcua:session daemon runs in the background, holding 0..N OPC UA sessions

HTTP request 1
  Opcua::read('ns=2;s=...')
    → OpcuaManager::connection('default')
    → ManagedClient::connect('opc.tcp://...')
      → IPC frame: {"command":"open","endpointUrl":"opc.tcp://...","config":{...},"authToken":"..."}
      → Daemon checks the session-reuse cache (key derived from
        endpoint + identity-related config keys) → returns sessionId
    → ManagedClient::read(...)
      → IPC frame: {"command":"query","sessionId":"...","method":"read","params":[...],"authToken":"..."}
      → Daemon reads from its existing OPC UA session
      → Response: {"success":true,"data":<DataValue payload>}
  (end of request — daemon-side OPC UA session lives on, unless the
   request explicitly called Opcua::disconnect(), which also sends
   {"command":"close"} and releases the session)

HTTP request 2
  Same flow — the daemon's session is reused; sub-millisecond connect

Cost: ~1ms IPC round-trip per call. The OPC UA handshake happens once on the daemon side, then never again until the daemon restarts.

For request-driven workloads, this is the difference between an unusable 1-second OPC UA latency per request and a snappy ~3-5ms total.

Auto-detection

OpcuaManager::isSessionManagerRunning() does a file_exists($socketPath) check for Unix-domain endpoints; for TCP endpoints it always returns true. Mode selection happens on each call to connection() — the manager picks managed mode whenever the socket file exists (or, on TCP, whenever session_manager.enabled is true).

Forcing direct mode in production (e.g. for a CLI command that doesn't need the daemon):

OPCUA_SESSION_MANAGER_ENABLED=false php artisan plc:something

See Session manager · Monitoring the daemon.

3 — The Laravel idioms

Service container

OpcuaManager is bound as a singleton:

$this->app->singleton(OpcuaManager::class, fn($app) => new OpcuaManager(...));
$this->app->alias(OpcuaManager::class, 'opcua');

Both app(OpcuaManager::class) and app('opcua') return the same instance.

Facade

PhpOpcua\LaravelOpcua\Facades\Opcua resolves the singleton and proxies method calls through it. Every method on the facade is documented in the DocBlock — your IDE picks them all up.

Configuration

config/opcua.php — a single config file. The package merges its built-in defaults so you can override only what you need.

Logging

OPC UA log lines route through config/logging.php channels specified by log_channel in config/opcua.php. Use any Laravel log channel (single, stack, syslog, papertrail, slack, …).

Cache

OPC UA browse / resolve / endpoint caching routes through config/cache.php stores specified by cache_store. Any Laravel cache backend works (file, redis, memcached, database, …).

Events

The 47-class PSR-14 event catalogue from opcua-client (see the event reference) flows through Laravel's event dispatcher — Illuminate\Events\Dispatcher implements the PSR-14 EventDispatcherInterface, so the events arrive at Event::listen(...) listeners natively. Queue listeners with ShouldQueue, broadcast with ShouldBroadcast. See Events · Overview.

Artisan

php artisan opcua:session starts the daemon. Configurable via flags and config. See Reference · Artisan commands.

What the package does not do

  • Does not embed the OPC UA stack. It depends on opcua-client, which is the actual implementation.
  • Does not depend on the session manager at runtime. The daemon dependency is bundled, but the package works without the daemon — just without persistent sessions.
  • Does not bind every OPC UA value to Eloquent. Persisting reads is your application's concern; see Recipes · Persistent tag history for the canonical pattern.
  • Does not provide a UI. Build your own (Blade, Livewire, Inertia, Filament); see Integrations and Recipes.

Where the OPC UA depth lives

This package wraps opcua-client and opcua-session-manager — the OPC UA-level documentation lives in those libraries:

This documentation focuses on the Laravel-specific surface: how to use it from a controller, a job, a Livewire component, a Pest test. For OPC UA primitives (what's a NodeId? what's a security policy?), the upstream docs are the source of truth.

Where to go next