Add component-level documentation for all 14 server subsystems
Provides technical documentation covering OPC UA server, address space, Galaxy repository, MXAccess bridge, data types, read/write, subscriptions, alarms, historian, incremental sync, configuration, dashboard, service hosting, and CLI tool. Updates README with component documentation table. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
182
docs/CliTool.md
Normal file
182
docs/CliTool.md
Normal file
@@ -0,0 +1,182 @@
|
||||
# CLI Tool
|
||||
|
||||
## Overview
|
||||
|
||||
The OPC UA CLI tool at `tools/opcuacli-dotnet/` is a command-line utility for testing OPC UA server functions. It targets .NET 10 and uses the OPC Foundation UA .NET Standard client library for OPC UA operations and [CliFx](https://github.com/Tyrrrz/CliFx) for command routing and argument parsing.
|
||||
|
||||
The tool is not part of the production service. It exists to verify that the LmxOpcUa server correctly exposes browse nodes, reads, writes, subscriptions, historical data, and alarm events without requiring a full OPC UA client application.
|
||||
|
||||
## Build and Run
|
||||
|
||||
```bash
|
||||
cd tools/opcuacli-dotnet
|
||||
dotnet build
|
||||
dotnet run -- <command> [options]
|
||||
```
|
||||
|
||||
## Shared Session Creation
|
||||
|
||||
`OpcUaHelper.ConnectAsync()` creates an OPC UA client session used by all commands. It configures the application identity, sets up directory-based certificate stores under `%LocalAppData%\OpcUaCli\pki\`, and auto-accepts untrusted server certificates. The session timeout is 60 seconds.
|
||||
|
||||
`OpcUaHelper.ConvertValue()` converts a raw string from the command line into the runtime type expected by the target node. It uses the current node value to infer the type (bool, byte, short, int, float, double, etc.) and falls back to string if the type is not recognized.
|
||||
|
||||
## Commands
|
||||
|
||||
### connect
|
||||
|
||||
Tests connectivity to an OPC UA server endpoint. Creates a session and immediately disconnects.
|
||||
|
||||
```bash
|
||||
dotnet run -- connect -u opc.tcp://localhost:4840
|
||||
```
|
||||
|
||||
### browse
|
||||
|
||||
Browses the OPC UA address space starting from the Objects folder or a specified node. Supports recursive traversal with a configurable depth limit.
|
||||
|
||||
```bash
|
||||
# Browse top-level Objects folder
|
||||
dotnet run -- browse -u opc.tcp://localhost:4840
|
||||
|
||||
# Browse a specific node
|
||||
dotnet run -- browse -u opc.tcp://localhost:4840 -n "ns=2;s=MyFolder"
|
||||
|
||||
# Browse recursively to depth 3
|
||||
dotnet run -- browse -u opc.tcp://localhost:4840 -r -d 3
|
||||
```
|
||||
|
||||
| Flag | Description |
|
||||
|------|-------------|
|
||||
| `-u` | OPC UA server endpoint URL (required) |
|
||||
| `-n` | Node ID to browse (default: Objects folder) |
|
||||
| `-d` | Maximum browse depth (default: 1) |
|
||||
| `-r` | Browse recursively using `-d` as max depth |
|
||||
|
||||
### read
|
||||
|
||||
Reads the current value of a single node and prints the value, data type, status code, and timestamps.
|
||||
|
||||
```bash
|
||||
dotnet run -- read -u opc.tcp://localhost:4840 -n "ns=2;s=TestMachine_001.SomeAttribute"
|
||||
```
|
||||
|
||||
| Flag | Description |
|
||||
|------|-------------|
|
||||
| `-u` | OPC UA server endpoint URL (required) |
|
||||
| `-n` | Node ID to read (required) |
|
||||
|
||||
### write
|
||||
|
||||
Writes a value to a node. The command reads the current value first to determine the target data type, then converts the supplied string value to that type using `OpcUaHelper.ConvertValue()`.
|
||||
|
||||
```bash
|
||||
dotnet run -- write -u opc.tcp://localhost:4840 -n "ns=2;s=MyNode" -v 42
|
||||
```
|
||||
|
||||
| Flag | Description |
|
||||
|------|-------------|
|
||||
| `-u` | OPC UA server endpoint URL (required) |
|
||||
| `-n` | Node ID to write to (required) |
|
||||
| `-v` | Value to write (required) |
|
||||
|
||||
### subscribe
|
||||
|
||||
Monitors a node for value changes using OPC UA subscriptions. Creates a `MonitoredItem` with the specified sampling interval and prints each notification with its source timestamp, value, and status code. Prints periodic tick lines showing session state, subscription ID, publishing status, and last notification value. Runs until Ctrl+C.
|
||||
|
||||
```bash
|
||||
dotnet run -- subscribe -u opc.tcp://localhost:4840 -n "ns=2;s=MyNode" -i 500
|
||||
```
|
||||
|
||||
| Flag | Description |
|
||||
|------|-------------|
|
||||
| `-u` | OPC UA server endpoint URL (required) |
|
||||
| `-n` | Node ID to monitor (required) |
|
||||
| `-i` | Sampling/publishing interval in milliseconds (default: 1000) |
|
||||
|
||||
### historyread
|
||||
|
||||
Reads historical data from a node. Supports both raw history reads and aggregate (processed) history reads.
|
||||
|
||||
```bash
|
||||
# Raw history
|
||||
dotnet run -- 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
|
||||
dotnet run -- 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 |
|
||||
|------|-------------|
|
||||
| `-u` | OPC UA server endpoint URL (required) |
|
||||
| `-n` | 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) |
|
||||
|
||||
#### Continuation points
|
||||
|
||||
When reading raw history, the server may return more values than fit in a single response. The command handles this by checking the `ContinuationPoint` on each result. If a continuation point is present, it issues follow-up `HistoryRead` calls with `ReleaseContinuationPoints = false` (i.e., `continuationPoint != null` is passed to the next read) until either the continuation point is empty or the `--max` limit is reached. This ensures that large result sets are fetched in full without requiring the caller to manage pagination.
|
||||
|
||||
#### Aggregate mapping
|
||||
|
||||
The `--aggregate` option maps human-readable names to OPC UA aggregate function node IDs:
|
||||
|
||||
| Name | OPC UA Node ID |
|
||||
|------|---------------|
|
||||
| `average` | `AggregateFunction_Average` |
|
||||
| `minimum` / `min` | `AggregateFunction_Minimum` |
|
||||
| `maximum` / `max` | `AggregateFunction_Maximum` |
|
||||
| `count` | `AggregateFunction_Count` |
|
||||
| `start` / `first` | `AggregateFunction_Start` |
|
||||
| `end` / `last` | `AggregateFunction_End` |
|
||||
|
||||
### alarms
|
||||
|
||||
Subscribes to alarm events on a node using OPC UA event subscriptions. Creates a `MonitoredItem` with `AttributeId = EventNotifier` and an `EventFilter` that selects alarm-relevant fields from the event stream. Runs until Ctrl+C.
|
||||
|
||||
```bash
|
||||
# Subscribe to alarm events
|
||||
dotnet run -- alarms -u opc.tcp://localhost:4840/LmxOpcUa \
|
||||
-n "ns=1;s=TestMachine_001"
|
||||
|
||||
# With condition refresh to get current alarm states
|
||||
dotnet run -- alarms -u opc.tcp://localhost:4840/LmxOpcUa \
|
||||
-n "ns=1;s=TestMachine_001" --refresh
|
||||
```
|
||||
|
||||
| Flag | Description |
|
||||
|------|-------------|
|
||||
| `-u` | OPC UA server endpoint URL (required) |
|
||||
| `-n` | Node ID to monitor for events (default: Server node) |
|
||||
| `-i` | Publishing interval in milliseconds (default: 1000) |
|
||||
| `--refresh` | Request a `ConditionRefresh` after subscribing to get current retained alarm states |
|
||||
|
||||
#### EventFilter and alarm display
|
||||
|
||||
The command builds an `EventFilter` with select clauses for 12 fields from the OPC UA alarm type hierarchy:
|
||||
|
||||
| Index | Type | Field |
|
||||
|-------|------|-------|
|
||||
| 0 | `BaseEventType` | `EventId` |
|
||||
| 1 | `BaseEventType` | `EventType` |
|
||||
| 2 | `BaseEventType` | `SourceName` |
|
||||
| 3 | `BaseEventType` | `Time` |
|
||||
| 4 | `BaseEventType` | `Message` |
|
||||
| 5 | `BaseEventType` | `Severity` |
|
||||
| 6 | `ConditionType` | `ConditionName` |
|
||||
| 7 | `ConditionType` | `Retain` |
|
||||
| 8 | `AcknowledgeableConditionType` | `AckedState/Id` |
|
||||
| 9 | `AlarmConditionType` | `ActiveState/Id` |
|
||||
| 10 | `AlarmConditionType` | `EnabledState/Id` |
|
||||
| 11 | `AlarmConditionType` | `SuppressedOrShelved` |
|
||||
|
||||
When an `EventFieldList` notification arrives, the handler extracts these fields by index and prints a structured alarm event to the console showing the source name, condition name, active/acknowledged state, severity, message, retain flag, and suppressed/shelved status.
|
||||
|
||||
The `--refresh` flag calls `subscription.ConditionRefreshAsync()` after the subscription is created, which asks the server to re-emit retained condition events so the operator sees the current alarm state immediately rather than waiting for the next transition.
|
||||
Reference in New Issue
Block a user