# Client CLI ## Overview `ZB.MOM.WW.LmxOpcUa.Client.CLI` is a cross-platform command-line client for the LmxOpcUa 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](https://github.com/Tyrrrz/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. ## Build and Run ```bash cd src/ZB.MOM.WW.LmxOpcUa.Client.CLI dotnet build dotnet run -- [options] ``` The executable name is `lmxopcua-cli`. ## 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. ```bash 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. ```bash lmxopcua-cli connect -u opc.tcp://localhost:4840/LmxOpcUa -F opc.tcp://localhost:4841/LmxOpcUa ``` ### 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 ```bash lmxopcua-cli browse -u opc.tcp://localhost:4840/LmxOpcUa -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. ```bash lmxopcua-cli connect -u opc.tcp://localhost:4840/LmxOpcUa -U admin -P admin123 ``` Output: ```text Connected to: opc.tcp://localhost:4840/LmxOpcUa Server: LmxOpcUa 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. ```bash lmxopcua-cli read -u opc.tcp://localhost:4840/LmxOpcUa -n "ns=3;s=DEV.ScanState" -U admin -P admin123 ``` | Flag | Description | |------|-------------| | `-n` / `--node` | Node ID to read (required) | Output: ```text 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()`. ```bash 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. ```bash # Browse top-level Objects folder lmxopcua-cli browse -u opc.tcp://localhost:4840/LmxOpcUa -U admin -P admin123 # Browse a specific node recursively to depth 3 lmxopcua-cli browse -u opc.tcp://localhost:4840/LmxOpcUa -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. ```bash 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. ```bash # Raw history lmxopcua-cli historyread -u opc.tcp://localhost:4840/LmxOpcUa \ -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/LmxOpcUa \ -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. ```bash # Subscribe to alarm events on the Server node lmxopcua-cli alarms -u opc.tcp://localhost:4840/LmxOpcUa # Subscribe to a specific source node with condition refresh lmxopcua-cli alarms -u opc.tcp://localhost:4840/LmxOpcUa \ -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. ```bash lmxopcua-cli redundancy -u opc.tcp://localhost:4840/LmxOpcUa -U admin -P admin123 ``` Example output: ```text Redundancy Mode: Warm Service Level: 200 Server URIs: - urn:localhost:LmxOpcUa:instance1 - urn:localhost:LmxOpcUa:instance2 Application URI: urn:localhost:LmxOpcUa:instance1 ``` ## Differences from tools/opcuacli-dotnet The `Client.CLI` replaces the standalone tool at `tools/opcuacli-dotnet/`. Key differences: | Aspect | tools/opcuacli-dotnet | Client.CLI | |--------|----------------------|------------| | OPC UA access | Direct `Session` API | `IOpcUaClientService` abstraction | | Connection/failover | Per-command `OpcUaFailoverHelper` | Shared service with built-in failover and keep-alive | | Certificate management | Inline in `OpcUaHelper` | Shared `ApplicationConfigurationFactory` | | Type conversion | `OpcUaHelper.ConvertValue` | `ValueConverter` in `Client.Shared` | | Executable name | `opcuacli-dotnet` | `lmxopcua-cli` | | Verbose logging | Not available | `--verbose` flag with Serilog | | Testability | No test seam | `IOpcUaClientServiceFactory` injection, 52 unit tests | The `tools/opcuacli-dotnet/` tool remains available for low-level debugging but is no longer the recommended client CLI.