From 1d85db7b4e11923932692125c08f17ecbe3e65dd Mon Sep 17 00:00:00 2001 From: Joseph Doherty Date: Sat, 13 Jun 2026 08:53:02 -0400 Subject: [PATCH] contracts(gateway): AlarmProviderMode, subtag watch-list, provider status, degraded provenance, mode-changed event --- .../Protos/mxaccess_gateway.proto | 59 +++++++++++++++++++ 1 file changed, 59 insertions(+) diff --git a/src/ZB.MOM.WW.MxGateway.Contracts/Protos/mxaccess_gateway.proto b/src/ZB.MOM.WW.MxGateway.Contracts/Protos/mxaccess_gateway.proto index eeb3b1c..4394702 100644 --- a/src/ZB.MOM.WW.MxGateway.Contracts/Protos/mxaccess_gateway.proto +++ b/src/ZB.MOM.WW.MxGateway.Contracts/Protos/mxaccess_gateway.proto @@ -315,6 +315,14 @@ message SubscribeBulkCommand { repeated string tag_addresses = 2; } +// Provider selection / current provider for the alarm feed. UNSPECIFIED on a +// SubscribeAlarmsCommand means auto: alarmmgr primary with subtag fallback. +enum AlarmProviderMode { + ALARM_PROVIDER_MODE_UNSPECIFIED = 0; + ALARM_PROVIDER_MODE_ALARMMGR = 1; + ALARM_PROVIDER_MODE_SUBTAG = 2; +} + // Subscribe the worker's alarm consumer to an AVEVA alarm provider. // Subscription expression follows the canonical // `\\\Galaxy!` format (literal "Galaxy" provider). The @@ -323,6 +331,12 @@ message SubscribeBulkCommand { // SubscribeAlarms to reconfigure). message SubscribeAlarmsCommand { string subscription_expression = 1; + // UNSPECIFIED = auto-failover/failback. ALARMMGR/SUBTAG force one provider. + AlarmProviderMode forced_mode = 2; + // Subtag watch-list resolved by the gateway (GR SQL + config). Empty in pure + // alarmmgr mode; in subtag mode it bounds what the consumer can observe. + repeated AlarmSubtagTarget watch_list = 3; + AlarmFailoverConfig failover = 4; } // Tear down the worker's alarm consumer. No-op if no subscription is @@ -330,6 +344,23 @@ message SubscribeAlarmsCommand { message UnsubscribeAlarmsCommand { } +// One alarm attribute the subtag fallback consumer advises. Addresses are full +// MXAccess item references the worker passes straight to AddItem. +message AlarmSubtagTarget { + string alarm_full_reference = 1; // e.g. "Galaxy!Area.Tank01.Level.HiHi" + string source_object_reference = 2; // e.g. "Tank01" + string active_subtag = 3; // item address of the in-alarm boolean + string acked_subtag = 4; // item address of the acknowledged boolean + string ack_comment_subtag = 5; // writable ack-comment attribute (ack write target) + string priority_subtag = 6; // optional severity source; empty if absent +} + +message AlarmFailoverConfig { + int32 consecutive_failure_threshold = 1; // wnwrap COM failures before switching (>=1) + int32 failback_probe_interval_seconds = 2; // probe cadence while degraded (>=1) + int32 failback_stable_probes = 3; // clean probes before switching back (>=1) +} + // Acknowledge a single alarm by its GUID. Operator identity fields are // recorded atomically with the ack transition in the alarm-history log. // The reply's hresult / native_status surfaces AVEVA's @@ -684,6 +715,7 @@ message MxEvent { OperationCompleteEvent operation_complete = 22; OnBufferedDataChangeEvent on_buffered_data_change = 23; OnAlarmTransitionEvent on_alarm_transition = 24; + OnAlarmProviderModeChangedEvent on_alarm_provider_mode_changed = 25; } } @@ -694,6 +726,7 @@ enum MxEventFamily { MX_EVENT_FAMILY_OPERATION_COMPLETE = 3; MX_EVENT_FAMILY_ON_BUFFERED_DATA_CHANGE = 4; MX_EVENT_FAMILY_ON_ALARM_TRANSITION = 5; + MX_EVENT_FAMILY_ON_ALARM_PROVIDER_MODE_CHANGED = 6; } message OnDataChangeEvent { @@ -768,6 +801,20 @@ message OnAlarmTransitionEvent { // Limit/threshold value that triggered the transition for limit alarms. // Optional; populated for AnalogLimitAlarm-family transitions. MxValue limit_value = 13; + + // True when this transition came from the subtag-monitoring fallback rather + // than the native alarmmgr provider — synthesized from data changes, reduced + // fidelity (synthetic GUID, no native raise time). + bool degraded = 14; + // Which provider produced this transition. + AlarmProviderMode source_provider = 15; +} + +message OnAlarmProviderModeChangedEvent { + AlarmProviderMode mode = 1; + string reason = 2; + int32 hresult = 3; // COM HRESULT that triggered failover; 0 on failback + google.protobuf.Timestamp at = 4; } enum AlarmTransitionKind { @@ -800,6 +847,8 @@ message ActiveAlarmSnapshot { string operator_comment = 11; MxValue current_value = 12; MxValue limit_value = 13; + bool degraded = 14; + AlarmProviderMode source_provider = 15; } enum AlarmConditionState { @@ -866,9 +915,19 @@ message AlarmFeedMessage { bool snapshot_complete = 2; // A live alarm state change (raise / acknowledge / clear). OnAlarmTransitionEvent transition = 3; + // Provider-mode status. Emitted once on stream open and again on every + // failover/failback so late joiners learn the current mode immediately. + AlarmProviderStatus provider_status = 4; } } +message AlarmProviderStatus { + AlarmProviderMode mode = 1; + bool degraded = 2; // true whenever mode == SUBTAG + string reason = 3; // human-readable switch reason + google.protobuf.Timestamp since = 4; +} + message MxStatusProxy { // Mirrors the `success` member of the MXAccess MXSTATUS_PROXY struct // (a 16-bit signed value in the COM struct, widened to int32 on the