ab202a1fa1
New tool wrapping ArchestrA.MxAccess.LMXProxyServerClass (the same COM
proxy aaObjectViewer / WindowViewer use) as a CliFx CLI for LLM-driven
debugging.
Commands:
- mxa info — loaded MxAccess assembly identity, supported value
types, MxStatusCategory enum.
- mxa read — fetch one or more tag values; subscribes briefly,
captures first OnDataChange per tag, tears down.
- mxa write — write a value with optional --type coercion; advises
first to resolve the attribute type, then waits for
OnWriteComplete with a per-call timeout.
- mxa subscribe — stream OnDataChange events for --seconds; JSON Lines
under --llm-json for piped agent consumption.
- mxa diag — minimal smoke test on a private STA thread; bypasses
the CliFx pipeline for diagnosing apartment / pump
issues.
Implementation notes documented in docs/api-notes.md (reverse-engineered
because AVEVA does not publish a single canonical MxAccess reference):
- Net48 / x86 / [STAThread] are non-negotiable. The CLI runs the entire
CliFx pipeline on a dedicated STA thread.
- COM events are dispatched as Win32 messages; AutoResetEvent.WaitOne
alone does not pump them on this configuration. MxSession.WaitForUpdate
loops Application.DoEvents() + drain + Sleep(20ms) instead.
- Write requires the target attribute's type to be resolved first.
WriteCommand advises and waits for the initial OnDataChange before
calling LMXProxyServerClass.Write to avoid ArgumentException
"Value does not fall within the expected range".
- Errors carry the full MXSTATUS_PROXY[] from MxAccess (Success,
Category, DetectedBy, Detail) so an agent can tell exactly which
layer rejected a request.
Verified against the live ZB galaxy with a writeable tag identified
via grdb (TestChildObject.TestInt, mx_attribute_category=10):
read: 99 (q=192, MxCategoryOk)
write 7: round-tripped — read returned 7 — written back to 99
write str: TestChildObject.TestString round-tripped a timestamp
subscribe: captured initial value plus subsequent change from a
separate process
The vendored ArchestrA.MxAccess.dll is gitignored — it is copied from
C:\Program Files (x86)\ArchestrA\Framework\Bin\ on any System Platform
install per the README.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
73 lines
4.7 KiB
Markdown
73 lines
4.7 KiB
Markdown
# mxaccesscli
|
|
|
|
A `.NET Framework 4.8 / x86` CliFx-based CLI for **reading, writing, and subscribing to AVEVA System Platform tags via MxAccess** (`ArchestrA.MxAccess.LMXProxyServerClass`). Output as scannable text or as a stable JSON envelope for LLM consumption. Built-in per-tag and per-call timeouts; structured surface of MxStatus categories on every error.
|
|
|
|
## Hard constraints
|
|
|
|
- **MxAccess is a 32-bit COM proxy.** The CLI must stay on `net48` / `x86` / `[STAThread]`. Do not retarget to .NET 10 or x64 — `LMXProxyServerClass` is registered for the WoW64 server only.
|
|
- **System Platform must be installed locally** so that `ArchestrA.MxAccess` is registered with COM and the LMX runtime is reachable. Without it `Register()` fails with a COM error.
|
|
- **MxAccess events fire on the registering apartment.** Calls **must** originate from an STA thread, which is why `Program.Main` is `[STAThread]`. If you call from a non-STA thread, events queue but never get pumped and your timeouts will always fire.
|
|
- **Reads are not synchronous in MxAccess.** "Read" is implemented as a brief subscribe → wait for first `OnDataChange` → tear down. If a tag never delivers a `DataChange` (offscan, wrong reference, security denied), the read times out — that's the correct semantic, not a CLI bug.
|
|
- **Writes need user identity for secured attributes.** Default `--user-id 0` is "unauthenticated"; secured attributes will reject. Use `--user-id <id>` after calling `AuthenticateUser()` from another path (or, for a CLI smoke test, target a non-secured `Writeable_USC_*` attribute).
|
|
|
|
## Layout
|
|
|
|
```text
|
|
mxaccesscli/
|
|
README.md this file
|
|
AGENTS.md agent rules for working in this folder
|
|
MxAccess.Cli.slnx
|
|
lib/
|
|
ArchestrA.MxAccess.dll (copied from System Platform's Framework\Bin)
|
|
src/MxAccess.Cli/
|
|
MxAccess.Cli.csproj
|
|
Program.cs [STAThread] entry point
|
|
IsExternalInit.cs net48 polyfill for C# 9 init accessors
|
|
Commands/ read, write, subscribe, info
|
|
Mx/ MxSession, MxItem, MxUpdate, ValueCoercion
|
|
Output/ LLM-JSON envelope writer
|
|
docs/
|
|
usage.md command surface, examples, JSON envelope contract
|
|
api-notes.md reverse-engineered MxAccess API reference (since AVEVA's
|
|
online docs are sparse): types, events, threading, status semantics
|
|
```
|
|
|
|
## Resource index — by task
|
|
|
|
| Task | Go to |
|
|
| --- | --- |
|
|
| Agent rules for editing this CLI | [`AGENTS.md`](AGENTS.md) |
|
|
| Run the CLI / option reference / examples | [`docs/usage.md`](docs/usage.md) |
|
|
| MxAccess API surface, threading model, MxStatus semantics | [`docs/api-notes.md`](docs/api-notes.md) |
|
|
| Find a writeable tag in the live galaxy (so smoke tests have a target) | [`../grdb/README.md`](../grdb/README.md) |
|
|
| Read tag values via SQL retrieval (an alternative path) | [`../histdb/README.md`](../histdb/README.md) |
|
|
|
|
### External documentation
|
|
|
|
AVEVA does not publish a single canonical MxAccess reference online. The closest official sources:
|
|
|
|
- `https://docs.aveva.com/` — search "MxAccess", "LMXProxyServer", "Object Viewer". Coverage is partial and depends on which product portal you land on.
|
|
- AVEVA Knowledge Base (subscriber-only): TID-based articles on `LMX` registration, secured writes, and `WriteSecured2`.
|
|
- The shipped `MXAccess32.tlb` type library at `C:\Program Files (x86)\ArchestrA\Framework\Bin\` is the most authoritative source for method signatures. [`docs/api-notes.md`](docs/api-notes.md) summarizes what it exposes.
|
|
|
|
## Build & run
|
|
|
|
```powershell
|
|
dotnet build src/MxAccess.Cli/MxAccess.Cli.csproj -p:Platform=x86 -c Release
|
|
|
|
# Read two tags with a 3-second timeout, JSON envelope:
|
|
dotnet run --project src/MxAccess.Cli/MxAccess.Cli.csproj -- read TestMachine_001.Speed Reactor1.Level -t 3 --llm-json
|
|
|
|
# Write a value with explicit type:
|
|
dotnet run --project src/MxAccess.Cli/MxAccess.Cli.csproj -- write TestMachine_001.Setpoint 42.5 --type double
|
|
|
|
# Subscribe to a tag for 30 seconds, JSON Lines for streaming:
|
|
dotnet run --project src/MxAccess.Cli/MxAccess.Cli.csproj -- subscribe TestMachine_001.Speed -s 30 --llm-json
|
|
```
|
|
|
|
The built executable is `bin\x86\Release\net48\mxa.exe`. Drop on `PATH` and use `mxa read ...`.
|
|
|
|
## Maintenance
|
|
|
|
This README follows the doctrine in [`../DOCS-GUIDE.md`](../DOCS-GUIDE.md). When you add a command, an option, or a new field on the JSON envelope, update [`docs/usage.md`](docs/usage.md) in the same change. Update [`docs/api-notes.md`](docs/api-notes.md) only if the underlying MxAccess assembly changes (different System Platform version, etc.). The root [`../CLAUDE.md`](../CLAUDE.md) carries one row pointing at this README — it should not need to change unless the tool's task surface changes.
|