using System; using System.Collections.Generic; namespace ZB.MOM.WW.MxGateway.Worker.MxAccess; /// /// Abstraction over an AVEVA alarm-consumer COM library. The production /// implementation () wraps /// WNWRAPCONSUMERLib.wwAlarmConsumerClass from /// C:\Program Files (x86)\Common Files\ArchestrA\wnwrapConsumer.dll; /// tests substitute a fake to drive transition events without a live /// Galaxy. /// /// /// /// The receive surface is poll-based: the production consumer /// periodically calls GetXmlCurrentAlarms2, parses the /// returned XML payload, diffs against the previous snapshot keyed /// by alarm GUID, and raises /// once per state change. This bypasses the FILETIME marshaling /// crash in aaAlarmManagedClient.AlarmClient.GetHighPriAlarm /// (see docs/AlarmClientDiscovery.md) — XML strings carry /// timestamps as ASCII fields, no DateTime auto-conversion happens /// on the .NET interop boundary. /// /// public interface IMxAccessAlarmConsumer : IDisposable { /// /// Fires once per detected alarm-state transition (raise, acknowledge, /// clear, or new-alarm-already-acked-on-arrival). Subscribers are /// expected to translate the record into the proto family /// OnAlarmTransition and enqueue it. Fired on the consumer's /// polling thread (the worker's STA in production); subscribers that /// need a different thread must marshal back themselves. /// event EventHandler? AlarmTransitionEmitted; /// /// Whether the most recent fetch that reached the retained snapshot came /// back holding the per-fetch cap. While this is /// the snapshot returned by is /// authoritative about presence only: the provider may hold actives it /// had no room to report, and the consumer has suspended the /// absence-implies-Clear inference. Not latched — the first sub-cap fetch /// after a run of capped ones clears it, because that fetch is complete /// and the snapshot it produced is again authoritative about absence. /// Consumers with no per-fetch cap (the subtag fallback, which is /// event-driven) always report . /// bool LastSnapshotTruncated { get; } /// /// Initializes the AVEVA alarm-client connection, registers as a /// consumer, and subscribes to the supplied alarm-provider expression. /// Subscription string follows AVEVA's canonical format: /// \\<node>\Galaxy!<area>. The literal "Galaxy" is /// the provider name (regardless of the configured Galaxy database /// name). Subscribe does not start any polling of its own; the caller /// drives polls explicitly via . /// /// The subscription expression (e.g., \\HOST\Galaxy!Area). void Subscribe(string subscription); /// /// Acknowledges a single alarm with full operator-identity fidelity. /// Reaches AVEVA's native AlarmAckByGUID; operator /// user / node / domain / full-name and the comment land atomically /// with the ack transition in the alarm-history log. /// /// The alarm GUID. /// The acknowledgment comment. /// The operator name. /// The operator node. /// The operator domain. /// The operator full name. /// The AVEVA-native status code. int AcknowledgeByGuid( Guid alarmGuid, string ackComment, string ackOperatorName, string ackOperatorNode, string ackOperatorDomain, string ackOperatorFullName); /// /// Acknowledge a single alarm by its (name, provider, group) tuple. /// Reaches AVEVA's AlarmAckByName on /// wwAlarmConsumerClass; same alarm-history outcome as /// , used when the caller has the /// human-readable reference but not the canonical GUID. /// /// The alarm name. /// The provider name. /// The group name. /// The acknowledgment comment. /// The operator name. /// The operator node. /// The operator domain. /// The operator full name. /// The AVEVA-native status code. int AcknowledgeByName( string alarmName, string providerName, string groupName, string ackComment, string ackOperatorName, string ackOperatorNode, string ackOperatorDomain, string ackOperatorFullName); /// /// Returns the consumer's most recently parsed snapshot of currently /// active alarms. Used by the gateway's QueryActiveAlarms (PR A.7) /// ConditionRefresh path — operator clients call this after reconnect /// to seed local Part 9 state. /// /// The most recently parsed snapshot of currently active alarms. IReadOnlyList SnapshotActiveAlarms(); /// /// Drives a single synchronous poll of the underlying alarm source. /// The production consumer owns no internal timer; the worker's STA /// drives polls via StaRuntime.InvokeAsync, satisfying the /// ThreadingModel=Apartment requirement of /// wwAlarmConsumerClass. Fake implementations should no-op. /// This method must be invoked on the thread that created the consumer /// (the worker's STA in production). /// void PollOnce(); }