OPC UA in PHP - without learning OPC UA
A while back I shared a pure-PHP OPC UA ecosystem that lets a web app talk to factory-floor PLCs, CNC machines, SCADA systems and IoT sensors without C++ SDKs, gateways, or sidecar proxies. Just Composer and ext-openssl.
It just reached v4.4.0 - the biggest release so far. There's a lot of new protocol surface (aggregates, history writes, file transfer, three new transports - I'll cover them). But here's the thing I actually want to tell you about:
You no longer need to learn any of it.
Every package now ships an AI Skill. Point your coding assistant at one repo, describe what you want in plain English, and it writes correct OPC UA code - the right APIs, the right security model, the right patterns - without you knowing how OPC UA works or how the ecosystem is laid out.
Let me start there, then show what's under the hood for when you're curious.
The point: you don't have to be an OPC UA expert
OPC UA is deep. The spec runs to a dozen multi-hundred-page Parts. There are NodeIds, secure channels, sessions, subscriptions, monitored items, companion specifications, three transport mappings, a publish/subscribe model with pre-shared group keys... Learning enough to write correct code used to be a real investment.
And LLMs don't help much on their own here: ask a generic assistant to "read a tag from my PLC over OPC UA in PHP" and it will happily hallucinate method names, miss the security model, and reinvent patterns that don't exist. It has never seen these libraries.
That's exactly what an Agent Skill fixes. A skill is a SKILL.md file - frontmatter that tells the model when it's relevant, plus a body and references/ that tell it how to use the package correctly: the API surface, the idioms, the security model, the testing approach, the common pitfalls.
Every package in the ecosystem now ships one under .ai/skills/<package>/, and they're all mirrored into a single auto-synced repo: php-opcua/ai-skills.
So your assistant can learn the whole ecosystem from one place - and you can stay at the level of "what do I want to happen."
From plain English to correct code
With the skills installed, this is the actual workflow. You write:
"Connect to
opc.https://plant.local:443/UA/through our corporate proxy and read the boiler temperature tag."
...and your assistant produces working code that uses the right transport, knows TLS is the secure channel (so OPC UA security stays None), and routes the proxy through the HTTP client - none of which you had to know:
$transport = new HttpsTransport(
httpClient: new CurlHttpClient(
verifyTls: true,
extraCurlOptions: [CURLOPT_PROXY => 'http://proxy.corp:3128'],
),
encoding: new BinaryHttpsEncoding(),
endpointUrl: 'opc.https://plant.local:443/UA/',
);
$client = (new ClientBuilder())
->setSecurityPolicy(SecurityPolicy::None) // TLS is the secure channel
->setSecurityMode(SecurityMode::None)
->setTransport($transport)
->connect('opc.https://plant.local:443/UA/');
echo $client->read('ns=2;s=Boiler/Temperature')->getValue();
Or "subscribe to the PubSub multicast group 239.0.0.1 and print every field", or "accept a reverse connection from our edge gateway and browse it" - same deal. You describe the outcome; the skill supplies the how.
Install it in one command
If you're on Laravel, Boost v2 pulls skills straight from a GitHub repo and syncs them across every AI agent it manages:
php artisan boost:add-skill php-opcua/ai-skills --list # see what's available
php artisan boost:add-skill php-opcua/ai-skills --skill opcua-client
php artisan boost:add-skill php-opcua/ai-skills --all # or grab everything
Using Claude Code? These are Anthropic Agent Skills - nothing to convert:
git clone https://github.com/php-opcua/ai-skills.git
cp -r ai-skills/skills/opcua-client ~/.claude/skills/ # personal, every project
# or .claude/skills/ to commit it with your repo
Claude Code auto-activates a skill when your task matches its description. Cursor, Windsurf, Copilot work too - drop the SKILL.md into their rules/instructions folder.
Take only the skills for the packages you use - each is self-contained. That's the whole onboarding.
...and if you are curious, here's what's new in 4.4.0
You don't need this section to be productive. But if you like knowing what your AI is driving, here's the release.
The ecosystem, briefly
| Package | Role |
|---|---|
opcua-client |
The core - pure-PHP client: read, write, browse, call, subscribe, history |
opcua-cli |
Terminal companion - browse/read/write/watch, all with --json
|
opcua-client-nodeset |
Pre-generated PHP types for OPC Foundation companion specs |
opcua-session-manager |
Keep sessions alive across requests via a ReactPHP daemon |
laravel-opcua / symfony-opcua
|
Framework integrations |
Core: aggregates, history writes, file transfer
-
AggregateModulecomputesInterpolate/Minimum/Maximum/Average/Countfrom a rawDataValuebuffer - pair it withhistoryAggregate()to fetch + bucket in one call. - HistoryUpdate - nine new methods for Insert / Replace / Update / Remove of historical data and events. History is no longer read-only.
-
FileTransferModulewraps the OPC UA File Transfer service set (Part 5) into typedopenFile/readFile/writeFile/closeFilecalls, with chunked reads for large files. - A pluggable transport layer (
ClientTransportInterface+ClientBuilder::setTransport()) - the quiet headline that made the three extensions below possible. Plus a smallDataValue::getType()accessor so you can read a value's type without the deprecatedgetVariant()hop.
Three new transports
OPC UA isn't only opc.tcp://. v4.4.0 brings three more mappings as opt-in extensions:
-
opcua-client-ext-reverse-connect(Part 6 7.1.2.3) - the server dials you. For edge gateways and PLCs behind NAT/firewall that can't accept inbound connections but can dial out. Your app listens, validates the announcedServerUriagainst a fail-secure whitelist, then proceeds with the normal handshake. -
opcua-client-ext-transport-https(Part 6 7.4) -opc.https://: one HTTPS POST per UA message, TLS as the secure channel. For getting through proxies and firewalls that blockopc.tcp://. Binary encoding is production-ready; JSON ships as a reference. -
opcua-client-ext-transport-pubsub(Part 14) - a PubSub subscriber: UADP and JSON over UDP (unicast or multicast), pre-shared group-key security, optional Security Key Service. A different runtime model, ideal for high-rate telemetry.
composer require php-opcua/opcua-client
# add only the transports you need:
composer require php-opcua/opcua-client-ext-reverse-connect
composer require php-opcua/opcua-client-ext-transport-https
composer require php-opcua/opcua-client-ext-transport-pubsub
Try it
- Code & docs: https://github.com/php-opcua
- AI Skills (start here): https://github.com/php-opcua/ai-skills
- Docs site: https://www.php-opcua.com
Everything is pure PHP, MIT-licensed, and tested against the OPC Foundation's UA-.NETStandard reference server.
The best part? You can install the skills, describe what you need, and ship a working industrial integration this afternoon - without reading a single page of the OPC UA spec. If you build something with it (or your AI does), I'd love to hear about it.
Industry 4.0, meet composer require.
Top comments (0)