# Client CLI

## Overview

`ZB.MOM.WW.OtOpcUa.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.OtOpcUa.Client.CLI
dotnet build
dotnet run -- <command> [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
```

## Testing

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

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