Files
lmxopcua/docs/Client.CLI.md
Joseph Doherty f217636467 Doc refresh (task #206) — Client.CLI + Client.UI brand flip + new top-level docs/README.md index. Client.CLI.md: replaced stale LmxOpcUa-OPC UA-server references with OtOpcUa throughout the overview + sample output + applicationUri examples (opc.tcp://localhost:4840/OtOpcUa, urn:localhost:OtOpcUa:instanceN); confirmed against src/ZB.MOM.WW.OtOpcUa.Server/Program.cs:69-71 which sets the live endpoint url + application uri to those exact values. Added a driver-agnostic note in the overview — the CLI is reachable against every shipped driver surface because the OPC UA endpoint abstracts them all. Kept the lmxopcua-cli executable name + the {LocalAppData}/LmxOpcUaClient/pki/ PKI folder name AS-IS because those are real filesystem-level residuals the code still uses (Program.cs SetExecutableName + OpcUaClientService.cs:428) — flipping them requires migration shims so existing dev boxes don't lose their trusted-cert store; added explicit doc text explaining the residual + why it persists so future readers aren't confused. Fixed the sample connect-output "Server: LmxOpcUa" to "Server: OtOpcUa Server" matching the live ApplicationName in OpcUaServerOptions.cs:39. Client.UI.md: replaced the 4 LmxOpcUa references — overview one-liner, status-bar mock (now reads "OtOpcUa Server" matching the server's reported ApplicationName), endpoint-url example, settings persistence path. Same residual-explanation note added under the LmxOpcUaClient/settings.json path pointing at the Client.Shared session-factory literal at OpcUaClientService.cs:428. docs/README.md is new — a top-level index distinguishing the two documentation tiers (current reference at docs/*.md vs implementation history + design notes at docs/v2/*.md). Every current-reference doc gets a one-line role description in a section table (Architecture + data-path / Drivers / Operational / Client tooling / Requirements) so a new reader picking up the repo finds their way in without having to grep file names. Cross-link calls out that load-bearing references from top-level docs (plan.md decisions, admin-ui.md, acl-design.md, config-db-schema.md, driver-specs.md, dev-environment.md, test-data-sources.md) live under v2/. Notes up front that the project was renamed LmxOpcUa → OtOpcUa and that any remaining LmxOpcUa-string in paths is a deliberate residual with a migration follow-up, so readers don't chase phantom bugs. Four parallel doc-refresh agents currently working on the rest of docs/*.md (task #202 core architecture, #203 driver docs split, #204 operational, #205 requirements) — those commits will land on separate worktree branches + get folded in together once complete; this index already lists the docs they'll produce (drivers/README.md, drivers/Galaxy.md, drivers/Galaxy-Repository.md) so the final merge just has the content showing up where the index already points.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-20 01:25:18 -04:00

9.1 KiB

Client CLI

Overview

ZB.MOM.WW.OtOpcUa.Client.CLI is a cross-platform command-line client for the OtOpcUa OPC UA server. It targets .NET 10 and uses the shared IOpcUaClientService from Client.Shared for all OPC UA operations. Commands are routed and parsed by CliFx.

The CLI is the primary tool for operators and developers to test and interact with the server from a terminal. It supports all core operations: connectivity testing, browsing, reading, writing, subscriptions, alarm monitoring, history reads, and redundancy queries. Any driver surface exposed by the server (Galaxy, Modbus, S7, AB CIP, AB Legacy, TwinCAT, FOCAS, OPC UA Client) is reachable through these commands — the CLI is driver-agnostic because everything below the OPC UA endpoint is.

Build and Run

cd src/ZB.MOM.WW.OtOpcUa.Client.CLI
dotnet build
dotnet run -- <command> [options]

The executable name is still lmxopcua-cli — a residual from the pre-v2 rename (Program.cs:SetExecutableName). Scripts + operator muscle memory depend on the name; flipping it to otopcua-cli is a follow-up that also needs to move the client-side PKI store folder ({LocalAppData}/LmxOpcUaClient/pki/ — used by the shared client for its application certificate) so trust relationships survive the rename.

Architecture

All commands inherit from CommandBase, which provides common connection options and helper methods. Every command follows the same lifecycle:

  1. Build ConnectionSettings from common options
  2. Create an IOpcUaClientService through the factory
  3. Call ConnectAsync to establish a session
  4. Perform the command-specific operation
  5. Call DisconnectAsync in a finally block

No command accesses the OPC UA Session directly; all operations go through the shared service abstraction. This ensures consistent behavior with the desktop UI client.

Common Options

All commands accept these options:

Flag Description
-u / --url OPC UA server endpoint URL (required)
-U / --username Username for UserName token authentication
-P / --password Password for UserName token authentication
-S / --security Transport security mode: none, sign, encrypt, signandencrypt (default: none)
-F / --failover-urls Comma-separated failover endpoint URLs for redundancy
--verbose Enable debug-level Serilog console logging (default: warning)

Authentication

When -U and -P are provided, the shared service passes a UserIdentity(username, password) to the OPC UA session. Without credentials, anonymous identity is used.

lmxopcua-cli write -u opc.tcp://localhost:4840 -n "ns=2;s=MyNode" -v 42 -U operator -P op123

Failover

When -F is provided, the shared service tries the primary URL first, then each failover URL in order. For long-running commands (subscribe, alarms), the service monitors the session via keep-alive and automatically reconnects to the next available server on failure.

lmxopcua-cli connect -u opc.tcp://localhost:4840/OtOpcUa -F opc.tcp://localhost:4841/OtOpcUa

Transport Security

When sign or encrypt is specified, the shared service:

  1. Ensures a client application certificate exists under {LocalAppData}/LmxOpcUaClient/pki/ (auto-created if missing)
  2. Discovers server endpoints and selects one matching the requested security mode
  3. Prefers Basic256Sha256 when multiple matching endpoints exist
  4. Fails with a clear error if no matching endpoint is found
lmxopcua-cli browse -u opc.tcp://localhost:4840/OtOpcUa -S encrypt -U admin -P secret -r -d 2

Verbose Logging

The --verbose flag switches Serilog output from Warning to Debug level, showing internal connection lifecycle, endpoint discovery, and OPC UA SDK diagnostics on the console.

Commands

connect

Tests connectivity to an OPC UA server. Creates a session, prints connection metadata, and disconnects.

lmxopcua-cli connect -u opc.tcp://localhost:4840/OtOpcUa -U admin -P admin123

Output:

Connected to: opc.tcp://localhost:4840/OtOpcUa
Server: OtOpcUa Server
Security Mode: None
Security Policy: http://opcfoundation.org/UA/SecurityPolicy#None
Connection successful.

read

Reads the current value of a single node and prints the value, status code, and timestamps.

lmxopcua-cli read -u opc.tcp://localhost:4840/OtOpcUa -n "ns=3;s=DEV.ScanState" -U admin -P admin123
Flag Description
-n / --node Node ID to read (required)

Output:

Node:        ns=3;s=DEV.ScanState
Value:       True
Status:      0x00000000
Source Time: 2026-03-30T19:58:38.0961252Z
Server Time: 2026-03-30T19:58:38.0971257Z

write

Writes a value to a node. The shared service reads the current value first to determine the target data type, then converts the supplied string value using ValueConverter.ConvertValue().

lmxopcua-cli write -u opc.tcp://localhost:4840 -n "ns=2;s=MyNode" -v 42
Flag Description
-n / --node Node ID to write to (required)
-v / --value Value to write (required)

browse

Browses the OPC UA address space starting from the Objects folder or a specified node. Supports recursive traversal with a configurable depth limit. Output uses tree-style indentation with [Object], [Variable], and [Method] markers.

# Browse top-level Objects folder
lmxopcua-cli browse -u opc.tcp://localhost:4840/OtOpcUa -U admin -P admin123

# Browse a specific node recursively to depth 3
lmxopcua-cli browse -u opc.tcp://localhost:4840/OtOpcUa -U admin -P admin123 -r -d 3 -n "ns=3;s=ZB"
Flag Description
-n / --node Node ID to browse (default: Objects folder)
-d / --depth Maximum browse depth (default: 1)
-r / --recursive Browse recursively using -d as max depth

subscribe

Monitors a node for value changes using OPC UA subscriptions. Prints each data change notification with timestamp, value, and status code. Runs until Ctrl+C, then unsubscribes and disconnects cleanly.

lmxopcua-cli subscribe -u opc.tcp://localhost:4840 -n "ns=2;s=MyNode" -i 500
Flag Description
-n / --node Node ID to monitor (required)
-i / --interval Sampling/publishing interval in milliseconds (default: 1000)

historyread

Reads historical data from a node. Supports raw history reads and aggregate (processed) history reads.

# Raw history
lmxopcua-cli historyread -u opc.tcp://localhost:4840/OtOpcUa \
  -n "ns=1;s=TestMachine_001.TestHistoryValue" \
  --start "2026-03-25" --end "2026-03-30"

# Aggregate: 1-hour average
lmxopcua-cli historyread -u opc.tcp://localhost:4840/OtOpcUa \
  -n "ns=1;s=TestMachine_001.TestHistoryValue" \
  --start "2026-03-25" --end "2026-03-30" \
  --aggregate Average --interval 3600000
Flag Description
-n / --node Node ID to read history for (required)
--start Start time, ISO 8601 or date string (default: 24 hours ago)
--end End time, ISO 8601 or date string (default: now)
--max Maximum number of values (default: 1000)
--aggregate Aggregate function: Average, Minimum, Maximum, Count, Start, End
--interval Processing interval in milliseconds for aggregates (default: 3600000)

Aggregate mapping

Name OPC UA Node ID
Average AggregateFunction_Average
Minimum AggregateFunction_Minimum
Maximum AggregateFunction_Maximum
Count AggregateFunction_Count
Start AggregateFunction_Start
End AggregateFunction_End

alarms

Subscribes to alarm events on a node. Prints structured alarm output including source, condition, severity, active/acknowledged state, and message. Runs until Ctrl+C, then unsubscribes and disconnects cleanly.

# Subscribe to alarm events on the Server node
lmxopcua-cli alarms -u opc.tcp://localhost:4840/OtOpcUa

# Subscribe to a specific source node with condition refresh
lmxopcua-cli alarms -u opc.tcp://localhost:4840/OtOpcUa \
  -n "ns=1;s=TestMachine_001" --refresh
Flag Description
-n / --node Node ID to monitor for events (default: Server node)
-i / --interval Publishing interval in milliseconds (default: 1000)
--refresh Request a ConditionRefresh after subscribing to get current retained alarm states

redundancy

Reads the OPC UA redundancy state from a server: redundancy mode, service level, server URIs, and application URI.

lmxopcua-cli redundancy -u opc.tcp://localhost:4840/OtOpcUa -U admin -P admin123

Example output:

Redundancy Mode:  Warm
Service Level:    200
Server URIs:
  - urn:localhost:OtOpcUa:instance1
  - urn:localhost:OtOpcUa:instance2
Application URI:  urn:localhost:OtOpcUa:instance1

Testing

The Client CLI has 52 unit tests covering option parsing, service invocation, output formatting, and cleanup behavior:

dotnet test tests/ZB.MOM.WW.OtOpcUa.Client.CLI.Tests