PR A.2 ship-pin discovery: the MXAccess COM Toolkit installed at
C:\Program Files (x86)\ArchestrA\Framework\Bin\ArchestrA.MXAccess.dll
does not expose any alarm-event family. Reflection enumeration of
the assembly confirms ILMXProxyServerEvents and
ILMXProxyServerEvents2 only carry OnDataChange, OnWriteComplete,
OperationComplete, and OnBufferedDataChange — no IAlarmEventSink,
no Alarms collection, no OnAlarmTransition.
AVEVA's separate alarm-subscription managed assemblies
(aaAlarmManagedClient.dll under InTouch\ViewAppFramework\Content\MA\
and ArchestrAAlarmsAndEvents.SDK.Common.dll under
Wonderware\Historian\x64\) exist on this box but are x64-only —
incompatible with the worker's x86 bitness, which is the bitness
constraint the mxaccessgw architecture exists to isolate in the
first place.
This commit replaces the speculative "TBD pin during dev-rig
validation" comment in MxAccessAlarmEventSink with the actual
finding plus the two operator-facing paths forward:
1. Stay on the value-driven sub-attribute path (current production
behaviour). lmxopcua's AlarmConditionService already synthesizes
Part 9 transitions from the four MXAccess sub-attributes.
Operator-comment fidelity is the only v1 regression.
2. Add an x64 alarm-helper sub-process alongside the worker that
loads aaAlarmManagedClient and forwards transitions to the
worker over a small named-pipe IPC. Recovers full v1 fidelity
but adds operational complexity.
Until that decision resolves, the sink's Attach is a no-op, the
worker continues to function for data subscriptions, and
lmxopcua-side AlarmConditionService keeps the sub-attribute
synthesis active.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Nineteenth (final) PR of the alarms-over-gateway epic. Pins the
public RPC handler contract added in PR A.3:
- AcknowledgeAlarm rejects empty session_id and empty
alarm_full_reference with InvalidArgument.
- AcknowledgeAlarm with valid input returns OK and a
worker-pending diagnostic so clients see a successful round-trip
even before A.2's worker dispatch lands.
- QueryActiveAlarms rejects empty session_id with InvalidArgument.
- QueryActiveAlarms with valid input streams zero snapshots until
PR A.2 wires the worker-side QueryActiveAlarmsCommand
(filter-prefix passthrough verified at the proto layer).
- OpenSession advertises both new RPC capability strings
(unary-acknowledge-alarm, server-stream-active-alarms) so client
capability negotiation lights up against the contract surface.
Closes Track A's gateway-side surface. The remaining worker
ConditionRefresh walk + integration parity-rig validation lands
during dev-rig hardware validation alongside PR A.2's COM-side
alarm subscription pin.
Tests: 279 passed (was 273; 6 new). Per-handler integration tests
land alongside the dev-rig validation when the worker walks the
real MxAccess active-alarm collection.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Eighteenth PR of the alarms-over-gateway epic
(docs/plans/alarms-over-gateway.md). Lands the proto-build path that
the worker uses to create OnAlarmTransition events. The COM-side
subscription that registers an alarm event sink against the MXAccess
Toolkit is pinned during dev-rig validation — the exact API differs
across AVEVA versions and needs hardware to verify.
Lands today (unit-testable, no hardware needed):
- MxAccessEventMapper.CreateOnAlarmTransition — mechanical proto
builder. Takes decoded alarm fields (full reference, source
object, alarm type, transition kind, severity, timestamps,
operator user/comment, category, description) and produces an
MxEvent with the OnAlarmTransition body populated. Mirrors the
pattern of CreateOnDataChange / CreateOnWriteComplete / etc.
- MxAccessAlarmEventSink — scaffolded class with documented
Attach / Detach + an internal EnqueueTransition entry point.
When dev-rig validation pins the MXAccess Toolkit alarm
subscription API, the only edit needed is to wire the COM
delegate inside Attach to call EnqueueTransition. The mapper
bridge is already done.
Pending dev-rig validation:
- Pin the MXAccess Toolkit alarm event source COM API (likely one
of IAlarmEventSink, IAlarmEventSubscription, or a method on
LMXProxyServerClass — verify against the worker host's installed
version).
- Add cancellation/cleanup tests once the COM hook is wired.
- Integration test against the parity rig that fires a real Galaxy
alarm and asserts the gateway emits OnAlarmTransition.
Tests:
- 2 new mapper tests pin the full-payload Acknowledge case and
the bare-bones Raise case.
- Full Worker.Tests suite green: 123 passed (was 121; 2 new).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Twelfth PR of the alarms-over-gateway epic
(docs/plans/alarms-over-gateway.md). Lands the public RPC handler
surface that PR A.1's proto introduced. The actual worker-side
ack call + active-alarm walk depend on PR A.2 (worker MxAccess
subscription); this PR ensures clients can call the RPCs and
receive a meaningful response without UNIMPLEMENTED at the gRPC
layer.
- AcknowledgeAlarm — validates session_id + alarm_full_reference,
resolves the session (NotFound on miss), returns a successful
reply with a structured DiagnosticMessage indicating worker
dispatch is pending PR A.2. Once A.2 ships, the body translates
the request into a WorkerCommand and forwards through
SessionManager.InvokeAsync.
- QueryActiveAlarms — validates session_id, returns an empty
stream. PR A.4 layers the actual ConditionRefresh implementation
once the worker's QueryActiveAlarmsCommand is available.
- OpenSessionReply.Capabilities advertises both new RPCs
(unary-acknowledge-alarm, server-stream-active-alarms) so
clients can negotiate against the contract surface.
OnAlarmTransition events flow through the existing StreamEvents
path automatically — EventStreamService and MxAccessGrpcMapper
forward whatever family the worker emits without filtering, so
no changes are needed there for A.3.
Tests: full 273-test suite still green. Per-handler unit tests
ship with PR A.4's expanded surface; A.3's stub handlers are
narrow enough that the existing parity-fixture tests cover the
contract round-trip.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
First PR of the alarms-over-gateway epic
(docs/plans/alarms-over-gateway.md in lmxopcua). Pure contract-surface
change — no functional wiring yet. Worker-side subscription (A.2),
gateway-side dispatch + ack handler (A.3), and ConditionRefresh
(A.4) follow.
mxaccess_gateway.proto:
- Extend MxEventFamily with MX_EVENT_FAMILY_ON_ALARM_TRANSITION = 5.
- Extend MxEvent.body oneof with OnAlarmTransitionEvent on_alarm_transition = 24.
- Add OnAlarmTransitionEvent message carrying the full MxAccess alarm
payload (full reference, source object, alarm-type-name, transition
kind, raw severity, original raise timestamp, transition timestamp,
operator user/comment, category, description, current/limit value).
Mapping to OPC UA 0-1000 severity ladder happens server-side in
lmxopcua's MxAccessSeverityMapper (B.1) — gateway preserves the
native MxAccess scale.
- Add AlarmTransitionKind enum (Raise / Acknowledge / Clear / Retrigger).
- Add ActiveAlarmSnapshot + AlarmConditionState for the
ConditionRefresh stream.
- Add public RPCs AcknowledgeAlarm (unary) and QueryActiveAlarms
(server-streaming) on MxAccessGateway service.
- Add AcknowledgeAlarmRequest/Reply + QueryActiveAlarmsRequest.
GatewayContractInfo.GatewayProtocolVersion bumps 2 -> 3. Fixture
manifests (proto-inputs, behavior, parity, golden OpenSessionReply)
and protoset descriptor regenerated.
Tests: round-trip serialization for the new messages with
all-fields-populated and empty-optional-fields cases; oneof
last-write-wins guard between OnDataChange and OnAlarmTransition;
descriptor service-method enumeration includes the two new RPCs.
All 273 existing tests still pass.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Resolve 14 conflicts from popping local stash on top of origin's
eed1e88 + 8d3352f doc-comment additions (11 mechanical, plus
version.rs, DashboardAuthenticatorTests.cs, DashboardGalaxyProjector.cs)
- Fix 4 test files that used AGENTS.md as the repo-root sentinel
(now use CLAUDE.md, since AGENTS.md was removed in 4731ab5)
- Redirect 10 doc citations from AGENTS.md to the matching gateway.md
sections (Value Model, Status Model, Security, STA Worker Thread
Model, gRPC Layer rule, cancellation rule)
Verified: solution build clean, x86 worker build clean, 266/266
gateway tests passing, 121/121 worker tests passing.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>