# MxAccess API notes Reverse-engineered from the shipped `ArchestrA.MxAccess.dll` (assembly version `3.2.0.0`, file at `C:\Program Files (x86)\ArchestrA\Framework\Bin\ArchestrA.MXAccess.dll`) plus its sibling type libraries `MXAccess.tlb` / `MXAccess20.tlb` / `MXAccess32.tlb`. AVEVA does not publish a single canonical online reference for this assembly, which is why this file exists. The assembly is registered in the GAC at `C:\Windows\assembly\GAC_MSIL\ArchestrA.MxAccess\3.2.0.0__23106a86e706d0ae\`. Strong name: `PublicKeyToken=23106a86e706d0ae`. ## Threading model `LMXProxyServerClass` is a COM proxy. **All calls — and the events the proxy fires — run on the apartment that called `Register`.** The CLI's `Program.Main` is `[STAThread]` for this reason; if you call into MxAccess from a non-STA thread you'll observe: - `Register()` returns a handle but events never fire. - `Write()` queues but `OnWriteComplete` never reaches your handler. A deeper STA pump is unnecessary for one-shot CLI invocations because CliFx's `ICommand.ExecuteAsync` runs on the entry thread synchronously, and the COM marshaller pumps the calling apartment while waiting on `WaitOne`. ## Type catalog The full public surface from reflection: ```text class LMXProxyServerClass -- the entry point (newable) class LMXProxyServer -- alias / synonym iface ILMXProxyServer -- v1 method set (Register, AddItem, Advise, Write, WriteSecured, AuthenticateUser) iface ILMXProxyServer2 -- adds ArchestrAUserToId iface ILMXProxyServer3 -- adds AddItem2 iface ILMXProxyServer4 -- adds Write2, WriteSecured2, Suspend, Activate, AdviseSupervisory iface ILMXProxyServer5 -- adds AddBufferedItem, SetBufferedUpdateInterval iface _ILMXProxyServerEvents -- OnDataChange, OnWriteComplete, OperationComplete iface _ILMXProxyServerEvents2 -- OnBufferedDataChange struct MxStatus -- success:int16, category:MxStatusCategory, detectedBy:MxStatusSource, detail:int16 struct MXSTATUS_PROXY -- same fields; passed to event handlers as an array enum MxStatusCategory -- 10 values; see `mxa info` enum MxStatusSource -- 7 values; "who detected this status" enum MxDataType -- MxNoData / MxBoolean / MxInteger / MxFloat / MxDouble / MxString / MxTime / MxElapsedTime / MxReferenceType / MxStatusType / MxDataTypeEnum / MxSecurityClassificationEnum / MxDataQualityType / MxQualifiedEnum / MxQualifiedStruct / MxInternationalizedString / MxBigString / MxDataTypeEND / MxDataTypeUnknown ``` ## Lifecycle methods ```csharp int Register(string clientName); // returns hServer void Unregister(int hServer); int AddItem(int hServer, string itemRef); // returns hItem int AddItem2(int hServer, string itemRef, string itemContext); int AddBufferedItem(int hServer, string itemRef, string itemContext); void RemoveItem(int hServer, int hItem); void Advise(int hServer, int hItem); void UnAdvise(int hServer, int hItem); void AdviseSupervisory(int hServer, int hItem); // higher-rate / mxsupv updates void SetBufferedUpdateInterval(int hServer, int intervalMs); ``` `Suspend` / `Activate` toggle update delivery on a per-item basis without losing the AddItem handle. ## Write methods ```csharp void Write (int hServer, int hItem, object value, int userId); void Write2 (int hServer, int hItem, object value, object timestamp, int userId); void WriteSecured (int hServer, int hItem, int currentUserId, int verifierUserId, object value); void WriteSecured2 (int hServer, int hItem, int currentUserId, int verifierUserId, object value, object timestamp); ``` `userId = 0` is unauthenticated. For attributes with **Operate**, **Tune**, **Configure**, **View Only**, **Free Access**, **Secured Write**, or **Verified Write** classifications (see [`../../aot/dev-guide/appendix-e-security-classifications.md`](../../aot/dev-guide/appendix-e-security-classifications.md)): - **Free Access** — `Write` succeeds with `userId = 0`. - **Operate / Tune / Configure** — `Write` requires a real `userId` from `AuthenticateUser`. - **Secured Write** — must call `WriteSecured` with the same user as both `currentUserId` and `verifierUserId` (or use `Write` after `AuthenticateUser` if Galaxy security allows). - **Verified Write** — must call `WriteSecured` with two distinct authenticated user ids (operator + verifier). ## Authentication helpers ```csharp int AuthenticateUser(int hServer, string verifyUser, string verifyUserPwd); int ArchestrAUserToId(int hServer, string userIdGuid); ``` `AuthenticateUser` returns a non-zero user id when credentials match the Galaxy security configuration, or 0 on failure. `ArchestrAUserToId` resolves a Galaxy user GUID to its numeric id. ## Events All events fire on the registering apartment. The CLI bridges them to a `ConcurrentQueue` plus an `AutoResetEvent` so command code uses `WaitForUpdate(predicate, timeout, out update)` rather than dealing with the COM event signature directly. ```csharp event OnDataChange(int hServer, int hItem, object value, int quality, object timestamp, ref MXSTATUS_PROXY[] statuses); event OnWriteComplete(int hServer, int hItem, ref MXSTATUS_PROXY[] statuses); event OperationComplete(int hServer, int hItem, ref MXSTATUS_PROXY[] statuses); // fires on AddItem completion etc. event OnBufferedDataChange(int hServer, int hItem, MxDataType dataType, object value, object quality, object timestamp, ref MXSTATUS_PROXY[] statuses); // only when AddBufferedItem was used ``` `timestamp` arrives as a Win32 `FILETIME` boxed inside an `object` (decimal/Int64-shaped). The CLI converts via `DateTime.FromFileTimeUtc(Convert.ToInt64(...))` and exposes it as a local-time `DateTime?`; if conversion fails the field is `null`. `quality` on `OnDataChange` is the legacy 16-bit OPC quality value (e.g. `192 = 0xC0` for "Good"). The richer state lives in the `statuses[]` array, especially `Category` and `DetectedBy`. ## Status semantics `MxStatusCategory` values, in roughly ascending severity: | Category | Meaning | | --- | --- | | `MxCategoryOk` | Operation succeeded. | | `MxCategoryPending` | Operation accepted, working on it; not an error. | | `MxCategoryWarning` | Soft issue (e.g. value clamped); operation proceeded. | | `MxCategoryCommunicationError` | LMX/NMX / engine reach failure. | | `MxCategoryConfigurationError` | Reference unresolved, attribute missing, type mismatch. | | `MxCategoryOperationalError` | Object not OnScan, attribute read-only, etc. | | `MxCategorySecurityError` | Secured / Verified attribute and credentials insufficient. | | `MxCategorySoftwareError` | Bug in the LMX runtime — usually rare. | | `MxCategoryOtherError` | Catch-all. | | `MxStatusCategoryUnknown` | Couldn't classify. | `MxStatusSource` tells you *who* set the category — useful when the same code (e.g. `MxCategoryConfigurationError`) can come from the requesting LMX (your client side) versus the responding automation object (the server side): ``` MxSourceRequestingLmx - this CLI's local LMX MxSourceRespondingLmx - the LMX hosting the target MxSourceRequestingNmx - cross-node messaging on this side MxSourceRespondingNmx - cross-node messaging on the target side MxSourceRequestingAutomationObject MxSourceRespondingAutomationObject MxSourceUnknown ``` A `statuses` array often has multiple entries — one per layer that touched the request. The CLI emits all of them so an agent can pinpoint which layer rejected the call. ## Buffered items `AddBufferedItem` returns updates batched at `SetBufferedUpdateInterval` (milliseconds) intervals via `OnBufferedDataChange`. Useful for high-rate tags where you want time-bucketed snapshots instead of every tick. The CLI does not expose this surface yet — adding a `subscribe --buffered ` option is straightforward. ## Type libraries | File | Use | | --- | --- | | `MXAccess.tlb` | v1 — minimal interface, legacy clients. | | `MXAccess20.tlb` | adds events. | | `MXAccess32.tlb` | full v3.x surface — what `ArchestrA.MxAccess.dll 3.2.0.0` projects. | If you need to consume MxAccess from a different language (C++, Python via comtypes, etc.), import `MXAccess32.tlb` rather than the older versions — they expose subsets. ## What the CLI does not (yet) cover - `Suspend` / `Activate` — easy to add as a sub-command. - `AddItem2` with explicit context — the CLI passes a single tag reference; if your environment needs context (cross-galaxy, role-based) wrap it. - `WriteSecured` / `WriteSecured2` — adding a `--verifier-id ` option to `WriteCommand` is the natural extension. - `AdviseSupervisory` and `AddBufferedItem` — opt-in performance modes.