Adds a 'Type support matrix' table to docs/usage.md capturing what was
verified against the live ZB galaxy on System Platform 2017 Express
with MxAccess 3.2.0.0:
Verified read + write (round-tripped):
- MxBoolean — DelmiaReceiver_001.TestAttribute (false→true→false)
- MxInteger — MESReceiver_001.MoveInBatchID (999→12345→0→999)
- MxString — MESReceiver_001.MoveOutErrorText (round-trip + restore)
- String array element via 1-based [N] indexing
— MESReceiver_001.MoveInPartNumbers[2] (11111→ARR-WRITE-OK→11111)
Verified read only (no writeable instance in this galaxy):
- MxFloat — DevPlatform.CPULoad{,Avg,Max,Min}, PageFaultsAvg
- MxTime — DevPlatform.SystemStartupTime → ISO-8601 string
- MxReferenceType — Container/Host/Area → target object's Tagname
Wired but no live instance found (matrix marked '❓'):
- MxDouble, MxElapsedTime, MxQualifiedEnum, MxInternationalizedString,
MxBigString. Adding a writeable UDA of any of these types should
exercise the existing code path without further changes.
Hard limitation surfaced and documented:
- MxAccess.AddItem('<obj>.<arrayAttr>') for bulk array read returns
MxCategoryCommunicationError, Detail=1003. Read array elements
individually via the 1-based '[N]' suffix; '[0]' is invalid.
Adds a 'Reading arrays' section pointing at grdb's attributes.sql
('array_dimension' column) for discovering element count.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
11 KiB
mxa — usage
Read, write, and subscribe to AVEVA System Platform tags via MxAccess. The CLI runs in-process: each invocation registers an LMXProxyServer, executes, and unregisters cleanly. Errors carry the underlying MxStatusCategory so an agent can decide whether the failure is transient (Pending), configurational, or operational.
Common notes
- Tag references are full attribute paths:
<ObjectName>.<AttributeName>(e.g.TestMachine_001.Speed). ForGalaxy:references, follow the convention used in InTouch / Object Viewer. --client <name>sets the client name passed to MxAccessRegister(). Defaults tomxa. Most install logs key on this string.- Timeouts are per-call. They control how long the CLI waits for a
OnDataChange(read) orOnWriteComplete(write). The default is 5 seconds. - First-event latency. LMX has to resolve the reference and bind to the hosting engine on each fresh client connection. Empirically the first
OnDataChangearrives 3-8 seconds afterAdvise(). Set timeouts andsubscribe --secondsaccordingly: a 3-secondreadmay legitimately time out on first contact, then succeed on the next try because LMX has cached the binding. - Subsequent events are fast. Once a tag is bound, value-change updates propagate within ~100 ms.
- Exit codes:
0on success,1if any operation timed out or returned a non-Ok / non-PendingMxStatusCategory,2on argument-validation errors.
mxa info
Print the loaded ArchestrA.MxAccess assembly identity, supported --type values, and the full MxStatusCategory enum. No tag access.
mxa info
mxa read <tag> [<tag>...]
Reads one or more tags by briefly subscribing and capturing the first OnDataChange per tag.
| Option | Default | Notes |
|---|---|---|
-t, --timeout <seconds> |
5 |
Per-tag timeout. Tags that don't deliver a DataChange within the window are reported with error: timeout. |
--client <name> |
mxa |
Passed to Register(). |
--llm-json |
off | Emit the JSON envelope. |
Examples:
mxa read TestMachine_001.Speed
mxa read TestMachine_001.Speed Reactor1.Level -t 3
mxa read TestMachine_001.Speed Reactor1.Level --llm-json
LLM-JSON envelope:
{
"query": { "command": "read", "tags": ["TestMachine_001.Speed"], "timeout_s": 5.0, "client": "mxa" },
"ok": true,
"results": [
{
"tag": "TestMachine_001.Speed",
"ok": true,
"value": 1234.5,
"quality": 192,
"timestamp": "2026-05-03T19:42:18.001",
"statuses": [
{ "Success": 0, "Category": "MxCategoryOk", "DetectedBy": "MxSourceRespondingAutomationObject", "Detail": 0 }
]
}
]
}
mxa write <tag> <value>
Writes one value to one tag and waits for OnWriteComplete.
| Option | Default | Notes |
|---|---|---|
--type <kind> |
inferred | Force the .NET type used for the boxed value. One of bool, byte, short, int, long, float, double, string, datetime. |
-t, --timeout <seconds> |
5 |
How long to wait for OnWriteComplete. |
--user-id <int> |
0 |
Authenticated user id. 0 is unauthenticated; secured attributes will reject. |
--client <name> |
mxa |
Passed to Register(). |
--llm-json |
off | Emit the JSON envelope. |
Type inference rules (when --type is not set): true/false/yes/no/on/off/1/0 → bool; pure integer → int (then long); decimals → double; everything else → string.
Examples:
mxa write TestMachine_001.Setpoint 42.5 --type double
mxa write TestMachine_001.RunFlag true
mxa write TestMachine_001.Label "Hello world"
mxa write Reactor1.Setpoint 100 --type int -t 10 --llm-json
The same JSON envelope shape as read, with results[0] containing { tag, ok, error?, statuses }. No value/quality/timestamp on the write result — consult a follow-up mxa read to confirm.
mxa subscribe <tag> [<tag>...]
Streams OnDataChange events for a duration.
| Option | Default | Notes |
|---|---|---|
-s, --seconds <seconds> |
10 |
Wall-clock duration of the subscription. |
--max <int> |
1000 |
Hard cap on emitted events. |
--client <name> |
mxa |
Passed to Register(). |
--llm-json |
off | JSON Lines mode — one JSON object per line, no outer envelope. |
Human output:
[INFO] Subscribed to 1 tag(s). Streaming for 30.0s. Ctrl-C to stop early.
[19:42:18.001] [OK ] TestMachine_001.Speed = 1234.5 (q=192)
[19:42:19.002] [OK ] TestMachine_001.Speed = 1245.7 (q=192)
...
[INFO] 30 event(s) emitted; subscription closed.
LLM-JSON output (one event per line, no surrounding [ ... ]):
{"tag":"TestMachine_001.Speed","ok":true,"value":1234.5,"quality":192,"timestamp":"2026-05-03T19:42:18.001","statuses":[{...}]}
{"tag":"TestMachine_001.Speed","ok":true,"value":1245.7,"quality":192,"timestamp":"2026-05-03T19:42:19.002","statuses":[{...}]}
JSON Lines lets a downstream consumer parse events incrementally rather than buffering the whole stream — the right shape for indefinite or long-running subscriptions.
Type support matrix
Verified end-to-end against the live ZB galaxy (System Platform 2017 Express, MxAccess 3.2.0.0). Each row records what the wire shape looks like in the JSON envelope.
MxDataType |
Read | Write | JSON shape | Notes |
|---|---|---|---|---|
MxBoolean |
✅ | ✅ | JSON true / false |
--type bool accepts true/false/1/0/yes/no/on/off. |
MxInteger (Int32) |
✅ | ✅ | JSON number | --type int. Up-cast to long if it overflows int.MaxValue. |
MxFloat (single) |
✅ | ⚠️ | JSON number | Read verified on DevPlatform.CPULoad family. Write requires a writeable Float UDA — none in the test galaxy, but --type float is wired. |
MxDouble |
❓ | ❓ | JSON number | No accessible Double instance in the test galaxy. Wiring is identical to Float; expected to work. |
MxString |
✅ | ✅ | JSON string | Default inferred type for non-numeric values. |
MxTime (DateTime) |
✅ | ⚠️ | JSON string "YYYY-MM-DDTHH:mm:ss" |
Read verified on DevPlatform.SystemStartupTime. Write via --type datetime accepts ISO-8601. |
MxElapsedTime |
❓ | ❓ | JSON number (seconds) | No accessible instance in the test galaxy. |
MxReferenceType |
✅ | – | JSON string (target object's Tagname) |
E.g. TestChildObject.Container → "DevTestObject". Writing references is not exposed by the CLI. |
MxQualifiedEnum (13) |
❓ | – | (likely string) | No accessible instance. |
MxQualifiedStruct (14) |
– | – | – | Access via dotted member names: <obj>.<struct>.<field>. |
MxInternationalizedString (15) |
❓ | ❓ | (likely string) | No accessible instance. |
MxBigString (16) |
❓ | ❓ | JSON string | No accessible instance. |
| Array (any type), bulk read | ❌ | – | — | MxAccess.AddItem(<arrayRef>) → MxCategoryCommunicationError, Detail=1003. Bulk array reads are not supported by this LMX client API. |
| Array element by index | ✅ | ✅ | scalar of element type | Reference syntax <obj>.<arrayAttr>[<n>]. 1-based indexing. Verified on MESReceiver_001.MoveInPartNumbers[2] (String[]). [0] is invalid. |
Legend: ✅ verified live, ⚠️ wiring present but no live instance to write, ❓ wiring present but no live instance found, ❌ not supported by MxAccess at this layer, – not applicable.
To test write support for a type, use ../../grdb/ to find a deployed instance whose dynamic_attribute.mx_data_type matches and whose mx_attribute_category is in (2-11, 24) (Writeable_* family).
Errors and statuses
Every result carries a statuses array — the elements of the COM MXSTATUS_PROXY[] MxAccess passes back. Field names match the C# struct exactly:
| Field | Type | Meaning |
|---|---|---|
Success |
int16 | 0 = Ok, non-zero = error code |
Category |
enum | MxCategoryOk, MxCategoryPending, MxCategoryWarning, MxCategoryCommunicationError, MxCategoryConfigurationError, MxCategoryOperationalError, MxCategorySecurityError, MxCategorySoftwareError, MxCategoryOtherError, MxStatusCategoryUnknown |
DetectedBy |
enum | MxSourceRequestingLmx, MxSourceRespondingLmx, MxSourceRequestingNmx, MxSourceRespondingNmx, MxSourceRequestingAutomationObject, MxSourceRespondingAutomationObject, MxSourceUnknown |
Detail |
int16 | Additional error-code detail |
A result is considered ok only if every statuses element has Category in (MxCategoryOk, MxCategoryPending).
Common failure shapes:
Category: MxCategoryConfigurationError— usually a typo'd reference or the attribute doesn't exist on the deployed instance. Sanity-check viagraccesscli object snapshot.Category: MxCategoryCommunicationError— engine isn't running, object is OffScan, or LMX can't reach the platform hosting the object.Category: MxCategorySecurityError— secured attribute,--user-id 0. UseWriteSecuredsemantics (not yet exposed by this CLI) or target aWriteable_USC_*attribute.- Timeout — most likely the tag is genuinely silent (no value updates) or the reference is wrong. With
--llm-jsonyou'll see"error": "timeout"and an emptystatuses.
Reading arrays
MxAccess does not return array attributes as a single rowset. Bulk AddItem("<obj>.<arrayAttr>") returns MxCategoryCommunicationError, Detail=1003. Read elements individually:
mxa read 'MESReceiver_001.MoveInPartNumbers[1]' \
'MESReceiver_001.MoveInPartNumbers[2]' \
'MESReceiver_001.MoveInPartNumbers[3]' \
--llm-json
- Array indices are 1-based (
[1],[2], …).[0]is invalid and returns a configuration error. - The CLI does not (yet) auto-discover the array length; combine with
../../grdb/queries/attributes.sql(array_dimensioncolumn) to know how many elements to fetch. - Writing an element uses the same indexed reference:
mxa write '<obj>.<attr>[N]' <value>.
Picking a tag for a smoke test
If the live galaxy is not familiar:
- Connect to the Galaxy Repository SQL — see
../../grdb/connectioninfo.md. - Find a deployed instance with a writeable UDA —
../../grdb/queries/attributes.sqllists user-defined attributes with their data type. Filter on aWriteable_*security classification (see../../aot/dev-guide/appendix-e-security-classifications.md). - The reference for MxAccess is
<InstanceName>.<AttributeName>.