OPC UA CLI PURE PHP TERMINAL
OPC UA CLI PURE PHP TERMINAL

CLI

Command-line tool for browsing OPC UA servers, reading/writing nodes, managing trust stores, and generating code.

$ composer require php-opcua/opcua-cli

CLI Tool

Overview

opcua-cli is a standalone command-line tool for exploring OPC UA servers without writing code. Useful for debugging on-site, verifying connectivity, and inspecting the address space.

Zero additional dependencies — uses the same pure PHP OPC UA client under the hood.

Installation

composer require php-opcua/opcua-cli

After installation, the CLI tool is available at:

opcua-cli

Commands

browse — Browse the address space

# Browse the Objects folder (default)
opcua-cli browse opc.tcp://localhost:4840

# Browse a specific path
opcua-cli browse opc.tcp://localhost:4840 /Objects/MyPLC

# Browse a specific NodeId
opcua-cli browse opc.tcp://localhost:4840 "ns=2;i=1000"

# Recursive browse with depth limit
opcua-cli browse opc.tcp://localhost:4840 /Objects --recursive --depth=3

# JSON output
opcua-cli browse opc.tcp://localhost:4840 /Objects --json

Output:

├── Server (i=2253) [Object]
├── MyPLC (ns=2;i=1000) [Object]
│   ├── Temperature (ns=2;i=1001) [Variable]
│   └── Pressure (ns=2;i=1002) [Variable]
└── DeviceSet (ns=3;i=5001) [Object]

Options:

Option Description
--recursive Browse recursively (tree view)
--depth=N Maximum depth for recursive browse (default: 3)

read — Read a node value

# Read the Value attribute (default)
opcua-cli read opc.tcp://localhost:4840 "i=2259"

# Read a specific attribute
opcua-cli read opc.tcp://localhost:4840 "ns=2;i=1001" --attribute=DisplayName

# JSON output
opcua-cli read opc.tcp://localhost:4840 "ns=2;i=1001" --json

Output:

NodeId:     ns=2;i=1001
Attribute:  Value
Value:      23.5
Type:       Double
Status:     Good (0x00000000)
Source:     2026-03-24T15:30:00+00:00
Server:     2026-03-24T15:30:00+00:00

Options:

Option Description
--attribute=NAME Attribute to read: Value (default), DisplayName, BrowseName, DataType, NodeClass, Description, AccessLevel, NodeId

write — Write a value to a node

# Auto-detect type (reads the node first)
opcua-cli write opc.tcp://localhost:4840 "ns=2;i=1001" 42

# Explicit type
opcua-cli write opc.tcp://localhost:4840 "ns=2;i=1001" 42 --type=Int32

# Write a boolean
opcua-cli write opc.tcp://localhost:4840 "ns=2;i=2000" true --type=Boolean

# JSON output
opcua-cli write opc.tcp://localhost:4840 "ns=2;i=1001" 42 --json

Output:

NodeId:  ns=2;i=1001
Value:   42
Type:    Int32
Status:  Good (0x00000000)

Options:

Option Description
--type=TYPE Explicit OPC UA type. If omitted, auto-detected from the node. Valid types: Boolean, SByte, Byte, Int16, UInt16, Int32, UInt32, Int64, UInt64, Float, Double, String

Value casting: When --type is specified, the value is cast accordingly ("true"bool, "42"int, "3.14"float). Without --type, the CLI infers from the string format.

endpoints — Discover server endpoints

opcua-cli endpoints opc.tcp://localhost:4840
opcua-cli endpoints opc.tcp://localhost:4840 --json

Output:

Endpoint: opc.tcp://localhost:4840
Security: None (mode: None)
Auth:     Anonymous, UserName

Endpoint: opc.tcp://localhost:4840
Security: Basic256Sha256 (mode: SignAndEncrypt)
Auth:     Anonymous, UserName, Certificate

watch — Watch a value in real time

Two modes:

  • Without --interval (default): uses OPC UA subscriptions. The server notifies only when the value changes — efficient, no unnecessary polling.
  • With --interval=N: manual polling with read() every N milliseconds. Useful for servers that don't support subscriptions or for debugging.
# Subscription mode (default)
opcua-cli watch opc.tcp://localhost:4840 "ns=2;i=1001"

# Polling mode — read every 250ms
opcua-cli watch opc.tcp://localhost:4840 "ns=2;i=1001" --interval=250

# JSON output
opcua-cli watch opc.tcp://localhost:4840 "ns=2;i=1001" --json

Output:

[15:30:00.123] 23.5
[15:30:00.625] 23.6
[15:30:01.127] 23.4
^C

Stop with Ctrl+C.

generate:nodeset — Generate PHP classes from NodeSet2.xml

# Generate with default output
opcua-cli generate:nodeset path/to/Opc.Ua.Di.NodeSet2.xml

# Specify output directory and namespace
opcua-cli generate:nodeset path/to/Opc.Ua.Di.NodeSet2.xml \
  --output=src/Generated/Di/ --namespace=App\\OpcUa\\Di

Output:

Generated: src/Generated/Di/DiNodeIds.php
Generated: src/Generated/Di/Codecs/DeviceTypeCodec.php
Generated: src/Generated/Di/DiRegistrar.php

Done. 3 file(s) generated in src/Generated/Di/

Generates three types of files:

  • NodeId constants — one class with all node IDs as string constants
  • Codec classes — one per structured DataType, implementing ExtensionObjectCodec
  • Registrar — a class with register(ExtensionObjectRepository) to batch-register all codecs

Options:

Option Description
--output=PATH Output directory (default: ./generated/)
--namespace=NS PHP namespace for generated classes (default: Generated\\OpcUa)

No server connection required — reads the XML file locally.

dump:nodeset — Export server address space to NodeSet2.xml

# Dump all non-zero namespaces
opcua-cli dump:nodeset opc.tcp://192.168.1.100:4840 --output=MyPLC.NodeSet2.xml

# Dump only namespace 2
opcua-cli dump:nodeset opc.tcp://192.168.1.100:4840 --output=MyPLC.NodeSet2.xml --namespace=2

# With security
opcua-cli dump:nodeset opc.tcp://192.168.1.100:4840 --output=MyPLC.NodeSet2.xml \
  -s Basic256Sha256 -m SignAndEncrypt --cert=client.pem --key=client.key

Output:

Namespace URIs:
  [0] http://opcfoundation.org/UA/
  [1] urn:myplc:opcua:server

Browsing address space...
Found 12 top-level nodes

Collecting nodes and reading attributes...
Collected 87 nodes

Building XML...
Written: MyPLC.NodeSet2.xml

Done. 87 nodes exported.

The exported file can be fed directly to generate:nodeset:

opcua-cli generate:nodeset MyPLC.NodeSet2.xml --output=src/Generated/MyPLC/

Options:

Option Description
--output=FILE Output XML file path (required)
--namespace=N Export only this namespace index (default: all non-zero)

WARNING: Always prefer the manufacturer's NodeSet2.xml file over a runtime dump.

The dump:nodeset command reconstructs the address space by browsing and reading attributes at runtime. This works well for NodeId constants and enumerations, but structured DataType definitions may be incomplete or missing depending on the server's OPC UA version and capabilities. Servers that do not support the DataTypeDefinition attribute (OPC UA < 1.04) will produce DataType nodes without <Definition> fields — meaning no DTOs or codecs can be generated for those types.

Use this command only when the device manufacturer does not provide a NodeSet2.xml file. If one is available (from the vendor documentation, the OPC Foundation repository, or the opcua-client-nodeset package), always use generate:nodeset directly on that file instead.

This command is not required and not mandatory for using the library. It is a convenience tool for situations where no other source of type information is available.

Security Options

All commands support full security configuration:

# Username/password authentication
opcua-cli read opc.tcp://server:4840 "i=2259" -u admin -p secret

# Full security with RSA certificates
opcua-cli read opc.tcp://server:4840 "i=2259" \
  --security-policy=Basic256Sha256 \
  --security-mode=SignAndEncrypt \
  --cert=/path/to/client.pem \
  --key=/path/to/client.key \
  --ca=/path/to/ca.pem \
  -u operator -p secret

# ECC security (auto-generated ECC certificate)
opcua-cli read opc.tcp://server:4840 "i=2259" \
  --security-policy=ECC_nistP256 \
  --security-mode=SignAndEncrypt \
  -u operator -p secret

ECC disclaimer: ECC security policies (ECC_nistP256, ECC_nistP384, ECC_brainpoolP256r1, ECC_brainpoolP384r1) are fully implemented and tested against the OPC Foundation's UA-.NETStandard reference stack. However, no commercial OPC UA vendor supports ECC endpoints yet. When using ECC, client certificates are auto-generated if --cert/--key are omitted, and username/password authentication uses the EccEncryptedSecret protocol automatically.

Option Short Description
--security-policy=<policy> -s None, Basic128Rsa15, Basic256, Basic256Sha256, Aes128Sha256RsaOaep, Aes256Sha256RsaPss, ECC_nistP256, ECC_nistP384, ECC_brainpoolP256r1, ECC_brainpoolP384r1
--security-mode=<mode> -m None, Sign, SignAndEncrypt
--cert=<path> Client certificate path
--key=<path> Client private key path
--ca=<path> CA certificate path
--username=<user> -u Username for authentication
--password=<pass> -p Password for authentication
--timeout=<seconds> -t Connection timeout (default: 5)

Output Options

JSON

Add --json (or -j) to any command for machine-readable output. Works with jq and shell scripts:

# Browse and extract node names
opcua-cli browse opc.tcp://localhost:4840 --json | jq '.[].name'

# Read a value
opcua-cli read opc.tcp://localhost:4840 "i=2259" --json | jq '.Value'

Debug Logging

Three debug modes:

# Log to stdout (incompatible with --json)
opcua-cli read opc.tcp://localhost:4840 "i=2259" --debug

# Log to stderr (compatible with --json)
opcua-cli read opc.tcp://localhost:4840 "i=2259" --debug-stderr --json

# Log to file (compatible with --json)
opcua-cli read opc.tcp://localhost:4840 "i=2259" --debug-file=/tmp/opcua.log --json

Debug output shows PSR-3 log messages: handshake, secure channel, session, retries, errors.

Global Options

Option Short Description
--json -j Output in JSON format
--debug -d Debug logging on stdout
--debug-stderr Debug logging on stderr
--debug-file=<path> Debug logging to file
--help -h Show help
--version -v Show version

Guides & Reference

Everything you need to get started and master CLI.