# ua-client **Repository Path**: gyb98/ua-client ## Basic Information - **Project Name**: ua-client - **Description**: No description available - **Primary Language**: Unknown - **License**: MIT - **Default Branch**: main - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-11-08 - **Last Updated**: 2026-11-08 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # ua-client A terminal OPC UA browser/inspector in Rust. Connect to a server, browse the address space, inspect node attributes and references, subscribe to values, write attributes and call methods. The binary is `ua-tui`, built on [`cursive`](https://crates.io/crates/cursive) and [`async-opcua`](https://crates.io/crates/async-opcua). ![ua-client](https://raw.githubusercontent.com/FreeOpcUa/ua-client/main/ua-client.png) ## Features - Endpoint URL bar with Connect/Disconnect, history dropdown of past successful connections (persisted across restarts). - Server endpoint picker (Connect → discovery dialog showing every advertised security policy / mode and supported identity tokens). The endpoint Connect will use is marked with `*`; Refresh and Connect stay disabled until discovery finishes. An unreachable server (no answer within 5 s) closes the picker and shows a popup instead. - Authentication: Anonymous, Username/Password, X.509 Certificate. Username and certificate/key paths are persisted per URL; passwords are not. - Per-URL persistence of the last-used auth mode, security mode and credentials so each saved server reopens with its own settings. - Address-space tree on the left with lazy-load expansion. Root is expanded automatically on connect; the last selected node per URL is restored on reconnect. Large folders are fetched completely via browse continuation points; a node whose children are still loading shows `⋯`. - Selected-node panels: all attributes one-per-line with aligned `Name : value` columns, plus a References panel (forward + inverse, all reference types, aligned columns). A failed read is shown in the pane itself with a hint to press `r`. - **Method calls**: press `c` on a Method node, the dialog reads `InputArguments`/`OutputArguments`, lets you fill scalar or comma-separated array inputs typed against the OPC UA data type, then renders the output values with their types. - **Data-change subscriptions**: press `s` on a node to get its live value in the Subscriptions pane; subscriptions are re-created automatically after a reconnect. - **Attribute writes**: press `e` on an attribute row to write built-in primitive types, `LocalizedText` and `QualifiedName`. - Bottom log panel fed by `tracing`. It follows new lines only while scrolled to the bottom, so scrolling up to read an error is not undone by the next line. - Settings (URL history, per-URL selection and connection prefs) are stored in `$XDG_CONFIG_HOME/ua-client/tui-state.json`. ## Build & run ```bash cargo run ``` Set `RUST_LOG` to control verbosity; the default is `info,opcua=info,ua_client=debug`. To exercise it end-to-end, start the `simple-server` sample from `async-opcua` in another terminal and connect to `opc.tcp://localhost:4855`: ```bash git clone https://github.com/freeopcua/async-opcua cd async-opcua && cargo run -p async-opcua-simple-server ``` ### `ua-tui` command-line flags ``` ua-tui [--url ] [--path ] ``` - `--url opc.tcp://host:port` — pre-fill the URL field; press Connect to connect. - `--path /Objects/Server/ServerStatus` — after connecting, navigate to this path instead of the URL's saved last-selected node. Segments may use `ns=N:Name` for non-default namespaces; reserved characters in browse names are `&`-escaped, exactly as the `p` key copies them. ### `ua-tui` keyboard reference Single-letter hotkeys act on the main screen only; while a dialog is open they are ignored, except `q` / `Ctrl+C`. `?` shows the same reference inside the app. Navigation: | Key | Action | |---|---| | `Tab` / `Shift+Tab` | Move focus between widgets | | Arrows / `j` / `k` | Move within the focused widget | | `Enter` | Select node (and expand/collapse if it has children). In the References or Subscriptions pane, jumps to that node | | `Esc` | Clear current selection (on the main screen) / close the dialog (inside one) | | `r` | Refresh selected node | | `q` / `Ctrl+C` | Quit (disconnects cleanly first; press again to force) | | `?` | In-app help | Copy to clipboard (acts on the selected node): | Key | Copies | |---|---| | `p` | Browse path (`/Objects/Server`) | | `n` | NodeId (`ns=1;i=1234`) | | `v` | Value attribute | If no system clipboard is available, the text is written to the log instead. Method: | Key | Action | |---|---| | `c` | Call selected Method (opens input dialog) | Subscriptions (acts on the selected tree node): | Key | Action | |---|---| | `s` | Subscribe — live value appears in the Subscriptions pane | | `Shift+s` | Unsubscribe | Attribute editing (acts on the row under the Attributes pane cursor): | Key | Action | |---|---| | `e` | Open the edit dialog. Writable: `Value`, `DisplayName`, `Description`, `BrowseName`, `Historizing`, `Executable`, `UserExecutable`, `IsAbstract`, `Symmetric`, `ContainsNoLoops`, `WriteMask`, `UserWriteMask`, `AccessLevelEx`, `AccessLevel`, `UserAccessLevel`, `EventNotifier`, `MinimumSamplingInterval`, `ValueRank`. | Resize (focus-dependent — moves the boundary of the focused pane): | Key | Effect | |---|---| | `Alt+Left` / `Alt+Right` | Tree pane width | | `Alt+Up` / `Alt+Down` | Attributes/References split (when attrs or refs is focused) | | `Alt+Up` / `Alt+Down` | Log height (when log is focused) | ## Encrypted connections For any security policy other than `None`, the first connection attempt typically fails with `BadSecurityChecksFailed` / `BadCertificateUntrusted`. This is expected: the server has no reason to trust the freshly generated client certificate yet. 1. Run the client once. A self-signed client keypair is created at `pki/own/cert.der` + `pki/private/private.pem` next to the working directory. 2. Try Connect with the desired encrypted endpoint. It will fail. 3. Find your client cert in the server's "rejected certificates" folder (server-specific path — e.g. for Prosys UA Simulation Server it's `/USERS_PKI/rejected/certs/`) and move it into the corresponding "trusted certs" folder. 4. Connect again — it should succeed. The log panel prints the cert path on every encrypted connection attempt and a hint when the server rejects it. > **Insecure default:** server-certificate checks (time validity, hostname, application-URI) are **disabled** by default so that real-world certificates (Beckhoff TwinCAT, NAT'd deployments, etc.) connect on first try. A warning is logged on startup. Acceptable on trusted networks only. ## Status Working: browse, read attributes / references, Anonymous / Username / X.509 identity tokens, **Method.Call**, encrypted (`Sign` and `SignAndEncrypt`) endpoints, **data-change subscriptions** (live Subscriptions pane, re-created after reconnect), **attribute writes** for the built-in primitive types. Not yet implemented: event subscriptions, ArrayDimensions / role-permission edits, custom-type editing for method inputs and Value writes that aren't built-in primitives. An experimental egui desktop front-end lives on the `egui` branch and is no longer maintained. ## License MIT — see [LICENSE](LICENSE).