Files
mxaccessgw/src/ZB.MOM.WW.MxGateway.Contracts/Protos/mxaccess_gateway.proto
T

1099 lines
36 KiB
Protocol Buffer

syntax = "proto3";
package mxaccess_gateway.v1;
option csharp_namespace = "ZB.MOM.WW.MxGateway.Contracts.Proto";
import "google/protobuf/duration.proto";
import "google/protobuf/timestamp.proto";
// Wire-compatibility policy (ProtobufStyleGuide): this contract evolves
// additively only. Never renumber or repurpose an existing field number or
// enum value. When a field or enum value is removed, add a `reserved` range
// (and `reserved` name) covering it in the same change so a future editor
// cannot accidentally reuse the retired tag.
// Public client API for MXAccess sessions hosted by the gateway.
service MxAccessGateway {
rpc OpenSession(OpenSessionRequest) returns (OpenSessionReply);
rpc CloseSession(CloseSessionRequest) returns (CloseSessionReply);
rpc Invoke(MxCommandRequest) returns (MxCommandReply);
rpc StreamEvents(StreamEventsRequest) returns (stream MxEvent);
rpc AcknowledgeAlarm(AcknowledgeAlarmRequest) returns (AcknowledgeAlarmReply);
// Session-less central alarm feed. The stream opens with the current
// active-alarm snapshot (one `active_alarm` per alarm), then a single
// `snapshot_complete`, then a `transition` for every subsequent change.
// Served by the gateway's always-on alarm monitor; any number of clients
// fan out from the single monitor without opening a worker session.
rpc StreamAlarms(StreamAlarmsRequest) returns (stream AlarmFeedMessage);
// Point-in-time snapshot of the currently-active alarm set served from the
// gateway's always-on alarm monitor cache (session-less). Used after a
// reconnect to seed Part 9 client state, or to reconcile alarms that may
// have been missed during a transport blip. Streamed so callers can
// begin processing without buffering the full set.
// `QueryActiveAlarmsRequest.alarm_filter_prefix` optionally narrows the
// snapshot to alarms whose `alarm_full_reference` starts with the given
// prefix; an empty prefix returns the full set.
rpc QueryActiveAlarms(QueryActiveAlarmsRequest) returns (stream ActiveAlarmSnapshot);
}
// Public request shape for QueryActiveAlarms.
// Clients may leave `session_id` empty; the gateway currently ignores it and
// serves the session-less central-monitor cache. A future version may use it
// to scope the snapshot to one session.
message QueryActiveAlarmsRequest {
string session_id = 1;
string client_correlation_id = 2;
// Optional filter: when non-empty, only snapshots whose alarm_full_reference
// starts with this string are returned.
string alarm_filter_prefix = 3;
}
message OpenSessionRequest {
string requested_backend = 1;
string client_session_name = 2;
string client_correlation_id = 3;
google.protobuf.Duration command_timeout = 4;
}
message OpenSessionReply {
string session_id = 1;
string backend_name = 2;
int32 worker_process_id = 3;
uint32 worker_protocol_version = 4;
repeated string capabilities = 5;
google.protobuf.Duration default_command_timeout = 6;
ProtocolStatus protocol_status = 7;
// Public gateway contract version implemented by this endpoint. Clients use
// this value to reject incompatible generated-code inputs before issuing
// command-specific MXAccess calls.
uint32 gateway_protocol_version = 8;
}
message CloseSessionRequest {
string session_id = 1;
string client_correlation_id = 2;
}
message CloseSessionReply {
string session_id = 1;
SessionState final_state = 2;
ProtocolStatus protocol_status = 3;
}
message StreamEventsRequest {
string session_id = 1;
uint64 after_worker_sequence = 2;
}
message MxCommandRequest {
string session_id = 1;
string client_correlation_id = 2;
MxCommand command = 3;
}
message MxCommand {
MxCommandKind kind = 1;
oneof payload {
RegisterCommand register = 10;
UnregisterCommand unregister = 11;
AddItemCommand add_item = 12;
AddItem2Command add_item2 = 13;
RemoveItemCommand remove_item = 14;
AdviseCommand advise = 15;
UnAdviseCommand un_advise = 16;
AdviseSupervisoryCommand advise_supervisory = 17;
AddBufferedItemCommand add_buffered_item = 18;
SetBufferedUpdateIntervalCommand set_buffered_update_interval = 19;
SuspendCommand suspend = 20;
ActivateCommand activate = 21;
WriteCommand write = 22;
Write2Command write2 = 23;
WriteSecuredCommand write_secured = 24;
WriteSecured2Command write_secured2 = 25;
AuthenticateUserCommand authenticate_user = 26;
ArchestrAUserToIdCommand archestra_user_to_id = 27;
AddItemBulkCommand add_item_bulk = 28;
AdviseItemBulkCommand advise_item_bulk = 29;
RemoveItemBulkCommand remove_item_bulk = 30;
UnAdviseItemBulkCommand un_advise_item_bulk = 31;
SubscribeBulkCommand subscribe_bulk = 32;
UnsubscribeBulkCommand unsubscribe_bulk = 33;
SubscribeAlarmsCommand subscribe_alarms = 34;
UnsubscribeAlarmsCommand unsubscribe_alarms = 35;
AcknowledgeAlarmCommand acknowledge_alarm_command = 36;
QueryActiveAlarmsCommand query_active_alarms_command = 37;
AcknowledgeAlarmByNameCommand acknowledge_alarm_by_name_command = 38;
WriteBulkCommand write_bulk = 39;
Write2BulkCommand write2_bulk = 40;
WriteSecuredBulkCommand write_secured_bulk = 41;
WriteSecured2BulkCommand write_secured2_bulk = 42;
ReadBulkCommand read_bulk = 43;
PingCommand ping = 100;
GetSessionStateCommand get_session_state = 101;
GetWorkerInfoCommand get_worker_info = 102;
DrainEventsCommand drain_events = 103;
ShutdownWorkerCommand shutdown_worker = 104;
}
}
enum MxCommandKind {
MX_COMMAND_KIND_UNSPECIFIED = 0;
MX_COMMAND_KIND_REGISTER = 1;
MX_COMMAND_KIND_UNREGISTER = 2;
MX_COMMAND_KIND_ADD_ITEM = 3;
MX_COMMAND_KIND_ADD_ITEM2 = 4;
MX_COMMAND_KIND_REMOVE_ITEM = 5;
MX_COMMAND_KIND_ADVISE = 6;
MX_COMMAND_KIND_UN_ADVISE = 7;
MX_COMMAND_KIND_ADVISE_SUPERVISORY = 8;
MX_COMMAND_KIND_ADD_BUFFERED_ITEM = 9;
MX_COMMAND_KIND_SET_BUFFERED_UPDATE_INTERVAL = 10;
MX_COMMAND_KIND_SUSPEND = 11;
MX_COMMAND_KIND_ACTIVATE = 12;
MX_COMMAND_KIND_WRITE = 13;
MX_COMMAND_KIND_WRITE2 = 14;
MX_COMMAND_KIND_WRITE_SECURED = 15;
MX_COMMAND_KIND_WRITE_SECURED2 = 16;
MX_COMMAND_KIND_AUTHENTICATE_USER = 17;
MX_COMMAND_KIND_ARCHESTRA_USER_TO_ID = 18;
MX_COMMAND_KIND_ADD_ITEM_BULK = 19;
MX_COMMAND_KIND_ADVISE_ITEM_BULK = 20;
MX_COMMAND_KIND_REMOVE_ITEM_BULK = 21;
MX_COMMAND_KIND_UN_ADVISE_ITEM_BULK = 22;
MX_COMMAND_KIND_SUBSCRIBE_BULK = 23;
MX_COMMAND_KIND_UNSUBSCRIBE_BULK = 24;
MX_COMMAND_KIND_SUBSCRIBE_ALARMS = 25;
MX_COMMAND_KIND_UNSUBSCRIBE_ALARMS = 26;
MX_COMMAND_KIND_ACKNOWLEDGE_ALARM = 27;
MX_COMMAND_KIND_QUERY_ACTIVE_ALARMS = 28;
MX_COMMAND_KIND_ACKNOWLEDGE_ALARM_BY_NAME = 29;
MX_COMMAND_KIND_WRITE_BULK = 30;
MX_COMMAND_KIND_WRITE2_BULK = 31;
MX_COMMAND_KIND_WRITE_SECURED_BULK = 32;
MX_COMMAND_KIND_WRITE_SECURED2_BULK = 33;
MX_COMMAND_KIND_READ_BULK = 34;
MX_COMMAND_KIND_PING = 100;
MX_COMMAND_KIND_GET_SESSION_STATE = 101;
MX_COMMAND_KIND_GET_WORKER_INFO = 102;
MX_COMMAND_KIND_DRAIN_EVENTS = 103;
MX_COMMAND_KIND_SHUTDOWN_WORKER = 104;
}
message RegisterCommand {
string client_name = 1;
}
message UnregisterCommand {
int32 server_handle = 1;
}
message AddItemCommand {
int32 server_handle = 1;
string item_definition = 2;
}
message AddItem2Command {
int32 server_handle = 1;
string item_definition = 2;
string item_context = 3;
}
message RemoveItemCommand {
int32 server_handle = 1;
int32 item_handle = 2;
}
message AdviseCommand {
int32 server_handle = 1;
int32 item_handle = 2;
}
message UnAdviseCommand {
int32 server_handle = 1;
int32 item_handle = 2;
}
message AdviseSupervisoryCommand {
int32 server_handle = 1;
int32 item_handle = 2;
}
message AddBufferedItemCommand {
int32 server_handle = 1;
string item_definition = 2;
string item_context = 3;
}
message SetBufferedUpdateIntervalCommand {
int32 server_handle = 1;
int32 update_interval_milliseconds = 2;
}
message SuspendCommand {
int32 server_handle = 1;
int32 item_handle = 2;
}
message ActivateCommand {
int32 server_handle = 1;
int32 item_handle = 2;
}
message WriteCommand {
int32 server_handle = 1;
int32 item_handle = 2;
MxValue value = 3;
int32 user_id = 4;
}
message Write2Command {
int32 server_handle = 1;
int32 item_handle = 2;
MxValue value = 3;
MxValue timestamp_value = 4;
int32 user_id = 5;
}
message WriteSecuredCommand {
int32 server_handle = 1;
int32 item_handle = 2;
int32 current_user_id = 3;
int32 verifier_user_id = 4;
// Credential-sensitive write value. Implementations must not log this field
// unless an explicit redacted value-logging path is enabled.
MxValue value = 5;
}
message WriteSecured2Command {
int32 server_handle = 1;
int32 item_handle = 2;
int32 current_user_id = 3;
int32 verifier_user_id = 4;
// Credential-sensitive write value. Implementations must not log this field
// unless an explicit redacted value-logging path is enabled.
MxValue value = 5;
MxValue timestamp_value = 6;
}
message AuthenticateUserCommand {
int32 server_handle = 1;
string verify_user = 2;
// Raw MXAccess credential. Implementations must keep this field out of logs,
// metrics labels, command lines, and diagnostics.
string verify_user_password = 3;
}
message ArchestrAUserToIdCommand {
int32 server_handle = 1;
string user_id_guid = 2;
}
message AddItemBulkCommand {
int32 server_handle = 1;
repeated string tag_addresses = 2;
}
message AdviseItemBulkCommand {
int32 server_handle = 1;
repeated int32 item_handles = 2;
}
message RemoveItemBulkCommand {
int32 server_handle = 1;
repeated int32 item_handles = 2;
}
message UnAdviseItemBulkCommand {
int32 server_handle = 1;
repeated int32 item_handles = 2;
}
message SubscribeBulkCommand {
int32 server_handle = 1;
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
// `\\<machine>\Galaxy!<area>` format (literal "Galaxy" provider). The
// worker spins up a wnwrapConsumer-backed subscription on its STA on
// first call; subsequent calls are an error (use UnsubscribeAlarms then
// 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
// currently active.
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
// AlarmAckByGUID return code.
message AcknowledgeAlarmCommand {
// Canonical 8-4-4-4-12 GUID string (e.g. "BCC47053-9542-4D65-BDAA-BCDEA6A32A73").
string alarm_guid = 1;
string comment = 2;
string operator_user = 3;
string operator_node = 4;
string operator_domain = 5;
string operator_full_name = 6;
}
// Snapshot the currently-active alarm set. Optional filter prefix scopes
// the snapshot to alarms whose alarm_full_reference starts with the
// supplied string (matches QueryActiveAlarmsRequest.alarm_filter_prefix).
message QueryActiveAlarmsCommand {
string alarm_filter_prefix = 1;
}
// Acknowledge a single alarm by its (name, provider, group) tuple. Used
// when the public RPC's AlarmFullReference (Provider!Group.Tag) cannot
// be resolved to a GUID directly. The worker invokes
// wwAlarmConsumerClass.AlarmAckByName which reaches the same alarm
// history path as AlarmAckByGUID.
message AcknowledgeAlarmByNameCommand {
// Tag/alarm name (e.g. "TestMachine_001.TestAlarm001"). Tag itself
// may contain dots; the gateway-side parser splits on the first dot
// after the '!' separator.
string alarm_name = 1;
// AVEVA alarm-provider name (literal "Galaxy" for ArchestrA Galaxies).
string provider_name = 2;
// Area/group name (e.g. "TestArea").
string group_name = 3;
string comment = 4;
string operator_user = 5;
string operator_node = 6;
string operator_domain = 7;
string operator_full_name = 8;
}
message UnsubscribeBulkCommand {
int32 server_handle = 1;
repeated int32 item_handles = 2;
}
// Bulk Write — sequential MXAccess Write per entry, on the worker's STA.
// MXAccess has no native bulk write; each entry round-trips through the same
// single-item Write path the gateway uses today. Per-item failures appear as
// BulkWriteResult entries with `was_successful = false` and never throw.
message WriteBulkCommand {
int32 server_handle = 1;
repeated WriteBulkEntry entries = 2;
}
message WriteBulkEntry {
int32 item_handle = 1;
MxValue value = 2;
int32 user_id = 3;
}
// Bulk Write2 — sequential MXAccess Write2 (timestamped) per entry.
message Write2BulkCommand {
int32 server_handle = 1;
repeated Write2BulkEntry entries = 2;
}
message Write2BulkEntry {
int32 item_handle = 1;
MxValue value = 2;
MxValue timestamp_value = 3;
int32 user_id = 4;
}
// Bulk WriteSecured — sequential MXAccess WriteSecured per entry.
// Credential-sensitive values (`value`) MUST be kept out of logs, metrics
// labels, command lines, and diagnostics — same redaction rules as the
// single-item WriteSecured contract.
message WriteSecuredBulkCommand {
int32 server_handle = 1;
repeated WriteSecuredBulkEntry entries = 2;
}
message WriteSecuredBulkEntry {
int32 item_handle = 1;
int32 current_user_id = 2;
int32 verifier_user_id = 3;
// Credential-sensitive write value. Implementations must not log this field
// unless an explicit redacted value-logging path is enabled.
MxValue value = 4;
}
// Bulk WriteSecured2 — sequential MXAccess WriteSecured2 (timestamped) per
// entry. Same redaction rules apply.
message WriteSecured2BulkCommand {
int32 server_handle = 1;
repeated WriteSecured2BulkEntry entries = 2;
}
message WriteSecured2BulkEntry {
int32 item_handle = 1;
int32 current_user_id = 2;
int32 verifier_user_id = 3;
// Credential-sensitive write value. Implementations must not log this field
// unless an explicit redacted value-logging path is enabled.
MxValue value = 4;
MxValue timestamp_value = 5;
}
// Bulk Read — snapshot the current value for each requested tag. MXAccess COM
// has no synchronous Read; the worker implements ReadBulk as:
//
// - If the tag is already in the session's item registry AND that item is
// currently advised AND the worker has a cached OnDataChange for it, the
// reply returns the cached value WITHOUT modifying the existing
// subscription (was_cached = true).
// - Otherwise the worker takes the snapshot lifecycle itself: AddItem +
// Advise, wait up to `timeout_ms` for the first OnDataChange, then
// UnAdvise + RemoveItem before returning. The session is left exactly
// as it was before the call (was_cached = false).
//
// `timeout_ms == 0` uses the gateway-configured default (1000 ms).
message ReadBulkCommand {
int32 server_handle = 1;
repeated string tag_addresses = 2;
uint32 timeout_ms = 3;
}
message PingCommand {
string message = 1;
}
message GetSessionStateCommand {
}
message GetWorkerInfoCommand {
}
message DrainEventsCommand {
uint32 max_events = 1;
}
message ShutdownWorkerCommand {
google.protobuf.Duration grace_period = 1;
}
message MxCommandReply {
string session_id = 1;
string correlation_id = 2;
MxCommandKind kind = 3;
ProtocolStatus protocol_status = 4;
// HRESULT captured from MXAccess or a COM exception. This remains separate
// from gateway protocol status so MXAccess parity details are not hidden by
// transport failures.
optional int32 hresult = 5;
MxValue return_value = 6;
repeated MxStatusProxy statuses = 7;
string diagnostic_message = 8;
oneof payload {
RegisterReply register = 20;
AddItemReply add_item = 21;
AddItem2Reply add_item2 = 22;
AddBufferedItemReply add_buffered_item = 23;
SuspendReply suspend = 24;
ActivateReply activate = 25;
AuthenticateUserReply authenticate_user = 26;
ArchestrAUserToIdReply archestra_user_to_id = 27;
BulkSubscribeReply add_item_bulk = 28;
BulkSubscribeReply advise_item_bulk = 29;
BulkSubscribeReply remove_item_bulk = 30;
BulkSubscribeReply un_advise_item_bulk = 31;
BulkSubscribeReply subscribe_bulk = 32;
BulkSubscribeReply unsubscribe_bulk = 33;
// Reply payload for BOTH MX_COMMAND_KIND_ACKNOWLEDGE_ALARM (by GUID)
// and MX_COMMAND_KIND_ACKNOWLEDGE_ALARM_BY_NAME. There is intentionally
// no by-name-specific reply case: the by-name ack carries no outcome
// detail beyond the native ack return code, so the worker reuses this
// `acknowledge_alarm` payload for both command kinds (the worker's
// MxAccessCommandExecutor sets `acknowledge_alarm` for the by-name arm
// too). Consumers must dispatch on MxCommandReply.kind, not on the
// payload case, to tell the two acks apart. The top-level `hresult`
// mirrors AcknowledgeAlarmReplyPayload.native_status and is preferred.
AcknowledgeAlarmReplyPayload acknowledge_alarm = 34;
QueryActiveAlarmsReplyPayload query_active_alarms = 35;
BulkWriteReply write_bulk = 36;
BulkWriteReply write2_bulk = 37;
BulkWriteReply write_secured_bulk = 38;
BulkWriteReply write_secured2_bulk = 39;
BulkReadReply read_bulk = 40;
SessionStateReply session_state = 100;
WorkerInfoReply worker_info = 101;
DrainEventsReply drain_events = 102;
}
}
message RegisterReply {
int32 server_handle = 1;
}
message AddItemReply {
int32 item_handle = 1;
}
message AddItem2Reply {
int32 item_handle = 1;
}
message AddBufferedItemReply {
int32 item_handle = 1;
}
message SuspendReply {
MxStatusProxy status = 1;
}
message ActivateReply {
MxStatusProxy status = 1;
}
message AuthenticateUserReply {
int32 user_id = 1;
}
message ArchestrAUserToIdReply {
int32 user_id = 1;
}
message SubscribeResult {
int32 server_handle = 1;
string tag_address = 2;
int32 item_handle = 3;
bool was_successful = 4;
string error_message = 5;
}
message BulkSubscribeReply {
repeated SubscribeResult results = 1;
}
// Per-item result for the four bulk write families. `item_handle` mirrors the
// request entry's item_handle so callers can correlate inputs to outputs even
// when the gateway's per-entry `IConstraintEnforcer.CheckWriteHandleAsync`
// filter (see `MxAccessGatewayService.ReplaceWriteBulkEntries` and
// `docs/Authorization.md`) dropped some entries before reaching the worker.
// Per-item failures populate `error_message` + `hresult` and never raise —
// callers iterate and inspect each entry.
message BulkWriteResult {
int32 server_handle = 1;
int32 item_handle = 2;
bool was_successful = 3;
optional int32 hresult = 4;
repeated MxStatusProxy statuses = 5;
string error_message = 6;
}
message BulkWriteReply {
repeated BulkWriteResult results = 1;
}
// Per-tag result for ReadBulk. `was_cached` is true when the value came from
// an existing live subscription's last OnDataChange (the worker did not touch
// the subscription); false when the worker took the AddItem + Advise + wait +
// UnAdvise + RemoveItem snapshot lifecycle itself.
//
// On `was_successful = true`, `value`, `quality`, `source_timestamp`, and
// `statuses` carry the read data (from the cached subscription or the snapshot
// lifecycle, depending on `was_cached`) and `error_message` is empty. On
// `was_successful = false`, only `server_handle`, `tag_address`, `item_handle`
// (when allocated), `was_cached`, and `error_message` are populated; `value`,
// `quality`, `source_timestamp`, and `statuses` are left at their proto3
// defaults (null / 0 / null / empty) and must not be read as data — they are
// wire-indistinguishable from "value is null with quality bad" data and serve
// only as absent markers. ReadBulk has no `hresult` field by design (its
// outcomes are timeout / cache / lifecycle states, not MXAccess COM return
// codes — see `docs/DesignDecisions.md` "Bulk Command Family"). Per-tag
// failures populate `error_message` and never raise — callers iterate and
// inspect each entry.
message BulkReadResult {
int32 server_handle = 1;
string tag_address = 2;
int32 item_handle = 3;
bool was_successful = 4;
bool was_cached = 5;
MxValue value = 6;
int32 quality = 7;
google.protobuf.Timestamp source_timestamp = 8;
repeated MxStatusProxy statuses = 9;
string error_message = 10;
}
message BulkReadReply {
repeated BulkReadResult results = 1;
}
message SessionStateReply {
SessionState state = 1;
}
message WorkerInfoReply {
int32 worker_process_id = 1;
string worker_version = 2;
string mxaccess_progid = 3;
string mxaccess_clsid = 4;
}
message DrainEventsReply {
repeated MxEvent events = 1;
}
// Reply payload for AcknowledgeAlarmCommand AND
// AcknowledgeAlarmByNameCommand — both ack command kinds reuse this
// payload case (`MxCommandReply.acknowledge_alarm`); there is no
// dedicated by-name reply case. Surfaces AVEVA's native ack return
// code (AlarmAckByGUID for the GUID arm, AlarmAckByName for the
// by-name arm); 0 means success. The MxCommandReply's hresult field
// carries the same value and is preferred for protocol consumers —
// this payload exists so the gateway-side WorkerAlarmRpcDispatcher
// can echo native_status into AcknowledgeAlarmReply.hresult without
// unpacking the outer envelope.
message AcknowledgeAlarmReplyPayload {
int32 native_status = 1;
}
// Reply payload for QueryActiveAlarmsCommand. The worker walks
// IMxAccessAlarmConsumer.SnapshotActiveAlarms and packs each record as
// an ActiveAlarmSnapshot proto for the gateway-side ConditionRefresh
// stream.
message QueryActiveAlarmsReplyPayload {
repeated ActiveAlarmSnapshot snapshots = 1;
}
message MxEvent {
MxEventFamily family = 1;
string session_id = 2;
int32 server_handle = 3;
int32 item_handle = 4;
MxValue value = 5;
int32 quality = 6;
google.protobuf.Timestamp source_timestamp = 7;
repeated MxStatusProxy statuses = 8;
uint64 worker_sequence = 9;
google.protobuf.Timestamp worker_timestamp = 10;
google.protobuf.Timestamp gateway_receive_timestamp = 11;
optional int32 hresult = 12;
string raw_status = 13;
oneof body {
OnDataChangeEvent on_data_change = 20;
OnWriteCompleteEvent on_write_complete = 21;
OperationCompleteEvent operation_complete = 22;
OnBufferedDataChangeEvent on_buffered_data_change = 23;
OnAlarmTransitionEvent on_alarm_transition = 24;
OnAlarmProviderModeChangedEvent on_alarm_provider_mode_changed = 25;
}
}
enum MxEventFamily {
MX_EVENT_FAMILY_UNSPECIFIED = 0;
MX_EVENT_FAMILY_ON_DATA_CHANGE = 1;
MX_EVENT_FAMILY_ON_WRITE_COMPLETE = 2;
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 {
}
message OnWriteCompleteEvent {
}
message OperationCompleteEvent {
}
message OnBufferedDataChangeEvent {
MxDataType data_type = 1;
MxArray quality_values = 2;
MxArray timestamp_values = 3;
int32 raw_data_type = 4;
}
// Carries a single MXAccess alarm transition (raise / acknowledge / clear /
// re-trigger) in native MXAccess terms. The Part 9 state machine + ACL +
// multi-source aggregation lives in lmxopcua's AlarmConditionService; the
// gateway is UA-agnostic and forwards the raw payload.
message OnAlarmTransitionEvent {
// Fully-qualified alarm reference (e.g. "Tank01.Level.HiHi"). Stable across
// transitions of the same condition; used by the lmxopcua side to correlate
// raise/ack/clear into a single Part 9 condition.
string alarm_full_reference = 1;
// Galaxy-side source object reference (e.g. "Tank01"). Empty for alarms
// that do not bind to a Galaxy object.
string source_object_reference = 2;
// MxAccess alarm-type qualifier (e.g. "AnalogLimitAlarm.HiHi", "DiscAlarm").
string alarm_type_name = 3;
// What kind of state change this event represents.
AlarmTransitionKind transition_kind = 4;
// Raw MXAccess severity value. Mapping to OPC UA 0-1000 happens server-side
// in lmxopcua via MxAccessSeverityMapper; the gateway preserves the native
// MXAccess scale.
int32 severity = 5;
// When the alarm originally entered the active state. Preserved across
// acknowledge transitions so the Part 9 condition keeps the original raise
// time. Unset on retrigger from a previously-cleared condition.
google.protobuf.Timestamp original_raise_timestamp = 6;
// When this specific transition occurred (raise time on Raise, ack time on
// Acknowledge, clear time on Clear).
google.protobuf.Timestamp transition_timestamp = 7;
// Operator principal recorded by MXAccess on Acknowledge transitions.
// Empty on raise / clear.
string operator_user = 8;
// Operator-supplied comment recorded by MXAccess on Acknowledge transitions.
// Empty on raise / clear or when no comment was supplied.
string operator_comment = 9;
// MxAccess alarm category (taxonomy bucket configured in the Galaxy
// template, e.g. "Process", "Safety", "Diagnostics").
string category = 10;
// Human-readable alarm description from the MxAccess alarm definition.
string description = 11;
// Current alarm value (the value of the source attribute at the moment of
// transition). Optional; populated when MxAccess surfaces it.
MxValue current_value = 12;
// 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 {
ALARM_TRANSITION_KIND_UNSPECIFIED = 0;
ALARM_TRANSITION_KIND_RAISE = 1;
ALARM_TRANSITION_KIND_ACKNOWLEDGE = 2;
ALARM_TRANSITION_KIND_CLEAR = 3;
ALARM_TRANSITION_KIND_RETRIGGER = 4;
}
// Snapshot of a currently-active MXAccess alarm condition, returned from a
// QueryActiveAlarms ConditionRefresh stream.
message ActiveAlarmSnapshot {
string alarm_full_reference = 1;
string source_object_reference = 2;
string alarm_type_name = 3;
int32 severity = 4;
google.protobuf.Timestamp original_raise_timestamp = 5;
AlarmConditionState current_state = 6;
string category = 7;
string description = 8;
// When the most recent state transition occurred (last raise, last ack,
// last clear).
google.protobuf.Timestamp last_transition_timestamp = 9;
// Operator who acknowledged the alarm if the current state is ActiveAcked.
// Empty otherwise.
string operator_user = 10;
// Operator comment recorded with the most recent acknowledge if the current
// state is ActiveAcked. Empty otherwise.
string operator_comment = 11;
MxValue current_value = 12;
MxValue limit_value = 13;
bool degraded = 14;
AlarmProviderMode source_provider = 15;
}
enum AlarmConditionState {
ALARM_CONDITION_STATE_UNSPECIFIED = 0;
ALARM_CONDITION_STATE_ACTIVE = 1;
ALARM_CONDITION_STATE_ACTIVE_ACKED = 2;
ALARM_CONDITION_STATE_INACTIVE = 3;
}
message AcknowledgeAlarmRequest {
// Retired: acknowledgement is session-less — it routes to the gateway's
// central alarm monitor, not a client worker session.
reserved 1;
reserved "session_id";
string client_correlation_id = 2;
// Fully-qualified alarm reference matching OnAlarmTransitionEvent.alarm_full_reference.
string alarm_full_reference = 3;
// Operator-supplied comment forwarded to MXAccess.
string comment = 4;
// Operator principal performing the acknowledgement. The lmxopcua side
// resolves this from the OPC UA session prior to invoking the RPC.
string operator_user = 5;
}
message AcknowledgeAlarmReply {
// Retired: see AcknowledgeAlarmRequest — acknowledgement is session-less.
reserved 1;
reserved "session_id";
string correlation_id = 2;
ProtocolStatus protocol_status = 3;
// Native ack return code echoed from the worker. The worker carries the
// ack outcome as a single int32 (AcknowledgeAlarmReplyPayload.native_status,
// = AlarmAckByName / AlarmAckByGUID return code; 0 = success); the gateway's
// WorkerAlarmRpcDispatcher copies that value here. This is the authoritative
// ack-outcome field for the public RPC. Absent only when the worker reply
// omitted the value entirely (a protocol violation).
optional int32 hresult = 4;
// Reserved for a structured MxStatusProxy view of the ack outcome. The
// worker by-name/by-GUID ack path produces only the int32 return code
// (see `hresult`), so the current gateway leaves this field UNSET on every
// reply. Clients must read `hresult` (and `protocol_status`) for the ack
// result and must not depend on `status` being populated.
MxStatusProxy status = 5;
string diagnostic_message = 6;
}
// Request to attach to the gateway's central alarm feed (StreamAlarms).
message StreamAlarmsRequest {
string client_correlation_id = 1;
// Optional alarm-reference prefix scoping the feed to an equipment
// sub-tree. Empty streams every active alarm.
string alarm_filter_prefix = 2;
}
// One message on the StreamAlarms feed. The stream opens with one
// `active_alarm` per currently-active alarm, then a single
// `snapshot_complete`, then a `transition` for every subsequent change.
message AlarmFeedMessage {
oneof payload {
// Part of the initial active-alarm snapshot (ConditionRefresh).
ActiveAlarmSnapshot active_alarm = 1;
// Sentinel: the initial snapshot is fully delivered and `transition`
// messages follow. Always true when present.
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
// wire). Despite the name it is NOT a boolean — it is the raw numeric
// indicator the worker reads off the COM struct without reinterpretation.
// It is carried verbatim for diagnostics; the authoritative success/
// failure of the operation is `category` (MX_STATUS_CATEGORY_OK marks
// success), with `detail`, `diagnostic_text`, `raw_category`, and
// `raw_detected_by` describing any non-OK outcome. Clients should branch
// on `category`, not on a specific `success` value.
int32 success = 1;
MxStatusCategory category = 2;
MxStatusSource detected_by = 3;
int32 detail = 4;
int32 raw_category = 5;
int32 raw_detected_by = 6;
string diagnostic_text = 7;
}
enum MxStatusCategory {
MX_STATUS_CATEGORY_UNSPECIFIED = 0;
MX_STATUS_CATEGORY_UNKNOWN = 1;
MX_STATUS_CATEGORY_OK = 2;
MX_STATUS_CATEGORY_PENDING = 3;
MX_STATUS_CATEGORY_WARNING = 4;
MX_STATUS_CATEGORY_COMMUNICATION_ERROR = 5;
MX_STATUS_CATEGORY_CONFIGURATION_ERROR = 6;
MX_STATUS_CATEGORY_OPERATIONAL_ERROR = 7;
MX_STATUS_CATEGORY_SECURITY_ERROR = 8;
MX_STATUS_CATEGORY_SOFTWARE_ERROR = 9;
MX_STATUS_CATEGORY_OTHER_ERROR = 10;
}
enum MxStatusSource {
MX_STATUS_SOURCE_UNSPECIFIED = 0;
MX_STATUS_SOURCE_UNKNOWN = 1;
MX_STATUS_SOURCE_REQUESTING_LMX = 2;
MX_STATUS_SOURCE_RESPONDING_LMX = 3;
MX_STATUS_SOURCE_REQUESTING_NMX = 4;
MX_STATUS_SOURCE_RESPONDING_NMX = 5;
MX_STATUS_SOURCE_REQUESTING_AUTOMATION_OBJECT = 6;
MX_STATUS_SOURCE_RESPONDING_AUTOMATION_OBJECT = 7;
}
message MxValue {
MxDataType data_type = 1;
string variant_type = 2;
bool is_null = 3;
string raw_diagnostic = 4;
int32 raw_data_type = 5;
oneof kind {
bool bool_value = 10;
int32 int32_value = 11;
int64 int64_value = 12;
float float_value = 13;
double double_value = 14;
string string_value = 15;
google.protobuf.Timestamp timestamp_value = 16;
MxArray array_value = 17;
bytes raw_value = 18;
}
}
message MxArray {
MxDataType element_data_type = 1;
string variant_type = 2;
repeated uint32 dimensions = 3;
string raw_diagnostic = 4;
int32 raw_element_data_type = 5;
oneof values {
BoolArray bool_values = 10;
Int32Array int32_values = 11;
Int64Array int64_values = 12;
FloatArray float_values = 13;
DoubleArray double_values = 14;
StringArray string_values = 15;
TimestampArray timestamp_values = 16;
RawArray raw_values = 17;
}
}
message BoolArray {
repeated bool values = 1;
}
message Int32Array {
repeated int32 values = 1;
}
message Int64Array {
repeated int64 values = 1;
}
message FloatArray {
repeated float values = 1;
}
message DoubleArray {
repeated double values = 1;
}
message StringArray {
repeated string values = 1;
}
message TimestampArray {
repeated google.protobuf.Timestamp values = 1;
}
message RawArray {
repeated bytes values = 1;
}
enum MxDataType {
MX_DATA_TYPE_UNSPECIFIED = 0;
MX_DATA_TYPE_UNKNOWN = 1;
MX_DATA_TYPE_NO_DATA = 2;
MX_DATA_TYPE_BOOLEAN = 3;
MX_DATA_TYPE_INTEGER = 4;
MX_DATA_TYPE_FLOAT = 5;
MX_DATA_TYPE_DOUBLE = 6;
MX_DATA_TYPE_STRING = 7;
MX_DATA_TYPE_TIME = 8;
MX_DATA_TYPE_ELAPSED_TIME = 9;
MX_DATA_TYPE_REFERENCE_TYPE = 10;
MX_DATA_TYPE_STATUS_TYPE = 11;
MX_DATA_TYPE_ENUM = 12;
MX_DATA_TYPE_SECURITY_CLASSIFICATION_ENUM = 13;
MX_DATA_TYPE_DATA_QUALITY_TYPE = 14;
MX_DATA_TYPE_QUALIFIED_ENUM = 15;
MX_DATA_TYPE_QUALIFIED_STRUCT = 16;
MX_DATA_TYPE_INTERNATIONALIZED_STRING = 17;
MX_DATA_TYPE_BIG_STRING = 18;
MX_DATA_TYPE_END = 19;
}
message ProtocolStatus {
ProtocolStatusCode code = 1;
string message = 2;
}
enum ProtocolStatusCode {
PROTOCOL_STATUS_CODE_UNSPECIFIED = 0;
PROTOCOL_STATUS_CODE_OK = 1;
PROTOCOL_STATUS_CODE_INVALID_REQUEST = 2;
PROTOCOL_STATUS_CODE_SESSION_NOT_FOUND = 3;
PROTOCOL_STATUS_CODE_SESSION_NOT_READY = 4;
PROTOCOL_STATUS_CODE_WORKER_UNAVAILABLE = 5;
PROTOCOL_STATUS_CODE_TIMEOUT = 6;
PROTOCOL_STATUS_CODE_CANCELED = 7;
PROTOCOL_STATUS_CODE_PROTOCOL_VIOLATION = 8;
PROTOCOL_STATUS_CODE_MXACCESS_FAILURE = 9;
}
enum SessionState {
SESSION_STATE_UNSPECIFIED = 0;
SESSION_STATE_CREATING = 1;
SESSION_STATE_STARTING_WORKER = 2;
SESSION_STATE_WAITING_FOR_PIPE = 3;
SESSION_STATE_HANDSHAKING = 4;
SESSION_STATE_INITIALIZING_WORKER = 5;
SESSION_STATE_READY = 6;
SESSION_STATE_CLOSING = 7;
SESSION_STATE_CLOSED = 8;
SESSION_STATE_FAULTED = 9;
}