From 5310fd0e266bd86df2112b36802ef884cf0649b6 Mon Sep 17 00:00:00 2001 From: Joseph Doherty Date: Mon, 9 Nov 2026 12:31:37 -0500 Subject: [PATCH] feat(streaming): carry IsMesReportable on AlarmStateUpdate (25) and DebugAlarmStateDto (20) (ScadaBridge#60) Central's Debug View live stream and Alarm Summary cache always saw false because neither wire message had the field. Additive proto fields, vendored C# regenerated with docker/regen-proto.sh (sitestream + sitecommand), mapped both ways in StreamRelayActor/SiteStreamGrpcClient and SiteCommandDtoMapper. The live stream publishes Alarm Actor events, which never carried the flag, so InstanceActor.HandleAlarmStateChanged now stamps it before retaining and publishing. A pre-#60 site sends the proto3 default. No UI badge yet. Claude-Session: https://claude.ai/code/session_01GT67AEHd2Acv1YPwGfXEoV --- CLAUDE.md | 2 +- ...-09-11-mes-reportable-alarm-flag-design.md | 8 + .../Messages/Streaming/AlarmStateChanged.cs | 7 +- .../Actors/StreamRelayActor.cs | 4 +- .../Grpc/SiteCommandDtoMapper.cs | 6 +- .../Grpc/SiteStreamGrpcClient.cs | 4 +- .../Protos/site_command.proto | 3 + .../Protos/sitestream.proto | 5 + .../SiteCommandGrpc/SiteCommand.cs | 458 ++++++++++-------- .../SiteStreamGrpc/Sitestream.cs | 179 ++++--- .../Actors/InstanceActor.cs | 22 +- .../Grpc/StreamRelayActorTests.cs | 34 ++ .../SiteCommandSamples.cs | 8 +- ...InstanceActorMesReportableSnapshotTests.cs | 43 +- 14 files changed, 489 insertions(+), 294 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index c2bbb169..e9a907e5 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -112,7 +112,7 @@ spec for each is `docs/requirements/Component-.md`, and `README.md` carrie - **`ActiveNodeEvaluator.SelfIsOldestUp` is THE single definition of "active node"** (`Communication/ClusterState/ActiveNodeEvaluator.cs`) — the **oldest Up member** in a role scope, and explicitly **never `cluster.State.Leader`**: leadership (lowest address) is an Akka-internal concept that diverges from singleton placement permanently once the original first node restarts and rejoins, and both sides claim it during a partition. The equivalence *oldest-Up == where `ClusterSingletonManager` places singletons* **is** the design. `ClusterActivityEvaluator.SelfIsOldest`, the S&F delivery gate, `/health/active` and the heartbeat `IsActive` stamp all delegate here. - Site nodes carry **two Akka roles**: the base `Site` plus a site-specific `site-{SiteId}` (`AkkaHostedService.BuildRoles`). Singletons scope to the **site-specific** role. - **The gRPC boundary is authenticated (PSK) as of 2026-07-22; Akka remoting still is not, and nothing is encrypted.** Akka remoting sets no `enable-ssl`, no secure cookie, no `trusted-selection-paths` — so intra-cluster Akka remoting remains open to anyone who can reach the remoting port, and that boundary still assumes a trusted network. The gRPC listener stays **h2c**, but `SiteStreamService` is no longer open: `ControlPlaneAuthInterceptor` (`Host/ControlPlaneAuthInterceptor.cs`) gates `/sitestream.SiteStreamService/` — including the `PullAuditEvents`/`PullSiteCalls` RPCs that return audit rows — against a **per-site preshared key**, fail-closed, constant-time compared, alongside the separate `LocalDbSyncAuthInterceptor` on `/localdb_sync.v1.LocalDbSync/` with its own separate key. **Site side:** `ScadaBridge:Communication:GrpcPsk`, in production `${secret:SB-GRPC-PSK-}`, and **`StartupValidator` refuses to boot a site node without it** (an unset key would leave the node healthy-looking but serving nothing). **Central side:** `SitePskProvider` resolves `SB-GRPC-PSK-{siteId}` from the secrets store at channel-build time (sites are added at runtime, so no boot-time expansion is possible), with `ScadaBridge:Communication:SitePsks:{siteId}` as an override for hosts running without a master key — the docker rig uses the latter. One key per site, never fleet-wide. A bearer token over h2c is readable and replayable on-path; TLS is the follow-on hardening and needs no change to this design. Introduced by Phase 0 of the ClusterClient→gRPC migration (`docs/plans/2026-07-22-clusterclient-to-grpc-plan.md`). -- gRPC streaming channel — **note the direction is inverted from the data flow**: data moves site→central, but each **site node hosts the gRPC server** (`SiteStreamGrpcServer`, Kestrel h2c, port 8083, mapped **only in the Site branch** of `Program.cs`) and **central is the client**, dialling in. Central creates per-site `SiteStreamGrpcClient` via `SiteStreamGrpcClientFactory`, keyed **`(siteId, endpoint)`** — the key was widened from site-only to fix an arch-review High where one session's NodeA→NodeB flip disposed a channel another session was still using. Proto evolution is **additive only** and field numbers are never reused (`AlarmStateUpdate` grew 7→23 fields for the native-alarm mirror, then 24 for `AckTime`). Generated C# is **vendored** under `Communication/SiteStreamGrpc/` with the `` include commented out — regeneration is a manual toggle-build-copy-untoggle, automated by `docker/regen-proto.sh [sitestream|centralcontrol|sitecommand|all]` (it always restores the csproj; an active `` item must never be committed — it breaks the Docker build). **Stream events are BATCHED as of R2 (2026-08-15)** — a site emitting ~37.5k events/s used to pay one gRPC message per event. Additive wire shape, no new RPC: `batching_supported` on the request (`InstanceStreamRequest` field 3 / `SiteStreamRequest` field 2) plus a `SiteStreamEvent.batch` oneof case (**field 4**) carrying a new `SiteStreamEventBatch { repeated SiteStreamEvent events = 1 }`. **The proto3 default of that flag IS the negotiation, and it is load-bearing** — a batch frame reaches a pre-R2 central as `EventOneofCase.None`, whose `ConvertToDomainEvent` returns null, so the whole batch would vanish with no error anywhere; an old central cannot set the flag, so it never gets one, and an old site ignores the unknown request field and keeps sending per-event frames the new client's `ForEachEvent` unpack handles as the single-event case. Server side is `SiteStreamEventBatcher`, a per-subscriber pump **downstream of `StreamRelayActor`'s bounded DropOldest channel** — so it changes framing only and **does NOT move the burst ceiling** (deferred register row 31; that ceiling lives in the shared publish stage upstream of the BroadcastHub). It never delays a lone event: it drains the already-queued backlog for free and lingers only once a backlog is proven, then emits a single-event buffer as a plain frame. `GrpcStreamBatchMaxEvents` (100, `1` disables) and `GrpcStreamBatchWindow` (25 ms, validated **strictly under 250 ms** = the load test's end-to-end P99 threshold); measured worst case P99 25.4 ms. **Benchmark-proven at target scale 2026-08-18** (the LoadHarness wire path — real Kestrel h2c + real `SiteStreamGrpcClient`, `--wire-probes-per-site`): 899,807 events in 12,462 frames (mean 72.2 ev/frame), wire P99 43.4 ms (5.8× inside the 250 ms budget — a 75-event burst never hits the 100 cap, so every batch pays the full 25 ms window: this workload's worst-case latency posture), zero drops/faults; results doc §8. Histogram `scadabridge.site.stream.batch_size`, recorded only on negotiated streams (`ScadaBridgeTelemetry.MeterName` is already in the `ObservedMeters` allowlist). **The client reconnects on graceful (OK-status) stream completion, not just on fault (arch-review remediation, commit `34a3f4bb`)** — Kestrel's `MaxStreamLifetime`/`Grpc.AspNetCore.Server` max-connection-age periodically ends a healthy stream with a normal completion, which the client used to treat as terminal (no reconnect attempt), silently killing a site's live feed until the next process restart (observed up to ~4h on the rig); live-probed at a 2-minute forced lifetime, reconnect lands within one reconcile tick and `IsLive` reflects the gap in between. +- gRPC streaming channel — **note the direction is inverted from the data flow**: data moves site→central, but each **site node hosts the gRPC server** (`SiteStreamGrpcServer`, Kestrel h2c, port 8083, mapped **only in the Site branch** of `Program.cs`) and **central is the client**, dialling in. Central creates per-site `SiteStreamGrpcClient` via `SiteStreamGrpcClientFactory`, keyed **`(siteId, endpoint)`** — the key was widened from site-only to fix an arch-review High where one session's NodeA→NodeB flip disposed a channel another session was still using. Proto evolution is **additive only** and field numbers are never reused (`AlarmStateUpdate` grew 7→23 fields for the native-alarm mirror, then 24 for `AckTime`, then 25 for `IsMesReportable` — Gitea #60). Generated C# is **vendored** under `Communication/SiteStreamGrpc/` with the `` include commented out — regeneration is a manual toggle-build-copy-untoggle, automated by `docker/regen-proto.sh [sitestream|centralcontrol|sitecommand|all]` (it always restores the csproj; an active `` item must never be committed — it breaks the Docker build). **Stream events are BATCHED as of R2 (2026-08-15)** — a site emitting ~37.5k events/s used to pay one gRPC message per event. Additive wire shape, no new RPC: `batching_supported` on the request (`InstanceStreamRequest` field 3 / `SiteStreamRequest` field 2) plus a `SiteStreamEvent.batch` oneof case (**field 4**) carrying a new `SiteStreamEventBatch { repeated SiteStreamEvent events = 1 }`. **The proto3 default of that flag IS the negotiation, and it is load-bearing** — a batch frame reaches a pre-R2 central as `EventOneofCase.None`, whose `ConvertToDomainEvent` returns null, so the whole batch would vanish with no error anywhere; an old central cannot set the flag, so it never gets one, and an old site ignores the unknown request field and keeps sending per-event frames the new client's `ForEachEvent` unpack handles as the single-event case. Server side is `SiteStreamEventBatcher`, a per-subscriber pump **downstream of `StreamRelayActor`'s bounded DropOldest channel** — so it changes framing only and **does NOT move the burst ceiling** (deferred register row 31; that ceiling lives in the shared publish stage upstream of the BroadcastHub). It never delays a lone event: it drains the already-queued backlog for free and lingers only once a backlog is proven, then emits a single-event buffer as a plain frame. `GrpcStreamBatchMaxEvents` (100, `1` disables) and `GrpcStreamBatchWindow` (25 ms, validated **strictly under 250 ms** = the load test's end-to-end P99 threshold); measured worst case P99 25.4 ms. **Benchmark-proven at target scale 2026-08-18** (the LoadHarness wire path — real Kestrel h2c + real `SiteStreamGrpcClient`, `--wire-probes-per-site`): 899,807 events in 12,462 frames (mean 72.2 ev/frame), wire P99 43.4 ms (5.8× inside the 250 ms budget — a 75-event burst never hits the 100 cap, so every batch pays the full 25 ms window: this workload's worst-case latency posture), zero drops/faults; results doc §8. Histogram `scadabridge.site.stream.batch_size`, recorded only on negotiated streams (`ScadaBridgeTelemetry.MeterName` is already in the `ObservedMeters` allowlist). **The client reconnects on graceful (OK-status) stream completion, not just on fault (arch-review remediation, commit `34a3f4bb`)** — Kestrel's `MaxStreamLifetime`/`Grpc.AspNetCore.Server` max-connection-age periodically ends a healthy stream with a normal completion, which the client used to treat as terminal (no reconnect attempt), silently killing a site's live feed until the next process restart (observed up to ~4h on the rig); live-probed at a 2-minute forced lifetime, reconnect lands within one reconcile tick and `IsLive` reflects the gap in between. - Native alarms are a **read-only** mirror of OPC UA Alarms & Conditions and MxAccess Gateway alarms — **no ack-back, no central tables**; state lives in the site's `native_alarm_state`, survives failover, and is cleared on redeploy/undeploy (mirrors static overrides). Central's per-site live alarm cache (`ISiteAlarmLiveCache`) is **transient in-memory only** — there is deliberately no persisted central alarm store, so the 15s poll remains the NotReporting authority behind the live stream. See `Component-DataConnectionLayer.md` / `Component-CentralUI.md` for the model and the authoring surface. Computed alarms carry an `IsMesReportable` flag (template checkbox, instance-overridable via a nullable override) exposed to scripts as `ScriptAlarm.IsMesReportable` / `Alarms.MesReportableAsync()` (2026-09-11); native alarms have no per-alarm row and keep the 900–999 MES severity band. - **`AckTime` mirror enrichment + the `Alarms` script accessor (MES alarm-status API Phase 1, 2026-08-01).** `AlarmStateChanged` carries an additive `AckTime` (`DateTimeOffset?`), mirrored on the vendored `AlarmStateUpdate` proto as **field 24** and persisted inside `native_alarm_state`'s `metadata_json` — deliberately NOT a new column, because that table is `RegisterReplicated` and LocalDb builds its CDC triggers from the column list at registration time. Set only while a condition is active AND acknowledged (so it is null while unacked and cleared on re-raise); the DCL stamps the source's own ack instant for OPC UA (new SelectClause **index 18** = `AckedState/TransitionTime`) and its observation time of the ack transition for MxGateway, which supplies none. Site `Call` scripts read alarms via the new **`Alarms.CurrentAsync()`** accessor (`ScriptRuntimeContext` + `ScriptGlobals`, local Ask on `GetAlarmSnapshotRequest`, returns `Commons.Types.Scripts.ScriptAlarm`), mirrored on `ScriptCompileSurface` AND the Central UI `SandboxScriptHost` editor surface. The trust model needed no change — it is a deny-list over API roots, not an allow-list of context members. Plan: `docs/plans/2026-06-30-mes-alarm-status-api.md` (Phases 2–4 are deployed config, not repo). - OPC UA cert trust is **site-local and not persisted centrally** (follow-up): the verify-endpoint probe captures an untrusted server cert but **NEVER trusts it**, and DeploymentManager broadcasts `TrustServerCertCommand`/`RemoveServerCertCommand` to **BOTH** site nodes — `CertStoreActor` runs on every site node, not as a singleton, so PKI stores stay consistent across failover. diff --git a/docs/plans/2026-09-11-mes-reportable-alarm-flag-design.md b/docs/plans/2026-09-11-mes-reportable-alarm-flag-design.md index 34ade192..e681a136 100644 --- a/docs/plans/2026-09-11-mes-reportable-alarm-flag-design.md +++ b/docs/plans/2026-09-11-mes-reportable-alarm-flag-design.md @@ -95,6 +95,14 @@ field 20, manual `regen-proto.sh`) plus mapper changes. Not needed for the scrip inbound API, so it is **deferred** (register row) to keep this slice free of wire changes. Design-time surfaces (template Alarms tab, Instance Configure overrides) DO show the flag. +**Update (Gitea #60, 2026-11-09): the wire half is done.** `AlarmStateUpdate` field 25 and +`DebugAlarmStateDto` field 20 (`is_mes_reportable`) carry the flag, mapped both ways in +`StreamRelayActor`/`SiteStreamGrpcClient` and `SiteCommandDtoMapper`. Because the live stream +publishes Alarm Actor events, `InstanceActor.HandleAlarmStateChanged` now also stamps the flag +before retaining and publishing (the snapshot projection still re-applies it, so retained and +fallback rows agree). A pre-#60 site sends the proto3 default `false`. No central surface renders +a "MES" badge yet — that is a UI decision left for when operators ask for it. + ### 2.5 The inbound API method (deployed config, rig) `AlarmStatus` — the full-filter endpoint from the legacy spec, minus the BTDB machine lookup diff --git a/src/ZB.MOM.WW.ScadaBridge.Commons/Messages/Streaming/AlarmStateChanged.cs b/src/ZB.MOM.WW.ScadaBridge.Commons/Messages/Streaming/AlarmStateChanged.cs index ca5691be..6f38201d 100644 --- a/src/ZB.MOM.WW.ScadaBridge.Commons/Messages/Streaming/AlarmStateChanged.cs +++ b/src/ZB.MOM.WW.ScadaBridge.Commons/Messages/Streaming/AlarmStateChanged.cs @@ -111,9 +111,10 @@ public record AlarmStateChanged( /// /// True when the alarm's deployed configuration flags it as MES-reportable /// (ResolvedAlarm.IsMesReportable). Stamped by the Instance Actor on its alarm - /// snapshot; always false for native conditions, which have no per-alarm config row. - /// NOT carried on the gRPC stream or the debug-snapshot DTO in this slice (no proto - /// field on either) — central sees the default. Additive; default false. + /// snapshot and on every event it relays to the site stream; always false for native + /// conditions, which have no per-alarm config row. Carried to central on + /// AlarmStateUpdate field 25 and DebugAlarmStateDto field 20 (Gitea #60); + /// a pre-#60 site sends the proto3 default. Additive; default false. /// public bool IsMesReportable { get; init; } } diff --git a/src/ZB.MOM.WW.ScadaBridge.Communication/Actors/StreamRelayActor.cs b/src/ZB.MOM.WW.ScadaBridge.Communication/Actors/StreamRelayActor.cs index d5bcf1cd..dbba105f 100644 --- a/src/ZB.MOM.WW.ScadaBridge.Communication/Actors/StreamRelayActor.cs +++ b/src/ZB.MOM.WW.ScadaBridge.Communication/Actors/StreamRelayActor.cs @@ -104,7 +104,9 @@ public class StreamRelayActor : ReceiveActor // computed alarms — a null proto Timestamp round-trips back to null. AckTime = msg.AckTime.HasValue ? Timestamp.FromDateTimeOffset(msg.AckTime.Value) - : null + : null, + // Gitea #60: the deployed MES-reportable flag, stamped by the Instance Actor. + IsMesReportable = msg.IsMesReportable } }; diff --git a/src/ZB.MOM.WW.ScadaBridge.Communication/Grpc/SiteCommandDtoMapper.cs b/src/ZB.MOM.WW.ScadaBridge.Communication/Grpc/SiteCommandDtoMapper.cs index f498fa2d..cc832a25 100644 --- a/src/ZB.MOM.WW.ScadaBridge.Communication/Grpc/SiteCommandDtoMapper.cs +++ b/src/ZB.MOM.WW.ScadaBridge.Communication/Grpc/SiteCommandDtoMapper.cs @@ -1941,7 +1941,8 @@ public static class SiteCommandDtoMapper CurrentValue = alarm.CurrentValue, LimitValue = alarm.LimitValue, NativeSourceCanonicalName = alarm.NativeSourceCanonicalName, - IsConfiguredPlaceholder = alarm.IsConfiguredPlaceholder + IsConfiguredPlaceholder = alarm.IsConfiguredPlaceholder, + IsMesReportable = alarm.IsMesReportable }; if (alarm.Condition != AlarmConditionStateFactory.ForComputed(alarm.State, alarm.Priority)) @@ -1983,7 +1984,8 @@ public static class SiteCommandDtoMapper CurrentValue = dto.CurrentValue, LimitValue = dto.LimitValue, NativeSourceCanonicalName = dto.NativeSourceCanonicalName, - IsConfiguredPlaceholder = dto.IsConfiguredPlaceholder + IsConfiguredPlaceholder = dto.IsConfiguredPlaceholder, + IsMesReportable = dto.IsMesReportable }; return dto.Condition is null ? alarm : alarm with { Condition = FromProto(dto.Condition) }; diff --git a/src/ZB.MOM.WW.ScadaBridge.Communication/Grpc/SiteStreamGrpcClient.cs b/src/ZB.MOM.WW.ScadaBridge.Communication/Grpc/SiteStreamGrpcClient.cs index 3152707c..67d9a7cd 100644 --- a/src/ZB.MOM.WW.ScadaBridge.Communication/Grpc/SiteStreamGrpcClient.cs +++ b/src/ZB.MOM.WW.ScadaBridge.Communication/Grpc/SiteStreamGrpcClient.cs @@ -605,7 +605,9 @@ public class SiteStreamGrpcClient : IAsyncDisposable, IDisposable IsConfiguredPlaceholder = evt.AlarmChanged.IsConfiguredPlaceholder, // MES alarm-status API §6.4: ack instant; an absent proto Timestamp (unacked // condition, computed alarm, or a pre-AckTime site) stays null. - AckTime = evt.AlarmChanged.AckTime?.ToDateTimeOffset() + AckTime = evt.AlarmChanged.AckTime?.ToDateTimeOffset(), + // Gitea #60: a pre-#60 site leaves the field at its proto3 default (false). + IsMesReportable = evt.AlarmChanged.IsMesReportable }, _ => null }; diff --git a/src/ZB.MOM.WW.ScadaBridge.Communication/Protos/site_command.proto b/src/ZB.MOM.WW.ScadaBridge.Communication/Protos/site_command.proto index 2f0dfedc..585f0070 100644 --- a/src/ZB.MOM.WW.ScadaBridge.Communication/Protos/site_command.proto +++ b/src/ZB.MOM.WW.ScadaBridge.Communication/Protos/site_command.proto @@ -654,6 +654,9 @@ message DebugAlarmStateDto { string limit_value = 17; string native_source_canonical_name = 18; bool is_configured_placeholder = 19; + // MES-reportable flag stamped by the Instance Actor's snapshot (Gitea #60); false for + // native conditions and from a pre-#60 site (proto3 default). + bool is_mes_reportable = 20; } message DebugViewSnapshotDto { diff --git a/src/ZB.MOM.WW.ScadaBridge.Communication/Protos/sitestream.proto b/src/ZB.MOM.WW.ScadaBridge.Communication/Protos/sitestream.proto index 535a8afd..59166e1c 100644 --- a/src/ZB.MOM.WW.ScadaBridge.Communication/Protos/sitestream.proto +++ b/src/ZB.MOM.WW.ScadaBridge.Communication/Protos/sitestream.proto @@ -141,6 +141,11 @@ message AlarmStateUpdate { // protocol supplies one (OPC UA A&C AckedState/TransitionTime) and the DCL's observation // time of the ack transition where it does not (MxAccess Gateway). google.protobuf.Timestamp ack_time = 24; + + // True when the alarm's deployed configuration flags it MES-reportable + // (ResolvedAlarm.IsMesReportable, Gitea #60). Always false for native conditions, + // which have no per-alarm config row; a pre-#60 site leaves it at the proto3 default. + bool is_mes_reportable = 25; } // Audit Log (#23) telemetry: single lifecycle event ferried from a site SQLite diff --git a/src/ZB.MOM.WW.ScadaBridge.Communication/SiteCommandGrpc/SiteCommand.cs b/src/ZB.MOM.WW.ScadaBridge.Communication/SiteCommandGrpc/SiteCommand.cs index d8570c38..8c371b69 100644 --- a/src/ZB.MOM.WW.ScadaBridge.Communication/SiteCommandGrpc/SiteCommand.cs +++ b/src/ZB.MOM.WW.ScadaBridge.Communication/SiteCommandGrpc/SiteCommand.cs @@ -292,7 +292,7 @@ namespace ZB.MOM.WW.ScadaBridge.Communication.Grpc { "dGgYAiABKAkSFgoOYXR0cmlidXRlX25hbWUYAyABKAkSNQoFdmFsdWUYBCAB", "KAsyJi5zY2FkYWJyaWRnZS5zaXRlY29tbWFuZC52MS5Mb29zZVZhbHVlEg8K", "B3F1YWxpdHkYBSABKAkSLQoJdGltZXN0YW1wGAYgASgLMhouZ29vZ2xlLnBy", - "b3RvYnVmLlRpbWVzdGFtcCKvBQoSRGVidWdBbGFybVN0YXRlRHRvEhwKFGlu", + "b3RvYnVmLlRpbWVzdGFtcCLKBQoSRGVidWdBbGFybVN0YXRlRHRvEhwKFGlu", "c3RhbmNlX3VuaXF1ZV9uYW1lGAEgASgJEhIKCmFsYXJtX25hbWUYAiABKAkS", "OAoFc3RhdGUYAyABKA4yKS5zY2FkYWJyaWRnZS5zaXRlY29tbWFuZC52MS5B", "bGFybVN0YXRlRHRvEhAKCHByaW9yaXR5GAQgASgFEi0KCXRpbWVzdGFtcBgF", @@ -307,212 +307,213 @@ namespace ZB.MOM.WW.ScadaBridge.Communication.Grpc { "aW5hbF9yYWlzZV90aW1lGA8gASgLMhouZ29vZ2xlLnByb3RvYnVmLlRpbWVz", "dGFtcBIVCg1jdXJyZW50X3ZhbHVlGBAgASgJEhMKC2xpbWl0X3ZhbHVlGBEg", "ASgJEiQKHG5hdGl2ZV9zb3VyY2VfY2Fub25pY2FsX25hbWUYEiABKAkSIQoZ", - "aXNfY29uZmlndXJlZF9wbGFjZWhvbGRlchgTIAEoCCKcAgoURGVidWdWaWV3", - "U25hcHNob3REdG8SHAoUaW5zdGFuY2VfdW5pcXVlX25hbWUYASABKAkSTAoQ", - "YXR0cmlidXRlX3ZhbHVlcxgCIAMoCzIyLnNjYWRhYnJpZGdlLnNpdGVjb21t", - "YW5kLnYxLkRlYnVnQXR0cmlidXRlVmFsdWVEdG8SRAoMYWxhcm1fc3RhdGVz", - "GAMgAygLMi4uc2NhZGFicmlkZ2Uuc2l0ZWNvbW1hbmQudjEuRGVidWdBbGFy", - "bVN0YXRlRHRvEjYKEnNuYXBzaG90X3RpbWVzdGFtcBgEIAEoCzIaLmdvb2ds", - "ZS5wcm90b2J1Zi5UaW1lc3RhbXASGgoSaW5zdGFuY2Vfbm90X2ZvdW5kGAUg", - "ASgIIvACCgxRdWVyeVJlcXVlc3QSTgoPZXZlbnRfbG9nX3F1ZXJ5GAEgASgL", - "MjMuc2NhZGFicmlkZ2Uuc2l0ZWNvbW1hbmQudjEuRXZlbnRMb2dRdWVyeVJl", - "cXVlc3REdG9IABJNCg5kZWJ1Z19zbmFwc2hvdBgCIAEoCzIzLnNjYWRhYnJp", - "ZGdlLnNpdGVjb21tYW5kLnYxLkRlYnVnU25hcHNob3RSZXF1ZXN0RHRvSAAS", - "WAoUc3Vic2NyaWJlX2RlYnVnX3ZpZXcYAyABKAsyOC5zY2FkYWJyaWRnZS5z", - "aXRlY29tbWFuZC52MS5TdWJzY3JpYmVEZWJ1Z1ZpZXdSZXF1ZXN0RHRvSAAS", - "XAoWdW5zdWJzY3JpYmVfZGVidWdfdmlldxgEIAEoCzI6LnNjYWRhYnJpZGdl", - "LnNpdGVjb21tYW5kLnYxLlVuc3Vic2NyaWJlRGVidWdWaWV3UmVxdWVzdER0", - "b0gAQgkKB2NvbW1hbmQikQIKClF1ZXJ5UmVwbHkSTwoPZXZlbnRfbG9nX3F1", - "ZXJ5GAEgASgLMjQuc2NhZGFicmlkZ2Uuc2l0ZWNvbW1hbmQudjEuRXZlbnRM", - "b2dRdWVyeVJlc3BvbnNlRHRvSAASTwoTZGVidWdfdmlld19zbmFwc2hvdBgC", - "IAEoCzIwLnNjYWRhYnJpZGdlLnNpdGVjb21tYW5kLnYxLkRlYnVnVmlld1Nu", - "YXBzaG90RHRvSAASWAoWdW5zdWJzY3JpYmVfZGVidWdfdmlldxgDIAEoCzI2", - "LnNjYWRhYnJpZGdlLnNpdGVjb21tYW5kLnYxLlVuc3Vic2NyaWJlRGVidWdW", - "aWV3QWNrRHRvSABCBwoFcmVwbHkingEKHFBhcmtlZE1lc3NhZ2VRdWVyeVJl", - "cXVlc3REdG8SFgoOY29ycmVsYXRpb25faWQYASABKAkSDwoHc2l0ZV9pZBgC", - "IAEoCRITCgtwYWdlX251bWJlchgDIAEoBRIRCglwYWdlX3NpemUYBCABKAUS", - "LQoJdGltZXN0YW1wGAUgASgLMhouZ29vZ2xlLnByb3RvYnVmLlRpbWVzdGFt", - "cCLyAgoVUGFya2VkTWVzc2FnZUVudHJ5RHRvEhIKCm1lc3NhZ2VfaWQYASAB", - "KAkSFQoNdGFyZ2V0X3N5c3RlbRgCIAEoCRITCgttZXRob2RfbmFtZRgDIAEo", - "CRIVCg1lcnJvcl9tZXNzYWdlGAQgASgJEhUKDWF0dGVtcHRfY291bnQYBSAB", - "KAUSNgoSb3JpZ2luYWxfdGltZXN0YW1wGAYgASgLMhouZ29vZ2xlLnByb3Rv", - "YnVmLlRpbWVzdGFtcBI6ChZsYXN0X2F0dGVtcHRfdGltZXN0YW1wGAcgASgL", - "MhouZ29vZ2xlLnByb3RvYnVmLlRpbWVzdGFtcBIUCgxtYXhfYXR0ZW1wdHMY", - "CCABKAUSSAoIY2F0ZWdvcnkYCSABKA4yNi5zY2FkYWJyaWRnZS5zaXRlY29t", - "bWFuZC52MS5TdG9yZUFuZEZvcndhcmRDYXRlZ29yeUR0bxIXCg9vcmlnaW5f", - "aW5zdGFuY2UYCiABKAkioQIKHVBhcmtlZE1lc3NhZ2VRdWVyeVJlc3BvbnNl", - "RHRvEhYKDmNvcnJlbGF0aW9uX2lkGAEgASgJEg8KB3NpdGVfaWQYAiABKAkS", - "QwoIbWVzc2FnZXMYAyADKAsyMS5zY2FkYWJyaWRnZS5zaXRlY29tbWFuZC52", - "MS5QYXJrZWRNZXNzYWdlRW50cnlEdG8SEwoLdG90YWxfY291bnQYBCABKAUS", - "EwoLcGFnZV9udW1iZXIYBSABKAUSEQoJcGFnZV9zaXplGAYgASgFEg8KB3N1", - "Y2Nlc3MYByABKAgSFQoNZXJyb3JfbWVzc2FnZRgIIAEoCRItCgl0aW1lc3Rh", - "bXAYCSABKAsyGi5nb29nbGUucHJvdG9idWYuVGltZXN0YW1wIooBChxQYXJr", - "ZWRNZXNzYWdlUmV0cnlSZXF1ZXN0RHRvEhYKDmNvcnJlbGF0aW9uX2lkGAEg", - "ASgJEg8KB3NpdGVfaWQYAiABKAkSEgoKbWVzc2FnZV9pZBgDIAEoCRItCgl0", - "aW1lc3RhbXAYBCABKAsyGi5nb29nbGUucHJvdG9idWYuVGltZXN0YW1wIl8K", - "HVBhcmtlZE1lc3NhZ2VSZXRyeVJlc3BvbnNlRHRvEhYKDmNvcnJlbGF0aW9u", - "X2lkGAEgASgJEg8KB3N1Y2Nlc3MYAiABKAgSFQoNZXJyb3JfbWVzc2FnZRgD", - "IAEoCSKMAQoeUGFya2VkTWVzc2FnZURpc2NhcmRSZXF1ZXN0RHRvEhYKDmNv", - "cnJlbGF0aW9uX2lkGAEgASgJEg8KB3NpdGVfaWQYAiABKAkSEgoKbWVzc2Fn", - "ZV9pZBgDIAEoCRItCgl0aW1lc3RhbXAYBCABKAsyGi5nb29nbGUucHJvdG9i", - "dWYuVGltZXN0YW1wImEKH1BhcmtlZE1lc3NhZ2VEaXNjYXJkUmVzcG9uc2VE", - "dG8SFgoOY29ycmVsYXRpb25faWQYASABKAkSDwoHc3VjY2VzcxgCIAEoCBIV", - "Cg1lcnJvcl9tZXNzYWdlGAMgASgJIk8KF1JldHJ5UGFya2VkT3BlcmF0aW9u", - "RHRvEhYKDmNvcnJlbGF0aW9uX2lkGAEgASgJEhwKFHRyYWNrZWRfb3BlcmF0", - "aW9uX2lkGAIgASgJIlEKGURpc2NhcmRQYXJrZWRPcGVyYXRpb25EdG8SFgoO", - "Y29ycmVsYXRpb25faWQYASABKAkSHAoUdHJhY2tlZF9vcGVyYXRpb25faWQY", - "AiABKAkiXQobUGFya2VkT3BlcmF0aW9uQWN0aW9uQWNrRHRvEhYKDmNvcnJl", - "bGF0aW9uX2lkGAEgASgJEg8KB2FwcGxpZWQYAiABKAgSFQoNZXJyb3JfbWVz", - "c2FnZRgDIAEoCSLeAwoNUGFya2VkUmVxdWVzdBJYChRwYXJrZWRfbWVzc2Fn", - "ZV9xdWVyeRgBIAEoCzI4LnNjYWRhYnJpZGdlLnNpdGVjb21tYW5kLnYxLlBh", - "cmtlZE1lc3NhZ2VRdWVyeVJlcXVlc3REdG9IABJYChRwYXJrZWRfbWVzc2Fn", - "ZV9yZXRyeRgCIAEoCzI4LnNjYWRhYnJpZGdlLnNpdGVjb21tYW5kLnYxLlBh", - "cmtlZE1lc3NhZ2VSZXRyeVJlcXVlc3REdG9IABJcChZwYXJrZWRfbWVzc2Fn", - "ZV9kaXNjYXJkGAMgASgLMjouc2NhZGFicmlkZ2Uuc2l0ZWNvbW1hbmQudjEu", - "UGFya2VkTWVzc2FnZURpc2NhcmRSZXF1ZXN0RHRvSAASVQoWcmV0cnlfcGFy", - "a2VkX29wZXJhdGlvbhgEIAEoCzIzLnNjYWRhYnJpZGdlLnNpdGVjb21tYW5k", - "LnYxLlJldHJ5UGFya2VkT3BlcmF0aW9uRHRvSAASWQoYZGlzY2FyZF9wYXJr", - "ZWRfb3BlcmF0aW9uGAUgASgLMjUuc2NhZGFicmlkZ2Uuc2l0ZWNvbW1hbmQu", - "djEuRGlzY2FyZFBhcmtlZE9wZXJhdGlvbkR0b0gAQgkKB2NvbW1hbmQihwMK", - "C1BhcmtlZFJlcGx5ElkKFHBhcmtlZF9tZXNzYWdlX3F1ZXJ5GAEgASgLMjku", - "c2NhZGFicmlkZ2Uuc2l0ZWNvbW1hbmQudjEuUGFya2VkTWVzc2FnZVF1ZXJ5", - "UmVzcG9uc2VEdG9IABJZChRwYXJrZWRfbWVzc2FnZV9yZXRyeRgCIAEoCzI5", - "LnNjYWRhYnJpZGdlLnNpdGVjb21tYW5kLnYxLlBhcmtlZE1lc3NhZ2VSZXRy", - "eVJlc3BvbnNlRHRvSAASXQoWcGFya2VkX21lc3NhZ2VfZGlzY2FyZBgDIAEo", - "CzI7LnNjYWRhYnJpZGdlLnNpdGVjb21tYW5kLnYxLlBhcmtlZE1lc3NhZ2VE", - "aXNjYXJkUmVzcG9uc2VEdG9IABJaChdwYXJrZWRfb3BlcmF0aW9uX2FjdGlv", - "bhgEIAEoCzI3LnNjYWRhYnJpZGdlLnNpdGVjb21tYW5kLnYxLlBhcmtlZE9w", - "ZXJhdGlvbkFjdGlvbkFja0R0b0gAQgcKBXJlcGx5IvwBChVSb3V0ZVRvQ2Fs", - "bFJlcXVlc3REdG8SFgoOY29ycmVsYXRpb25faWQYASABKAkSHAoUaW5zdGFu", - "Y2VfdW5pcXVlX25hbWUYAiABKAkSEwoLc2NyaXB0X25hbWUYAyABKAkSPQoK", - "cGFyYW1ldGVycxgEIAEoCzIpLnNjYWRhYnJpZGdlLnNpdGVjb21tYW5kLnYx", - "Lkxvb3NlVmFsdWVNYXASLQoJdGltZXN0YW1wGAUgASgLMhouZ29vZ2xlLnBy", - "b3RvYnVmLlRpbWVzdGFtcBIbChNwYXJlbnRfZXhlY3V0aW9uX2lkGAYgASgJ", - "Eg0KBXRyYWNlGAcgASgIIpICChZSb3V0ZVRvQ2FsbFJlc3BvbnNlRHRvEhYK", - "DmNvcnJlbGF0aW9uX2lkGAEgASgJEg8KB3N1Y2Nlc3MYAiABKAgSPAoMcmV0", - "dXJuX3ZhbHVlGAMgASgLMiYuc2NhZGFicmlkZ2Uuc2l0ZWNvbW1hbmQudjEu", - "TG9vc2VWYWx1ZRIVCg1lcnJvcl9tZXNzYWdlGAQgASgJEi0KCXRpbWVzdGFt", - "cBgFIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXASGgoSY2hpbGRf", - "ZXhlY3V0aW9uX2lkGAYgASgJEi8KDHRyYWNlX2V2ZW50cxgHIAMoCzIZLnNp", - "dGVzdHJlYW0uQXVkaXRFdmVudER0byK7AQoeUm91dGVUb0dldEF0dHJpYnV0", - "ZXNSZXF1ZXN0RHRvEhYKDmNvcnJlbGF0aW9uX2lkGAEgASgJEhwKFGluc3Rh", - "bmNlX3VuaXF1ZV9uYW1lGAIgASgJEhcKD2F0dHJpYnV0ZV9uYW1lcxgDIAMo", - "CRItCgl0aW1lc3RhbXAYBCABKAsyGi5nb29nbGUucHJvdG9idWYuVGltZXN0", - "YW1wEhsKE3BhcmVudF9leGVjdXRpb25faWQYBSABKAkiywEKH1JvdXRlVG9H", - "ZXRBdHRyaWJ1dGVzUmVzcG9uc2VEdG8SFgoOY29ycmVsYXRpb25faWQYASAB", - "KAkSOQoGdmFsdWVzGAIgASgLMikuc2NhZGFicmlkZ2Uuc2l0ZWNvbW1hbmQu", - "djEuTG9vc2VWYWx1ZU1hcBIPCgdzdWNjZXNzGAMgASgIEhUKDWVycm9yX21l", - "c3NhZ2UYBCABKAkSLQoJdGltZXN0YW1wGAUgASgLMhouZ29vZ2xlLnByb3Rv", - "YnVmLlRpbWVzdGFtcCLUAgoeUm91dGVUb1NldEF0dHJpYnV0ZXNSZXF1ZXN0", - "RHRvEhYKDmNvcnJlbGF0aW9uX2lkGAEgASgJEhwKFGluc3RhbmNlX3VuaXF1", - "ZV9uYW1lGAIgASgJEmkKEGF0dHJpYnV0ZV92YWx1ZXMYAyADKAsyTy5zY2Fk", - "YWJyaWRnZS5zaXRlY29tbWFuZC52MS5Sb3V0ZVRvU2V0QXR0cmlidXRlc1Jl", - "cXVlc3REdG8uQXR0cmlidXRlVmFsdWVzRW50cnkSLQoJdGltZXN0YW1wGAQg", - "ASgLMhouZ29vZ2xlLnByb3RvYnVmLlRpbWVzdGFtcBIbChNwYXJlbnRfZXhl", - "Y3V0aW9uX2lkGAUgASgJEg0KBXRyYWNlGAYgASgIGjYKFEF0dHJpYnV0ZVZh", - "bHVlc0VudHJ5EgsKA2tleRgBIAEoCRINCgV2YWx1ZRgCIAEoCToCOAEikAEK", - "H1JvdXRlVG9TZXRBdHRyaWJ1dGVzUmVzcG9uc2VEdG8SFgoOY29ycmVsYXRp", - "b25faWQYASABKAkSDwoHc3VjY2VzcxgCIAEoCBIVCg1lcnJvcl9tZXNzYWdl", - "GAMgASgJEi0KCXRpbWVzdGFtcBgEIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5U", - "aW1lc3RhbXAiwwIKIVJvdXRlVG9XYWl0Rm9yQXR0cmlidXRlUmVxdWVzdER0", - "bxIWCg5jb3JyZWxhdGlvbl9pZBgBIAEoCRIcChRpbnN0YW5jZV91bmlxdWVf", - "bmFtZRgCIAEoCRIWCg5hdHRyaWJ1dGVfbmFtZRgDIAEoCRI6ChR0YXJnZXRf", - "dmFsdWVfZW5jb2RlZBgEIAEoCzIcLmdvb2dsZS5wcm90b2J1Zi5TdHJpbmdW", - "YWx1ZRIqCgd0aW1lb3V0GAUgASgLMhkuZ29vZ2xlLnByb3RvYnVmLkR1cmF0", - "aW9uEi0KCXRpbWVzdGFtcBgGIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1l", - "c3RhbXASGwoTcGFyZW50X2V4ZWN1dGlvbl9pZBgHIAEoCRIcChRyZXF1aXJl", - "X2dvb2RfcXVhbGl0eRgIIAEoCCL/AQoiUm91dGVUb1dhaXRGb3JBdHRyaWJ1", - "dGVSZXNwb25zZUR0bxIWCg5jb3JyZWxhdGlvbl9pZBgBIAEoCRIPCgdtYXRj", - "aGVkGAIgASgIEjUKBXZhbHVlGAMgASgLMiYuc2NhZGFicmlkZ2Uuc2l0ZWNv", - "bW1hbmQudjEuTG9vc2VWYWx1ZRIPCgdxdWFsaXR5GAQgASgJEhEKCXRpbWVk", - "X291dBgFIAEoCBIPCgdzdWNjZXNzGAYgASgIEhUKDWVycm9yX21lc3NhZ2UY", - "ByABKAkSLQoJdGltZXN0YW1wGAggASgLMhouZ29vZ2xlLnByb3RvYnVmLlRp", - "bWVzdGFtcCKJAwoMUm91dGVSZXF1ZXN0EkoKDXJvdXRlX3RvX2NhbGwYASAB", - "KAsyMS5zY2FkYWJyaWRnZS5zaXRlY29tbWFuZC52MS5Sb3V0ZVRvQ2FsbFJl", - "cXVlc3REdG9IABJdChdyb3V0ZV90b19nZXRfYXR0cmlidXRlcxgCIAEoCzI6", - "LnNjYWRhYnJpZGdlLnNpdGVjb21tYW5kLnYxLlJvdXRlVG9HZXRBdHRyaWJ1", - "dGVzUmVxdWVzdER0b0gAEl0KF3JvdXRlX3RvX3NldF9hdHRyaWJ1dGVzGAMg", - "ASgLMjouc2NhZGFicmlkZ2Uuc2l0ZWNvbW1hbmQudjEuUm91dGVUb1NldEF0", - "dHJpYnV0ZXNSZXF1ZXN0RHRvSAASZAobcm91dGVfdG9fd2FpdF9mb3JfYXR0", - "cmlidXRlGAQgASgLMj0uc2NhZGFicmlkZ2Uuc2l0ZWNvbW1hbmQudjEuUm91", - "dGVUb1dhaXRGb3JBdHRyaWJ1dGVSZXF1ZXN0RHRvSABCCQoHY29tbWFuZCKJ", - "AwoKUm91dGVSZXBseRJLCg1yb3V0ZV90b19jYWxsGAEgASgLMjIuc2NhZGFi", - "cmlkZ2Uuc2l0ZWNvbW1hbmQudjEuUm91dGVUb0NhbGxSZXNwb25zZUR0b0gA", - "El4KF3JvdXRlX3RvX2dldF9hdHRyaWJ1dGVzGAIgASgLMjsuc2NhZGFicmlk", - "Z2Uuc2l0ZWNvbW1hbmQudjEuUm91dGVUb0dldEF0dHJpYnV0ZXNSZXNwb25z", - "ZUR0b0gAEl4KF3JvdXRlX3RvX3NldF9hdHRyaWJ1dGVzGAMgASgLMjsuc2Nh", - "ZGFicmlkZ2Uuc2l0ZWNvbW1hbmQudjEuUm91dGVUb1NldEF0dHJpYnV0ZXNS", - "ZXNwb25zZUR0b0gAEmUKG3JvdXRlX3RvX3dhaXRfZm9yX2F0dHJpYnV0ZRgE", - "IAEoCzI+LnNjYWRhYnJpZGdlLnNpdGVjb21tYW5kLnYxLlJvdXRlVG9XYWl0", - "Rm9yQXR0cmlidXRlUmVzcG9uc2VEdG9IAEIHCgVyZXBseSJBChZUcmlnZ2Vy", - "U2l0ZUZhaWxvdmVyRHRvEhYKDmNvcnJlbGF0aW9uX2lkGAEgASgJEg8KB3Np", - "dGVfaWQYAiABKAkibQoSU2l0ZUZhaWxvdmVyQWNrRHRvEhYKDmNvcnJlbGF0", - "aW9uX2lkGAEgASgJEhAKCGFjY2VwdGVkGAIgASgIEhYKDnRhcmdldF9hZGRy", - "ZXNzGAMgASgJEhUKDWVycm9yX21lc3NhZ2UYBCABKAkqywEKE0RlcGxveW1l", - "bnRTdGF0dXNEdG8SJQohREVQTE9ZTUVOVF9TVEFUVVNfRFRPX1VOU1BFQ0lG", - "SUVEEAASIQodREVQTE9ZTUVOVF9TVEFUVVNfRFRPX1BFTkRJTkcQARIlCiFE", - "RVBMT1lNRU5UX1NUQVRVU19EVE9fSU5fUFJPR1JFU1MQAhIhCh1ERVBMT1lN", - "RU5UX1NUQVRVU19EVE9fU1VDQ0VTUxADEiAKHERFUExPWU1FTlRfU1RBVFVT", - "X0RUT19GQUlMRUQQBCrEAQoSQnJvd3NlTm9kZUNsYXNzRHRvEiUKIUJST1dT", - "RV9OT0RFX0NMQVNTX0RUT19VTlNQRUNJRklFRBAAEiAKHEJST1dTRV9OT0RF", - "X0NMQVNTX0RUT19PQkpFQ1QQARIiCh5CUk9XU0VfTk9ERV9DTEFTU19EVE9f", - "VkFSSUFCTEUQAhIgChxCUk9XU0VfTk9ERV9DTEFTU19EVE9fTUVUSE9EEAMS", - "HwobQlJPV1NFX05PREVfQ0xBU1NfRFRPX09USEVSEAQqoQIKFEJyb3dzZUZh", - "aWx1cmVLaW5kRHRvEicKI0JST1dTRV9GQUlMVVJFX0tJTkRfRFRPX1VOU1BF", - "Q0lGSUVEEAASMAosQlJPV1NFX0ZBSUxVUkVfS0lORF9EVE9fQ09OTkVDVElP", - "Tl9OT1RfRk9VTkQQARI0CjBCUk9XU0VfRkFJTFVSRV9LSU5EX0RUT19DT05O", - "RUNUSU9OX05PVF9DT05ORUNURUQQAhIpCiVCUk9XU0VfRkFJTFVSRV9LSU5E", - "X0RUT19OT1RfQlJPV1NBQkxFEAMSIwofQlJPV1NFX0ZBSUxVUkVfS0lORF9E", - "VE9fVElNRU9VVBAEEigKJEJST1dTRV9GQUlMVVJFX0tJTkRfRFRPX1NFUlZF", - "Ul9FUlJPUhAFKqoCChtSZWFkVGFnVmFsdWVzRmFpbHVyZUtpbmREdG8SMAos", - "UkVBRF9UQUdfVkFMVUVTX0ZBSUxVUkVfS0lORF9EVE9fVU5TUEVDSUZJRUQQ", - "ABI5CjVSRUFEX1RBR19WQUxVRVNfRkFJTFVSRV9LSU5EX0RUT19DT05ORUNU", - "SU9OX05PVF9GT1VORBABEj0KOVJFQURfVEFHX1ZBTFVFU19GQUlMVVJFX0tJ", - "TkRfRFRPX0NPTk5FQ1RJT05fTk9UX0NPTk5FQ1RFRBACEiwKKFJFQURfVEFH", - "X1ZBTFVFU19GQUlMVVJFX0tJTkRfRFRPX1RJTUVPVVQQAxIxCi1SRUFEX1RB", - "R19WQUxVRVNfRkFJTFVSRV9LSU5EX0RUT19TRVJWRVJfRVJST1IQBCqTAgoU", - "VmVyaWZ5RmFpbHVyZUtpbmREdG8SJwojVkVSSUZZX0ZBSUxVUkVfS0lORF9E", - "VE9fVU5TUEVDSUZJRUQQABInCiNWRVJJRllfRkFJTFVSRV9LSU5EX0RUT19V", - "TlJFQUNIQUJMRRABEicKI1ZFUklGWV9GQUlMVVJFX0tJTkRfRFRPX0FVVEhf", - "RkFJTEVEEAISMQotVkVSSUZZX0ZBSUxVUkVfS0lORF9EVE9fVU5UUlVTVEVE", - "X0NFUlRJRklDQVRFEAMSIwofVkVSSUZZX0ZBSUxVUkVfS0lORF9EVE9fVElN", - "RU9VVBAEEigKJFZFUklGWV9GQUlMVVJFX0tJTkRfRFRPX1NFUlZFUl9FUlJP", - "UhAFKuUBChpTdG9yZUFuZEZvcndhcmRDYXRlZ29yeUR0bxIuCipTVE9SRV9B", - "TkRfRk9SV0FSRF9DQVRFR09SWV9EVE9fVU5TUEVDSUZJRUQQABIyCi5TVE9S", - "RV9BTkRfRk9SV0FSRF9DQVRFR09SWV9EVE9fRVhURVJOQUxfU1lTVEVNEAES", - "LworU1RPUkVfQU5EX0ZPUldBUkRfQ0FURUdPUllfRFRPX05PVElGSUNBVElP", - "ThACEjIKLlNUT1JFX0FORF9GT1JXQVJEX0NBVEVHT1JZX0RUT19DQUNIRURf", - "REJfV1JJVEUQAypoCg1BbGFybVN0YXRlRHRvEh8KG0FMQVJNX1NUQVRFX0RU", - "T19VTlNQRUNJRklFRBAAEhoKFkFMQVJNX1NUQVRFX0RUT19BQ1RJVkUQARIa", - "ChZBTEFSTV9TVEFURV9EVE9fTk9STUFMEAIquQEKDUFsYXJtTGV2ZWxEdG8S", - "HwobQUxBUk1fTEVWRUxfRFRPX1VOU1BFQ0lGSUVEEAASGAoUQUxBUk1fTEVW", - "RUxfRFRPX05PTkUQARIXChNBTEFSTV9MRVZFTF9EVE9fTE9XEAISGwoXQUxB", - "Uk1fTEVWRUxfRFRPX0xPV19MT1cQAxIYChRBTEFSTV9MRVZFTF9EVE9fSElH", - "SBAEEh0KGUFMQVJNX0xFVkVMX0RUT19ISUdIX0hJR0gQBSqSAQoMQWxhcm1L", - "aW5kRHRvEh4KGkFMQVJNX0tJTkRfRFRPX1VOU1BFQ0lGSUVEEAASGwoXQUxB", - "Uk1fS0lORF9EVE9fQ09NUFVURUQQARIgChxBTEFSTV9LSU5EX0RUT19OQVRJ", - "VkVfT1BDX1VBEAISIwofQUxBUk1fS0lORF9EVE9fTkFUSVZFX01YX0FDQ0VT", - "UxADKugBChNBbGFybVNoZWx2ZVN0YXRlRHRvEiYKIkFMQVJNX1NIRUxWRV9T", - "VEFURV9EVE9fVU5TUEVDSUZJRUQQABIkCiBBTEFSTV9TSEVMVkVfU1RBVEVf", - "RFRPX1VOU0hFTFZFRBABEisKJ0FMQVJNX1NIRUxWRV9TVEFURV9EVE9fT05F", - "X1NIT1RfU0hFTFZFRBACEigKJEFMQVJNX1NIRUxWRV9TVEFURV9EVE9fVElN", - "RURfU0hFTFZFRBADEiwKKEFMQVJNX1NIRUxWRV9TVEFURV9EVE9fUEVSTUFO", - "RU5UX1NIRUxWRUQQBDKEBQoSU2l0ZUNvbW1hbmRTZXJ2aWNlEmwKEEV4ZWN1", - "dGVMaWZlY3ljbGUSLC5zY2FkYWJyaWRnZS5zaXRlY29tbWFuZC52MS5MaWZl", - "Y3ljbGVSZXF1ZXN0Giouc2NhZGFicmlkZ2Uuc2l0ZWNvbW1hbmQudjEuTGlm", - "ZWN5Y2xlUmVwbHkSYAoMRXhlY3V0ZU9wY1VhEiguc2NhZGFicmlkZ2Uuc2l0", - "ZWNvbW1hbmQudjEuT3BjVWFSZXF1ZXN0GiYuc2NhZGFicmlkZ2Uuc2l0ZWNv", - "bW1hbmQudjEuT3BjVWFSZXBseRJgCgxFeGVjdXRlUXVlcnkSKC5zY2FkYWJy", - "aWRnZS5zaXRlY29tbWFuZC52MS5RdWVyeVJlcXVlc3QaJi5zY2FkYWJyaWRn", - "ZS5zaXRlY29tbWFuZC52MS5RdWVyeVJlcGx5EmMKDUV4ZWN1dGVQYXJrZWQS", - "KS5zY2FkYWJyaWRnZS5zaXRlY29tbWFuZC52MS5QYXJrZWRSZXF1ZXN0Gicu", - "c2NhZGFicmlkZ2Uuc2l0ZWNvbW1hbmQudjEuUGFya2VkUmVwbHkSYAoMRXhl", - "Y3V0ZVJvdXRlEiguc2NhZGFicmlkZ2Uuc2l0ZWNvbW1hbmQudjEuUm91dGVS", - "ZXF1ZXN0GiYuc2NhZGFicmlkZ2Uuc2l0ZWNvbW1hbmQudjEuUm91dGVSZXBs", - "eRJ1Cg9UcmlnZ2VyRmFpbG92ZXISMi5zY2FkYWJyaWRnZS5zaXRlY29tbWFu", - "ZC52MS5UcmlnZ2VyU2l0ZUZhaWxvdmVyRHRvGi4uc2NhZGFicmlkZ2Uuc2l0", - "ZWNvbW1hbmQudjEuU2l0ZUZhaWxvdmVyQWNrRHRvQiuqAihaQi5NT00uV1cu", - "U2NhZGFCcmlkZ2UuQ29tbXVuaWNhdGlvbi5HcnBjYgZwcm90bzM=")); + "aXNfY29uZmlndXJlZF9wbGFjZWhvbGRlchgTIAEoCBIZChFpc19tZXNfcmVw", + "b3J0YWJsZRgUIAEoCCKcAgoURGVidWdWaWV3U25hcHNob3REdG8SHAoUaW5z", + "dGFuY2VfdW5pcXVlX25hbWUYASABKAkSTAoQYXR0cmlidXRlX3ZhbHVlcxgC", + "IAMoCzIyLnNjYWRhYnJpZGdlLnNpdGVjb21tYW5kLnYxLkRlYnVnQXR0cmli", + "dXRlVmFsdWVEdG8SRAoMYWxhcm1fc3RhdGVzGAMgAygLMi4uc2NhZGFicmlk", + "Z2Uuc2l0ZWNvbW1hbmQudjEuRGVidWdBbGFybVN0YXRlRHRvEjYKEnNuYXBz", + "aG90X3RpbWVzdGFtcBgEIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3Rh", + "bXASGgoSaW5zdGFuY2Vfbm90X2ZvdW5kGAUgASgIIvACCgxRdWVyeVJlcXVl", + "c3QSTgoPZXZlbnRfbG9nX3F1ZXJ5GAEgASgLMjMuc2NhZGFicmlkZ2Uuc2l0", + "ZWNvbW1hbmQudjEuRXZlbnRMb2dRdWVyeVJlcXVlc3REdG9IABJNCg5kZWJ1", + "Z19zbmFwc2hvdBgCIAEoCzIzLnNjYWRhYnJpZGdlLnNpdGVjb21tYW5kLnYx", + "LkRlYnVnU25hcHNob3RSZXF1ZXN0RHRvSAASWAoUc3Vic2NyaWJlX2RlYnVn", + "X3ZpZXcYAyABKAsyOC5zY2FkYWJyaWRnZS5zaXRlY29tbWFuZC52MS5TdWJz", + "Y3JpYmVEZWJ1Z1ZpZXdSZXF1ZXN0RHRvSAASXAoWdW5zdWJzY3JpYmVfZGVi", + "dWdfdmlldxgEIAEoCzI6LnNjYWRhYnJpZGdlLnNpdGVjb21tYW5kLnYxLlVu", + "c3Vic2NyaWJlRGVidWdWaWV3UmVxdWVzdER0b0gAQgkKB2NvbW1hbmQikQIK", + "ClF1ZXJ5UmVwbHkSTwoPZXZlbnRfbG9nX3F1ZXJ5GAEgASgLMjQuc2NhZGFi", + "cmlkZ2Uuc2l0ZWNvbW1hbmQudjEuRXZlbnRMb2dRdWVyeVJlc3BvbnNlRHRv", + "SAASTwoTZGVidWdfdmlld19zbmFwc2hvdBgCIAEoCzIwLnNjYWRhYnJpZGdl", + "LnNpdGVjb21tYW5kLnYxLkRlYnVnVmlld1NuYXBzaG90RHRvSAASWAoWdW5z", + "dWJzY3JpYmVfZGVidWdfdmlldxgDIAEoCzI2LnNjYWRhYnJpZGdlLnNpdGVj", + "b21tYW5kLnYxLlVuc3Vic2NyaWJlRGVidWdWaWV3QWNrRHRvSABCBwoFcmVw", + "bHkingEKHFBhcmtlZE1lc3NhZ2VRdWVyeVJlcXVlc3REdG8SFgoOY29ycmVs", + "YXRpb25faWQYASABKAkSDwoHc2l0ZV9pZBgCIAEoCRITCgtwYWdlX251bWJl", + "chgDIAEoBRIRCglwYWdlX3NpemUYBCABKAUSLQoJdGltZXN0YW1wGAUgASgL", + "MhouZ29vZ2xlLnByb3RvYnVmLlRpbWVzdGFtcCLyAgoVUGFya2VkTWVzc2Fn", + "ZUVudHJ5RHRvEhIKCm1lc3NhZ2VfaWQYASABKAkSFQoNdGFyZ2V0X3N5c3Rl", + "bRgCIAEoCRITCgttZXRob2RfbmFtZRgDIAEoCRIVCg1lcnJvcl9tZXNzYWdl", + "GAQgASgJEhUKDWF0dGVtcHRfY291bnQYBSABKAUSNgoSb3JpZ2luYWxfdGlt", + "ZXN0YW1wGAYgASgLMhouZ29vZ2xlLnByb3RvYnVmLlRpbWVzdGFtcBI6ChZs", + "YXN0X2F0dGVtcHRfdGltZXN0YW1wGAcgASgLMhouZ29vZ2xlLnByb3RvYnVm", + "LlRpbWVzdGFtcBIUCgxtYXhfYXR0ZW1wdHMYCCABKAUSSAoIY2F0ZWdvcnkY", + "CSABKA4yNi5zY2FkYWJyaWRnZS5zaXRlY29tbWFuZC52MS5TdG9yZUFuZEZv", + "cndhcmRDYXRlZ29yeUR0bxIXCg9vcmlnaW5faW5zdGFuY2UYCiABKAkioQIK", + "HVBhcmtlZE1lc3NhZ2VRdWVyeVJlc3BvbnNlRHRvEhYKDmNvcnJlbGF0aW9u", + "X2lkGAEgASgJEg8KB3NpdGVfaWQYAiABKAkSQwoIbWVzc2FnZXMYAyADKAsy", + "MS5zY2FkYWJyaWRnZS5zaXRlY29tbWFuZC52MS5QYXJrZWRNZXNzYWdlRW50", + "cnlEdG8SEwoLdG90YWxfY291bnQYBCABKAUSEwoLcGFnZV9udW1iZXIYBSAB", + "KAUSEQoJcGFnZV9zaXplGAYgASgFEg8KB3N1Y2Nlc3MYByABKAgSFQoNZXJy", + "b3JfbWVzc2FnZRgIIAEoCRItCgl0aW1lc3RhbXAYCSABKAsyGi5nb29nbGUu", + "cHJvdG9idWYuVGltZXN0YW1wIooBChxQYXJrZWRNZXNzYWdlUmV0cnlSZXF1", + "ZXN0RHRvEhYKDmNvcnJlbGF0aW9uX2lkGAEgASgJEg8KB3NpdGVfaWQYAiAB", + "KAkSEgoKbWVzc2FnZV9pZBgDIAEoCRItCgl0aW1lc3RhbXAYBCABKAsyGi5n", + "b29nbGUucHJvdG9idWYuVGltZXN0YW1wIl8KHVBhcmtlZE1lc3NhZ2VSZXRy", + "eVJlc3BvbnNlRHRvEhYKDmNvcnJlbGF0aW9uX2lkGAEgASgJEg8KB3N1Y2Nl", + "c3MYAiABKAgSFQoNZXJyb3JfbWVzc2FnZRgDIAEoCSKMAQoeUGFya2VkTWVz", + "c2FnZURpc2NhcmRSZXF1ZXN0RHRvEhYKDmNvcnJlbGF0aW9uX2lkGAEgASgJ", + "Eg8KB3NpdGVfaWQYAiABKAkSEgoKbWVzc2FnZV9pZBgDIAEoCRItCgl0aW1l", + "c3RhbXAYBCABKAsyGi5nb29nbGUucHJvdG9idWYuVGltZXN0YW1wImEKH1Bh", + "cmtlZE1lc3NhZ2VEaXNjYXJkUmVzcG9uc2VEdG8SFgoOY29ycmVsYXRpb25f", + "aWQYASABKAkSDwoHc3VjY2VzcxgCIAEoCBIVCg1lcnJvcl9tZXNzYWdlGAMg", + "ASgJIk8KF1JldHJ5UGFya2VkT3BlcmF0aW9uRHRvEhYKDmNvcnJlbGF0aW9u", + "X2lkGAEgASgJEhwKFHRyYWNrZWRfb3BlcmF0aW9uX2lkGAIgASgJIlEKGURp", + "c2NhcmRQYXJrZWRPcGVyYXRpb25EdG8SFgoOY29ycmVsYXRpb25faWQYASAB", + "KAkSHAoUdHJhY2tlZF9vcGVyYXRpb25faWQYAiABKAkiXQobUGFya2VkT3Bl", + "cmF0aW9uQWN0aW9uQWNrRHRvEhYKDmNvcnJlbGF0aW9uX2lkGAEgASgJEg8K", + "B2FwcGxpZWQYAiABKAgSFQoNZXJyb3JfbWVzc2FnZRgDIAEoCSLeAwoNUGFy", + "a2VkUmVxdWVzdBJYChRwYXJrZWRfbWVzc2FnZV9xdWVyeRgBIAEoCzI4LnNj", + "YWRhYnJpZGdlLnNpdGVjb21tYW5kLnYxLlBhcmtlZE1lc3NhZ2VRdWVyeVJl", + "cXVlc3REdG9IABJYChRwYXJrZWRfbWVzc2FnZV9yZXRyeRgCIAEoCzI4LnNj", + "YWRhYnJpZGdlLnNpdGVjb21tYW5kLnYxLlBhcmtlZE1lc3NhZ2VSZXRyeVJl", + "cXVlc3REdG9IABJcChZwYXJrZWRfbWVzc2FnZV9kaXNjYXJkGAMgASgLMjou", + "c2NhZGFicmlkZ2Uuc2l0ZWNvbW1hbmQudjEuUGFya2VkTWVzc2FnZURpc2Nh", + "cmRSZXF1ZXN0RHRvSAASVQoWcmV0cnlfcGFya2VkX29wZXJhdGlvbhgEIAEo", + "CzIzLnNjYWRhYnJpZGdlLnNpdGVjb21tYW5kLnYxLlJldHJ5UGFya2VkT3Bl", + "cmF0aW9uRHRvSAASWQoYZGlzY2FyZF9wYXJrZWRfb3BlcmF0aW9uGAUgASgL", + "MjUuc2NhZGFicmlkZ2Uuc2l0ZWNvbW1hbmQudjEuRGlzY2FyZFBhcmtlZE9w", + "ZXJhdGlvbkR0b0gAQgkKB2NvbW1hbmQihwMKC1BhcmtlZFJlcGx5ElkKFHBh", + "cmtlZF9tZXNzYWdlX3F1ZXJ5GAEgASgLMjkuc2NhZGFicmlkZ2Uuc2l0ZWNv", + "bW1hbmQudjEuUGFya2VkTWVzc2FnZVF1ZXJ5UmVzcG9uc2VEdG9IABJZChRw", + "YXJrZWRfbWVzc2FnZV9yZXRyeRgCIAEoCzI5LnNjYWRhYnJpZGdlLnNpdGVj", + "b21tYW5kLnYxLlBhcmtlZE1lc3NhZ2VSZXRyeVJlc3BvbnNlRHRvSAASXQoW", + "cGFya2VkX21lc3NhZ2VfZGlzY2FyZBgDIAEoCzI7LnNjYWRhYnJpZGdlLnNp", + "dGVjb21tYW5kLnYxLlBhcmtlZE1lc3NhZ2VEaXNjYXJkUmVzcG9uc2VEdG9I", + "ABJaChdwYXJrZWRfb3BlcmF0aW9uX2FjdGlvbhgEIAEoCzI3LnNjYWRhYnJp", + "ZGdlLnNpdGVjb21tYW5kLnYxLlBhcmtlZE9wZXJhdGlvbkFjdGlvbkFja0R0", + "b0gAQgcKBXJlcGx5IvwBChVSb3V0ZVRvQ2FsbFJlcXVlc3REdG8SFgoOY29y", + "cmVsYXRpb25faWQYASABKAkSHAoUaW5zdGFuY2VfdW5pcXVlX25hbWUYAiAB", + "KAkSEwoLc2NyaXB0X25hbWUYAyABKAkSPQoKcGFyYW1ldGVycxgEIAEoCzIp", + "LnNjYWRhYnJpZGdlLnNpdGVjb21tYW5kLnYxLkxvb3NlVmFsdWVNYXASLQoJ", + "dGltZXN0YW1wGAUgASgLMhouZ29vZ2xlLnByb3RvYnVmLlRpbWVzdGFtcBIb", + "ChNwYXJlbnRfZXhlY3V0aW9uX2lkGAYgASgJEg0KBXRyYWNlGAcgASgIIpIC", + "ChZSb3V0ZVRvQ2FsbFJlc3BvbnNlRHRvEhYKDmNvcnJlbGF0aW9uX2lkGAEg", + "ASgJEg8KB3N1Y2Nlc3MYAiABKAgSPAoMcmV0dXJuX3ZhbHVlGAMgASgLMiYu", + "c2NhZGFicmlkZ2Uuc2l0ZWNvbW1hbmQudjEuTG9vc2VWYWx1ZRIVCg1lcnJv", + "cl9tZXNzYWdlGAQgASgJEi0KCXRpbWVzdGFtcBgFIAEoCzIaLmdvb2dsZS5w", + "cm90b2J1Zi5UaW1lc3RhbXASGgoSY2hpbGRfZXhlY3V0aW9uX2lkGAYgASgJ", + "Ei8KDHRyYWNlX2V2ZW50cxgHIAMoCzIZLnNpdGVzdHJlYW0uQXVkaXRFdmVu", + "dER0byK7AQoeUm91dGVUb0dldEF0dHJpYnV0ZXNSZXF1ZXN0RHRvEhYKDmNv", + "cnJlbGF0aW9uX2lkGAEgASgJEhwKFGluc3RhbmNlX3VuaXF1ZV9uYW1lGAIg", + "ASgJEhcKD2F0dHJpYnV0ZV9uYW1lcxgDIAMoCRItCgl0aW1lc3RhbXAYBCAB", + "KAsyGi5nb29nbGUucHJvdG9idWYuVGltZXN0YW1wEhsKE3BhcmVudF9leGVj", + "dXRpb25faWQYBSABKAkiywEKH1JvdXRlVG9HZXRBdHRyaWJ1dGVzUmVzcG9u", + "c2VEdG8SFgoOY29ycmVsYXRpb25faWQYASABKAkSOQoGdmFsdWVzGAIgASgL", + "Mikuc2NhZGFicmlkZ2Uuc2l0ZWNvbW1hbmQudjEuTG9vc2VWYWx1ZU1hcBIP", + "CgdzdWNjZXNzGAMgASgIEhUKDWVycm9yX21lc3NhZ2UYBCABKAkSLQoJdGlt", + "ZXN0YW1wGAUgASgLMhouZ29vZ2xlLnByb3RvYnVmLlRpbWVzdGFtcCLUAgoe", + "Um91dGVUb1NldEF0dHJpYnV0ZXNSZXF1ZXN0RHRvEhYKDmNvcnJlbGF0aW9u", + "X2lkGAEgASgJEhwKFGluc3RhbmNlX3VuaXF1ZV9uYW1lGAIgASgJEmkKEGF0", + "dHJpYnV0ZV92YWx1ZXMYAyADKAsyTy5zY2FkYWJyaWRnZS5zaXRlY29tbWFu", + "ZC52MS5Sb3V0ZVRvU2V0QXR0cmlidXRlc1JlcXVlc3REdG8uQXR0cmlidXRl", + "VmFsdWVzRW50cnkSLQoJdGltZXN0YW1wGAQgASgLMhouZ29vZ2xlLnByb3Rv", + "YnVmLlRpbWVzdGFtcBIbChNwYXJlbnRfZXhlY3V0aW9uX2lkGAUgASgJEg0K", + "BXRyYWNlGAYgASgIGjYKFEF0dHJpYnV0ZVZhbHVlc0VudHJ5EgsKA2tleRgB", + "IAEoCRINCgV2YWx1ZRgCIAEoCToCOAEikAEKH1JvdXRlVG9TZXRBdHRyaWJ1", + "dGVzUmVzcG9uc2VEdG8SFgoOY29ycmVsYXRpb25faWQYASABKAkSDwoHc3Vj", + "Y2VzcxgCIAEoCBIVCg1lcnJvcl9tZXNzYWdlGAMgASgJEi0KCXRpbWVzdGFt", + "cBgEIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXAiwwIKIVJvdXRl", + "VG9XYWl0Rm9yQXR0cmlidXRlUmVxdWVzdER0bxIWCg5jb3JyZWxhdGlvbl9p", + "ZBgBIAEoCRIcChRpbnN0YW5jZV91bmlxdWVfbmFtZRgCIAEoCRIWCg5hdHRy", + "aWJ1dGVfbmFtZRgDIAEoCRI6ChR0YXJnZXRfdmFsdWVfZW5jb2RlZBgEIAEo", + "CzIcLmdvb2dsZS5wcm90b2J1Zi5TdHJpbmdWYWx1ZRIqCgd0aW1lb3V0GAUg", + "ASgLMhkuZ29vZ2xlLnByb3RvYnVmLkR1cmF0aW9uEi0KCXRpbWVzdGFtcBgG", + "IAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXASGwoTcGFyZW50X2V4", + "ZWN1dGlvbl9pZBgHIAEoCRIcChRyZXF1aXJlX2dvb2RfcXVhbGl0eRgIIAEo", + "CCL/AQoiUm91dGVUb1dhaXRGb3JBdHRyaWJ1dGVSZXNwb25zZUR0bxIWCg5j", + "b3JyZWxhdGlvbl9pZBgBIAEoCRIPCgdtYXRjaGVkGAIgASgIEjUKBXZhbHVl", + "GAMgASgLMiYuc2NhZGFicmlkZ2Uuc2l0ZWNvbW1hbmQudjEuTG9vc2VWYWx1", + "ZRIPCgdxdWFsaXR5GAQgASgJEhEKCXRpbWVkX291dBgFIAEoCBIPCgdzdWNj", + "ZXNzGAYgASgIEhUKDWVycm9yX21lc3NhZ2UYByABKAkSLQoJdGltZXN0YW1w", + "GAggASgLMhouZ29vZ2xlLnByb3RvYnVmLlRpbWVzdGFtcCKJAwoMUm91dGVS", + "ZXF1ZXN0EkoKDXJvdXRlX3RvX2NhbGwYASABKAsyMS5zY2FkYWJyaWRnZS5z", + "aXRlY29tbWFuZC52MS5Sb3V0ZVRvQ2FsbFJlcXVlc3REdG9IABJdChdyb3V0", + "ZV90b19nZXRfYXR0cmlidXRlcxgCIAEoCzI6LnNjYWRhYnJpZGdlLnNpdGVj", + "b21tYW5kLnYxLlJvdXRlVG9HZXRBdHRyaWJ1dGVzUmVxdWVzdER0b0gAEl0K", + "F3JvdXRlX3RvX3NldF9hdHRyaWJ1dGVzGAMgASgLMjouc2NhZGFicmlkZ2Uu", + "c2l0ZWNvbW1hbmQudjEuUm91dGVUb1NldEF0dHJpYnV0ZXNSZXF1ZXN0RHRv", + "SAASZAobcm91dGVfdG9fd2FpdF9mb3JfYXR0cmlidXRlGAQgASgLMj0uc2Nh", + "ZGFicmlkZ2Uuc2l0ZWNvbW1hbmQudjEuUm91dGVUb1dhaXRGb3JBdHRyaWJ1", + "dGVSZXF1ZXN0RHRvSABCCQoHY29tbWFuZCKJAwoKUm91dGVSZXBseRJLCg1y", + "b3V0ZV90b19jYWxsGAEgASgLMjIuc2NhZGFicmlkZ2Uuc2l0ZWNvbW1hbmQu", + "djEuUm91dGVUb0NhbGxSZXNwb25zZUR0b0gAEl4KF3JvdXRlX3RvX2dldF9h", + "dHRyaWJ1dGVzGAIgASgLMjsuc2NhZGFicmlkZ2Uuc2l0ZWNvbW1hbmQudjEu", + "Um91dGVUb0dldEF0dHJpYnV0ZXNSZXNwb25zZUR0b0gAEl4KF3JvdXRlX3Rv", + "X3NldF9hdHRyaWJ1dGVzGAMgASgLMjsuc2NhZGFicmlkZ2Uuc2l0ZWNvbW1h", + "bmQudjEuUm91dGVUb1NldEF0dHJpYnV0ZXNSZXNwb25zZUR0b0gAEmUKG3Jv", + "dXRlX3RvX3dhaXRfZm9yX2F0dHJpYnV0ZRgEIAEoCzI+LnNjYWRhYnJpZGdl", + "LnNpdGVjb21tYW5kLnYxLlJvdXRlVG9XYWl0Rm9yQXR0cmlidXRlUmVzcG9u", + "c2VEdG9IAEIHCgVyZXBseSJBChZUcmlnZ2VyU2l0ZUZhaWxvdmVyRHRvEhYK", + "DmNvcnJlbGF0aW9uX2lkGAEgASgJEg8KB3NpdGVfaWQYAiABKAkibQoSU2l0", + "ZUZhaWxvdmVyQWNrRHRvEhYKDmNvcnJlbGF0aW9uX2lkGAEgASgJEhAKCGFj", + "Y2VwdGVkGAIgASgIEhYKDnRhcmdldF9hZGRyZXNzGAMgASgJEhUKDWVycm9y", + "X21lc3NhZ2UYBCABKAkqywEKE0RlcGxveW1lbnRTdGF0dXNEdG8SJQohREVQ", + "TE9ZTUVOVF9TVEFUVVNfRFRPX1VOU1BFQ0lGSUVEEAASIQodREVQTE9ZTUVO", + "VF9TVEFUVVNfRFRPX1BFTkRJTkcQARIlCiFERVBMT1lNRU5UX1NUQVRVU19E", + "VE9fSU5fUFJPR1JFU1MQAhIhCh1ERVBMT1lNRU5UX1NUQVRVU19EVE9fU1VD", + "Q0VTUxADEiAKHERFUExPWU1FTlRfU1RBVFVTX0RUT19GQUlMRUQQBCrEAQoS", + "QnJvd3NlTm9kZUNsYXNzRHRvEiUKIUJST1dTRV9OT0RFX0NMQVNTX0RUT19V", + "TlNQRUNJRklFRBAAEiAKHEJST1dTRV9OT0RFX0NMQVNTX0RUT19PQkpFQ1QQ", + "ARIiCh5CUk9XU0VfTk9ERV9DTEFTU19EVE9fVkFSSUFCTEUQAhIgChxCUk9X", + "U0VfTk9ERV9DTEFTU19EVE9fTUVUSE9EEAMSHwobQlJPV1NFX05PREVfQ0xB", + "U1NfRFRPX09USEVSEAQqoQIKFEJyb3dzZUZhaWx1cmVLaW5kRHRvEicKI0JS", + "T1dTRV9GQUlMVVJFX0tJTkRfRFRPX1VOU1BFQ0lGSUVEEAASMAosQlJPV1NF", + "X0ZBSUxVUkVfS0lORF9EVE9fQ09OTkVDVElPTl9OT1RfRk9VTkQQARI0CjBC", + "Uk9XU0VfRkFJTFVSRV9LSU5EX0RUT19DT05ORUNUSU9OX05PVF9DT05ORUNU", + "RUQQAhIpCiVCUk9XU0VfRkFJTFVSRV9LSU5EX0RUT19OT1RfQlJPV1NBQkxF", + "EAMSIwofQlJPV1NFX0ZBSUxVUkVfS0lORF9EVE9fVElNRU9VVBAEEigKJEJS", + "T1dTRV9GQUlMVVJFX0tJTkRfRFRPX1NFUlZFUl9FUlJPUhAFKqoCChtSZWFk", + "VGFnVmFsdWVzRmFpbHVyZUtpbmREdG8SMAosUkVBRF9UQUdfVkFMVUVTX0ZB", + "SUxVUkVfS0lORF9EVE9fVU5TUEVDSUZJRUQQABI5CjVSRUFEX1RBR19WQUxV", + "RVNfRkFJTFVSRV9LSU5EX0RUT19DT05ORUNUSU9OX05PVF9GT1VORBABEj0K", + "OVJFQURfVEFHX1ZBTFVFU19GQUlMVVJFX0tJTkRfRFRPX0NPTk5FQ1RJT05f", + "Tk9UX0NPTk5FQ1RFRBACEiwKKFJFQURfVEFHX1ZBTFVFU19GQUlMVVJFX0tJ", + "TkRfRFRPX1RJTUVPVVQQAxIxCi1SRUFEX1RBR19WQUxVRVNfRkFJTFVSRV9L", + "SU5EX0RUT19TRVJWRVJfRVJST1IQBCqTAgoUVmVyaWZ5RmFpbHVyZUtpbmRE", + "dG8SJwojVkVSSUZZX0ZBSUxVUkVfS0lORF9EVE9fVU5TUEVDSUZJRUQQABIn", + "CiNWRVJJRllfRkFJTFVSRV9LSU5EX0RUT19VTlJFQUNIQUJMRRABEicKI1ZF", + "UklGWV9GQUlMVVJFX0tJTkRfRFRPX0FVVEhfRkFJTEVEEAISMQotVkVSSUZZ", + "X0ZBSUxVUkVfS0lORF9EVE9fVU5UUlVTVEVEX0NFUlRJRklDQVRFEAMSIwof", + "VkVSSUZZX0ZBSUxVUkVfS0lORF9EVE9fVElNRU9VVBAEEigKJFZFUklGWV9G", + "QUlMVVJFX0tJTkRfRFRPX1NFUlZFUl9FUlJPUhAFKuUBChpTdG9yZUFuZEZv", + "cndhcmRDYXRlZ29yeUR0bxIuCipTVE9SRV9BTkRfRk9SV0FSRF9DQVRFR09S", + "WV9EVE9fVU5TUEVDSUZJRUQQABIyCi5TVE9SRV9BTkRfRk9SV0FSRF9DQVRF", + "R09SWV9EVE9fRVhURVJOQUxfU1lTVEVNEAESLworU1RPUkVfQU5EX0ZPUldB", + "UkRfQ0FURUdPUllfRFRPX05PVElGSUNBVElPThACEjIKLlNUT1JFX0FORF9G", + "T1JXQVJEX0NBVEVHT1JZX0RUT19DQUNIRURfREJfV1JJVEUQAypoCg1BbGFy", + "bVN0YXRlRHRvEh8KG0FMQVJNX1NUQVRFX0RUT19VTlNQRUNJRklFRBAAEhoK", + "FkFMQVJNX1NUQVRFX0RUT19BQ1RJVkUQARIaChZBTEFSTV9TVEFURV9EVE9f", + "Tk9STUFMEAIquQEKDUFsYXJtTGV2ZWxEdG8SHwobQUxBUk1fTEVWRUxfRFRP", + "X1VOU1BFQ0lGSUVEEAASGAoUQUxBUk1fTEVWRUxfRFRPX05PTkUQARIXChNB", + "TEFSTV9MRVZFTF9EVE9fTE9XEAISGwoXQUxBUk1fTEVWRUxfRFRPX0xPV19M", + "T1cQAxIYChRBTEFSTV9MRVZFTF9EVE9fSElHSBAEEh0KGUFMQVJNX0xFVkVM", + "X0RUT19ISUdIX0hJR0gQBSqSAQoMQWxhcm1LaW5kRHRvEh4KGkFMQVJNX0tJ", + "TkRfRFRPX1VOU1BFQ0lGSUVEEAASGwoXQUxBUk1fS0lORF9EVE9fQ09NUFVU", + "RUQQARIgChxBTEFSTV9LSU5EX0RUT19OQVRJVkVfT1BDX1VBEAISIwofQUxB", + "Uk1fS0lORF9EVE9fTkFUSVZFX01YX0FDQ0VTUxADKugBChNBbGFybVNoZWx2", + "ZVN0YXRlRHRvEiYKIkFMQVJNX1NIRUxWRV9TVEFURV9EVE9fVU5TUEVDSUZJ", + "RUQQABIkCiBBTEFSTV9TSEVMVkVfU1RBVEVfRFRPX1VOU0hFTFZFRBABEisK", + "J0FMQVJNX1NIRUxWRV9TVEFURV9EVE9fT05FX1NIT1RfU0hFTFZFRBACEigK", + "JEFMQVJNX1NIRUxWRV9TVEFURV9EVE9fVElNRURfU0hFTFZFRBADEiwKKEFM", + "QVJNX1NIRUxWRV9TVEFURV9EVE9fUEVSTUFORU5UX1NIRUxWRUQQBDKEBQoS", + "U2l0ZUNvbW1hbmRTZXJ2aWNlEmwKEEV4ZWN1dGVMaWZlY3ljbGUSLC5zY2Fk", + "YWJyaWRnZS5zaXRlY29tbWFuZC52MS5MaWZlY3ljbGVSZXF1ZXN0Giouc2Nh", + "ZGFicmlkZ2Uuc2l0ZWNvbW1hbmQudjEuTGlmZWN5Y2xlUmVwbHkSYAoMRXhl", + "Y3V0ZU9wY1VhEiguc2NhZGFicmlkZ2Uuc2l0ZWNvbW1hbmQudjEuT3BjVWFS", + "ZXF1ZXN0GiYuc2NhZGFicmlkZ2Uuc2l0ZWNvbW1hbmQudjEuT3BjVWFSZXBs", + "eRJgCgxFeGVjdXRlUXVlcnkSKC5zY2FkYWJyaWRnZS5zaXRlY29tbWFuZC52", + "MS5RdWVyeVJlcXVlc3QaJi5zY2FkYWJyaWRnZS5zaXRlY29tbWFuZC52MS5R", + "dWVyeVJlcGx5EmMKDUV4ZWN1dGVQYXJrZWQSKS5zY2FkYWJyaWRnZS5zaXRl", + "Y29tbWFuZC52MS5QYXJrZWRSZXF1ZXN0Gicuc2NhZGFicmlkZ2Uuc2l0ZWNv", + "bW1hbmQudjEuUGFya2VkUmVwbHkSYAoMRXhlY3V0ZVJvdXRlEiguc2NhZGFi", + "cmlkZ2Uuc2l0ZWNvbW1hbmQudjEuUm91dGVSZXF1ZXN0GiYuc2NhZGFicmlk", + "Z2Uuc2l0ZWNvbW1hbmQudjEuUm91dGVSZXBseRJ1Cg9UcmlnZ2VyRmFpbG92", + "ZXISMi5zY2FkYWJyaWRnZS5zaXRlY29tbWFuZC52MS5UcmlnZ2VyU2l0ZUZh", + "aWxvdmVyRHRvGi4uc2NhZGFicmlkZ2Uuc2l0ZWNvbW1hbmQudjEuU2l0ZUZh", + "aWxvdmVyQWNrRHRvQiuqAihaQi5NT00uV1cuU2NhZGFCcmlkZ2UuQ29tbXVu", + "aWNhdGlvbi5HcnBjYgZwcm90bzM=")); descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData, new pbr::FileDescriptor[] { global::Google.Protobuf.WellKnownTypes.TimestampReflection.Descriptor, global::Google.Protobuf.WellKnownTypes.DurationReflection.Descriptor, global::Google.Protobuf.WellKnownTypes.WrappersReflection.Descriptor, global::ZB.MOM.WW.ScadaBridge.Communication.Grpc.SitestreamReflection.Descriptor, }, new pbr::GeneratedClrTypeInfo(new[] {typeof(global::ZB.MOM.WW.ScadaBridge.Communication.Grpc.DeploymentStatusDto), typeof(global::ZB.MOM.WW.ScadaBridge.Communication.Grpc.BrowseNodeClassDto), typeof(global::ZB.MOM.WW.ScadaBridge.Communication.Grpc.BrowseFailureKindDto), typeof(global::ZB.MOM.WW.ScadaBridge.Communication.Grpc.ReadTagValuesFailureKindDto), typeof(global::ZB.MOM.WW.ScadaBridge.Communication.Grpc.VerifyFailureKindDto), typeof(global::ZB.MOM.WW.ScadaBridge.Communication.Grpc.StoreAndForwardCategoryDto), typeof(global::ZB.MOM.WW.ScadaBridge.Communication.Grpc.AlarmStateDto), typeof(global::ZB.MOM.WW.ScadaBridge.Communication.Grpc.AlarmLevelDto), typeof(global::ZB.MOM.WW.ScadaBridge.Communication.Grpc.AlarmKindDto), typeof(global::ZB.MOM.WW.ScadaBridge.Communication.Grpc.AlarmShelveStateDto), }, null, new pbr::GeneratedClrTypeInfo[] { @@ -580,7 +581,7 @@ namespace ZB.MOM.WW.ScadaBridge.Communication.Grpc { new pbr::GeneratedClrTypeInfo(typeof(global::ZB.MOM.WW.ScadaBridge.Communication.Grpc.UnsubscribeDebugViewAckDto), global::ZB.MOM.WW.ScadaBridge.Communication.Grpc.UnsubscribeDebugViewAckDto.Parser, null, null, null, null, null), new pbr::GeneratedClrTypeInfo(typeof(global::ZB.MOM.WW.ScadaBridge.Communication.Grpc.AlarmConditionStateDto), global::ZB.MOM.WW.ScadaBridge.Communication.Grpc.AlarmConditionStateDto.Parser, new[]{ "Active", "Acknowledged", "Confirmed", "Shelve", "Suppressed", "Severity" }, null, null, null, null), new pbr::GeneratedClrTypeInfo(typeof(global::ZB.MOM.WW.ScadaBridge.Communication.Grpc.DebugAttributeValueDto), global::ZB.MOM.WW.ScadaBridge.Communication.Grpc.DebugAttributeValueDto.Parser, new[]{ "InstanceUniqueName", "AttributePath", "AttributeName", "Value", "Quality", "Timestamp" }, null, null, null, null), - new pbr::GeneratedClrTypeInfo(typeof(global::ZB.MOM.WW.ScadaBridge.Communication.Grpc.DebugAlarmStateDto), global::ZB.MOM.WW.ScadaBridge.Communication.Grpc.DebugAlarmStateDto.Parser, new[]{ "InstanceUniqueName", "AlarmName", "State", "Priority", "Timestamp", "Level", "Message", "Kind", "Condition", "SourceReference", "AlarmTypeName", "Category", "OperatorUser", "OperatorComment", "OriginalRaiseTime", "CurrentValue", "LimitValue", "NativeSourceCanonicalName", "IsConfiguredPlaceholder" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::ZB.MOM.WW.ScadaBridge.Communication.Grpc.DebugAlarmStateDto), global::ZB.MOM.WW.ScadaBridge.Communication.Grpc.DebugAlarmStateDto.Parser, new[]{ "InstanceUniqueName", "AlarmName", "State", "Priority", "Timestamp", "Level", "Message", "Kind", "Condition", "SourceReference", "AlarmTypeName", "Category", "OperatorUser", "OperatorComment", "OriginalRaiseTime", "CurrentValue", "LimitValue", "NativeSourceCanonicalName", "IsConfiguredPlaceholder", "IsMesReportable" }, null, null, null, null), new pbr::GeneratedClrTypeInfo(typeof(global::ZB.MOM.WW.ScadaBridge.Communication.Grpc.DebugViewSnapshotDto), global::ZB.MOM.WW.ScadaBridge.Communication.Grpc.DebugViewSnapshotDto.Parser, new[]{ "InstanceUniqueName", "AttributeValues", "AlarmStates", "SnapshotTimestamp", "InstanceNotFound" }, null, null, null, null), new pbr::GeneratedClrTypeInfo(typeof(global::ZB.MOM.WW.ScadaBridge.Communication.Grpc.QueryRequest), global::ZB.MOM.WW.ScadaBridge.Communication.Grpc.QueryRequest.Parser, new[]{ "EventLogQuery", "DebugSnapshot", "SubscribeDebugView", "UnsubscribeDebugView" }, new[]{ "Command" }, null, null, null), new pbr::GeneratedClrTypeInfo(typeof(global::ZB.MOM.WW.ScadaBridge.Communication.Grpc.QueryReply), global::ZB.MOM.WW.ScadaBridge.Communication.Grpc.QueryReply.Parser, new[]{ "EventLogQuery", "DebugViewSnapshot", "UnsubscribeDebugView" }, new[]{ "Reply" }, null, null, null), @@ -22342,6 +22343,7 @@ namespace ZB.MOM.WW.ScadaBridge.Communication.Grpc { limitValue_ = other.limitValue_; nativeSourceCanonicalName_ = other.nativeSourceCanonicalName_; isConfiguredPlaceholder_ = other.isConfiguredPlaceholder_; + isMesReportable_ = other.isMesReportable_; _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); } @@ -22587,6 +22589,22 @@ namespace ZB.MOM.WW.ScadaBridge.Communication.Grpc { } } + /// Field number for the "is_mes_reportable" field. + public const int IsMesReportableFieldNumber = 20; + private bool isMesReportable_; + /// + /// MES-reportable flag stamped by the Instance Actor's snapshot (Gitea #60); false for + /// native conditions and from a pre-#60 site (proto3 default). + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public bool IsMesReportable { + get { return isMesReportable_; } + set { + isMesReportable_ = value; + } + } + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] public override bool Equals(object other) { @@ -22621,6 +22639,7 @@ namespace ZB.MOM.WW.ScadaBridge.Communication.Grpc { if (LimitValue != other.LimitValue) return false; if (NativeSourceCanonicalName != other.NativeSourceCanonicalName) return false; if (IsConfiguredPlaceholder != other.IsConfiguredPlaceholder) return false; + if (IsMesReportable != other.IsMesReportable) return false; return Equals(_unknownFields, other._unknownFields); } @@ -22647,6 +22666,7 @@ namespace ZB.MOM.WW.ScadaBridge.Communication.Grpc { if (LimitValue.Length != 0) hash ^= LimitValue.GetHashCode(); if (NativeSourceCanonicalName.Length != 0) hash ^= NativeSourceCanonicalName.GetHashCode(); if (IsConfiguredPlaceholder != false) hash ^= IsConfiguredPlaceholder.GetHashCode(); + if (IsMesReportable != false) hash ^= IsMesReportable.GetHashCode(); if (_unknownFields != null) { hash ^= _unknownFields.GetHashCode(); } @@ -22741,6 +22761,10 @@ namespace ZB.MOM.WW.ScadaBridge.Communication.Grpc { output.WriteRawTag(152, 1); output.WriteBool(IsConfiguredPlaceholder); } + if (IsMesReportable != false) { + output.WriteRawTag(160, 1); + output.WriteBool(IsMesReportable); + } if (_unknownFields != null) { _unknownFields.WriteTo(output); } @@ -22827,6 +22851,10 @@ namespace ZB.MOM.WW.ScadaBridge.Communication.Grpc { output.WriteRawTag(152, 1); output.WriteBool(IsConfiguredPlaceholder); } + if (IsMesReportable != false) { + output.WriteRawTag(160, 1); + output.WriteBool(IsMesReportable); + } if (_unknownFields != null) { _unknownFields.WriteTo(ref output); } @@ -22894,6 +22922,9 @@ namespace ZB.MOM.WW.ScadaBridge.Communication.Grpc { if (IsConfiguredPlaceholder != false) { size += 2 + 1; } + if (IsMesReportable != false) { + size += 2 + 1; + } if (_unknownFields != null) { size += _unknownFields.CalculateSize(); } @@ -22972,6 +23003,9 @@ namespace ZB.MOM.WW.ScadaBridge.Communication.Grpc { if (other.IsConfiguredPlaceholder != false) { IsConfiguredPlaceholder = other.IsConfiguredPlaceholder; } + if (other.IsMesReportable != false) { + IsMesReportable = other.IsMesReportable; + } _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); } @@ -23076,6 +23110,10 @@ namespace ZB.MOM.WW.ScadaBridge.Communication.Grpc { IsConfiguredPlaceholder = input.ReadBool(); break; } + case 160: { + IsMesReportable = input.ReadBool(); + break; + } } } #endif @@ -23180,6 +23218,10 @@ namespace ZB.MOM.WW.ScadaBridge.Communication.Grpc { IsConfiguredPlaceholder = input.ReadBool(); break; } + case 160: { + IsMesReportable = input.ReadBool(); + break; + } } } } diff --git a/src/ZB.MOM.WW.ScadaBridge.Communication/SiteStreamGrpc/Sitestream.cs b/src/ZB.MOM.WW.ScadaBridge.Communication/SiteStreamGrpc/Sitestream.cs index db029242..169e579b 100644 --- a/src/ZB.MOM.WW.ScadaBridge.Communication/SiteStreamGrpc/Sitestream.cs +++ b/src/ZB.MOM.WW.ScadaBridge.Communication/SiteStreamGrpc/Sitestream.cs @@ -42,7 +42,7 @@ namespace ZB.MOM.WW.ScadaBridge.Communication.Grpc { "CRINCgV2YWx1ZRgEIAEoCRIkCgdxdWFsaXR5GAUgASgOMhMuc2l0ZXN0cmVh", "bS5RdWFsaXR5Ei0KCXRpbWVzdGFtcBgGIAEoCzIaLmdvb2dsZS5wcm90b2J1", "Zi5UaW1lc3RhbXASGwoTc291cmNlX2V4ZWN1dGlvbl9pZBgHIAEoCRINCgV0", - "cmFjZRgIIAEoCCKvBQoQQWxhcm1TdGF0ZVVwZGF0ZRIcChRpbnN0YW5jZV91", + "cmFjZRgIIAEoCCLKBQoQQWxhcm1TdGF0ZVVwZGF0ZRIcChRpbnN0YW5jZV91", "bmlxdWVfbmFtZRgBIAEoCRISCgphbGFybV9uYW1lGAIgASgJEikKBXN0YXRl", "GAMgASgOMhouc2l0ZXN0cmVhbS5BbGFybVN0YXRlRW51bRIQCghwcmlvcml0", "eRgEIAEoBRItCgl0aW1lc3RhbXAYBSABKAsyGi5nb29nbGUucHJvdG9idWYu", @@ -57,72 +57,73 @@ namespace ZB.MOM.WW.ScadaBridge.Communication.Grpc { "DWN1cnJlbnRfdmFsdWUYFCABKAkSEwoLbGltaXRfdmFsdWUYFSABKAkSJAoc", "bmF0aXZlX3NvdXJjZV9jYW5vbmljYWxfbmFtZRgWIAEoCRIhChlpc19jb25m", "aWd1cmVkX3BsYWNlaG9sZGVyGBcgASgIEiwKCGFja190aW1lGBggASgLMhou", - "Z29vZ2xlLnByb3RvYnVmLlRpbWVzdGFtcCK9BAoNQXVkaXRFdmVudER0bxIQ", - "CghldmVudF9pZBgBIAEoCRIzCg9vY2N1cnJlZF9hdF91dGMYAiABKAsyGi5n", - "b29nbGUucHJvdG9idWYuVGltZXN0YW1wEg8KB2NoYW5uZWwYAyABKAkSDAoE", - "a2luZBgEIAEoCRIWCg5jb3JyZWxhdGlvbl9pZBgFIAEoCRIWCg5zb3VyY2Vf", - "c2l0ZV9pZBgGIAEoCRIaChJzb3VyY2VfaW5zdGFuY2VfaWQYByABKAkSFQoN", - "c291cmNlX3NjcmlwdBgIIAEoCRINCgVhY3RvchgJIAEoCRIOCgZ0YXJnZXQY", - "CiABKAkSDgoGc3RhdHVzGAsgASgJEjAKC2h0dHBfc3RhdHVzGAwgASgLMhsu", - "Z29vZ2xlLnByb3RvYnVmLkludDMyVmFsdWUSMAoLZHVyYXRpb25fbXMYDSAB", - "KAsyGy5nb29nbGUucHJvdG9idWYuSW50MzJWYWx1ZRIVCg1lcnJvcl9tZXNz", - "YWdlGA4gASgJEhQKDGVycm9yX2RldGFpbBgPIAEoCRIXCg9yZXF1ZXN0X3N1", - "bW1hcnkYECABKAkSGAoQcmVzcG9uc2Vfc3VtbWFyeRgRIAEoCRIZChFwYXls", - "b2FkX3RydW5jYXRlZBgSIAEoCBINCgVleHRyYRgTIAEoCRIUCgxleGVjdXRp", - "b25faWQYFCABKAkSGwoTcGFyZW50X2V4ZWN1dGlvbl9pZBgVIAEoCRITCgtz", - "b3VyY2Vfbm9kZRgWIAEoCSI8Cg9BdWRpdEV2ZW50QmF0Y2gSKQoGZXZlbnRz", - "GAEgAygLMhkuc2l0ZXN0cmVhbS5BdWRpdEV2ZW50RHRvIkMKCUluZ2VzdEFj", - "axIaChJhY2NlcHRlZF9ldmVudF9pZHMYASADKAkSGgoScmVqZWN0ZWRfZXZl", - "bnRfaWRzGAIgAygJIokDChZTaXRlQ2FsbE9wZXJhdGlvbmFsRHRvEhwKFHRy", - "YWNrZWRfb3BlcmF0aW9uX2lkGAEgASgJEg8KB2NoYW5uZWwYAiABKAkSDgoG", - "dGFyZ2V0GAMgASgJEhMKC3NvdXJjZV9zaXRlGAQgASgJEg4KBnN0YXR1cxgF", - "IAEoCRITCgtyZXRyeV9jb3VudBgGIAEoBRISCgpsYXN0X2Vycm9yGAcgASgJ", - "EjAKC2h0dHBfc3RhdHVzGAggASgLMhsuZ29vZ2xlLnByb3RvYnVmLkludDMy", - "VmFsdWUSMgoOY3JlYXRlZF9hdF91dGMYCSABKAsyGi5nb29nbGUucHJvdG9i", - "dWYuVGltZXN0YW1wEjIKDnVwZGF0ZWRfYXRfdXRjGAogASgLMhouZ29vZ2xl", - "LnByb3RvYnVmLlRpbWVzdGFtcBIzCg90ZXJtaW5hbF9hdF91dGMYCyABKAsy", - "Gi5nb29nbGUucHJvdG9idWYuVGltZXN0YW1wEhMKC3NvdXJjZV9ub2RlGAwg", - "ASgJIoABChVDYWNoZWRUZWxlbWV0cnlQYWNrZXQSLgoLYXVkaXRfZXZlbnQY", - "ASABKAsyGS5zaXRlc3RyZWFtLkF1ZGl0RXZlbnREdG8SNwoLb3BlcmF0aW9u", - "YWwYAiABKAsyIi5zaXRlc3RyZWFtLlNpdGVDYWxsT3BlcmF0aW9uYWxEdG8i", - "SgoUQ2FjaGVkVGVsZW1ldHJ5QmF0Y2gSMgoHcGFja2V0cxgBIAMoCzIhLnNp", - "dGVzdHJlYW0uQ2FjaGVkVGVsZW1ldHJ5UGFja2V0Im0KFlB1bGxBdWRpdEV2", - "ZW50c1JlcXVlc3QSLQoJc2luY2VfdXRjGAEgASgLMhouZ29vZ2xlLnByb3Rv", - "YnVmLlRpbWVzdGFtcBISCgpiYXRjaF9zaXplGAIgASgFEhAKCGFmdGVyX2lk", - "GAMgASgJIlwKF1B1bGxBdWRpdEV2ZW50c1Jlc3BvbnNlEikKBmV2ZW50cxgB", - "IAMoCzIZLnNpdGVzdHJlYW0uQXVkaXRFdmVudER0bxIWCg5tb3JlX2F2YWls", - "YWJsZRgCIAEoCCKEAQoWUHVsbFRyYWNlRXZlbnRzUmVxdWVzdBIQCghhZnRl", - "cl9pZBgEIAEoCRIVCg1leGVjdXRpb25faWRzGAEgAygJEi0KCXNpbmNlX3V0", - "YxgCIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXASEgoKbWF4X2V2", - "ZW50cxgDIAEoBSJEChdQdWxsVHJhY2VFdmVudHNSZXNwb25zZRIpCgZldmVu", - "dHMYASADKAsyGS5zaXRlc3RyZWFtLkF1ZGl0RXZlbnREdG8iawoUUHVsbFNp", - "dGVDYWxsc1JlcXVlc3QSLQoJc2luY2VfdXRjGAEgASgLMhouZ29vZ2xlLnBy", - "b3RvYnVmLlRpbWVzdGFtcBISCgpiYXRjaF9zaXplGAIgASgFEhAKCGFmdGVy", - "X2lkGAMgASgJImkKFVB1bGxTaXRlQ2FsbHNSZXNwb25zZRI4CgxvcGVyYXRp", - "b25hbHMYASADKAsyIi5zaXRlc3RyZWFtLlNpdGVDYWxsT3BlcmF0aW9uYWxE", - "dG8SFgoObW9yZV9hdmFpbGFibGUYAiABKAgqXAoHUXVhbGl0eRIXChNRVUFM", - "SVRZX1VOU1BFQ0lGSUVEEAASEAoMUVVBTElUWV9HT09EEAESFQoRUVVBTElU", - "WV9VTkNFUlRBSU4QAhIPCgtRVUFMSVRZX0JBRBADKl0KDkFsYXJtU3RhdGVF", - "bnVtEhsKF0FMQVJNX1NUQVRFX1VOU1BFQ0lGSUVEEAASFgoSQUxBUk1fU1RB", - "VEVfTk9STUFMEAESFgoSQUxBUk1fU1RBVEVfQUNUSVZFEAIqhQEKDkFsYXJt", - "TGV2ZWxFbnVtEhQKEEFMQVJNX0xFVkVMX05PTkUQABITCg9BTEFSTV9MRVZF", - "TF9MT1cQARIXChNBTEFSTV9MRVZFTF9MT1dfTE9XEAISFAoQQUxBUk1fTEVW", - "RUxfSElHSBADEhkKFUFMQVJNX0xFVkVMX0hJR0hfSElHSBAEMuIEChFTaXRl", - "U3RyZWFtU2VydmljZRJVChFTdWJzY3JpYmVJbnN0YW5jZRIhLnNpdGVzdHJl", - "YW0uSW5zdGFuY2VTdHJlYW1SZXF1ZXN0Ghsuc2l0ZXN0cmVhbS5TaXRlU3Ry", - "ZWFtRXZlbnQwARJNCg1TdWJzY3JpYmVTaXRlEh0uc2l0ZXN0cmVhbS5TaXRl", - "U3RyZWFtUmVxdWVzdBobLnNpdGVzdHJlYW0uU2l0ZVN0cmVhbUV2ZW50MAES", - "RwoRSW5nZXN0QXVkaXRFdmVudHMSGy5zaXRlc3RyZWFtLkF1ZGl0RXZlbnRC", - "YXRjaBoVLnNpdGVzdHJlYW0uSW5nZXN0QWNrElAKFUluZ2VzdENhY2hlZFRl", - "bGVtZXRyeRIgLnNpdGVzdHJlYW0uQ2FjaGVkVGVsZW1ldHJ5QmF0Y2gaFS5z", - "aXRlc3RyZWFtLkluZ2VzdEFjaxJaCg9QdWxsQXVkaXRFdmVudHMSIi5zaXRl", - "c3RyZWFtLlB1bGxBdWRpdEV2ZW50c1JlcXVlc3QaIy5zaXRlc3RyZWFtLlB1", - "bGxBdWRpdEV2ZW50c1Jlc3BvbnNlEloKD1B1bGxUcmFjZUV2ZW50cxIiLnNp", - "dGVzdHJlYW0uUHVsbFRyYWNlRXZlbnRzUmVxdWVzdBojLnNpdGVzdHJlYW0u", - "UHVsbFRyYWNlRXZlbnRzUmVzcG9uc2USVAoNUHVsbFNpdGVDYWxscxIgLnNp", - "dGVzdHJlYW0uUHVsbFNpdGVDYWxsc1JlcXVlc3QaIS5zaXRlc3RyZWFtLlB1", - "bGxTaXRlQ2FsbHNSZXNwb25zZUIrqgIoWkIuTU9NLldXLlNjYWRhQnJpZGdl", - "LkNvbW11bmljYXRpb24uR3JwY2IGcHJvdG8z")); + "Z29vZ2xlLnByb3RvYnVmLlRpbWVzdGFtcBIZChFpc19tZXNfcmVwb3J0YWJs", + "ZRgZIAEoCCK9BAoNQXVkaXRFdmVudER0bxIQCghldmVudF9pZBgBIAEoCRIz", + "Cg9vY2N1cnJlZF9hdF91dGMYAiABKAsyGi5nb29nbGUucHJvdG9idWYuVGlt", + "ZXN0YW1wEg8KB2NoYW5uZWwYAyABKAkSDAoEa2luZBgEIAEoCRIWCg5jb3Jy", + "ZWxhdGlvbl9pZBgFIAEoCRIWCg5zb3VyY2Vfc2l0ZV9pZBgGIAEoCRIaChJz", + "b3VyY2VfaW5zdGFuY2VfaWQYByABKAkSFQoNc291cmNlX3NjcmlwdBgIIAEo", + "CRINCgVhY3RvchgJIAEoCRIOCgZ0YXJnZXQYCiABKAkSDgoGc3RhdHVzGAsg", + "ASgJEjAKC2h0dHBfc3RhdHVzGAwgASgLMhsuZ29vZ2xlLnByb3RvYnVmLklu", + "dDMyVmFsdWUSMAoLZHVyYXRpb25fbXMYDSABKAsyGy5nb29nbGUucHJvdG9i", + "dWYuSW50MzJWYWx1ZRIVCg1lcnJvcl9tZXNzYWdlGA4gASgJEhQKDGVycm9y", + "X2RldGFpbBgPIAEoCRIXCg9yZXF1ZXN0X3N1bW1hcnkYECABKAkSGAoQcmVz", + "cG9uc2Vfc3VtbWFyeRgRIAEoCRIZChFwYXlsb2FkX3RydW5jYXRlZBgSIAEo", + "CBINCgVleHRyYRgTIAEoCRIUCgxleGVjdXRpb25faWQYFCABKAkSGwoTcGFy", + "ZW50X2V4ZWN1dGlvbl9pZBgVIAEoCRITCgtzb3VyY2Vfbm9kZRgWIAEoCSI8", + "Cg9BdWRpdEV2ZW50QmF0Y2gSKQoGZXZlbnRzGAEgAygLMhkuc2l0ZXN0cmVh", + "bS5BdWRpdEV2ZW50RHRvIkMKCUluZ2VzdEFjaxIaChJhY2NlcHRlZF9ldmVu", + "dF9pZHMYASADKAkSGgoScmVqZWN0ZWRfZXZlbnRfaWRzGAIgAygJIokDChZT", + "aXRlQ2FsbE9wZXJhdGlvbmFsRHRvEhwKFHRyYWNrZWRfb3BlcmF0aW9uX2lk", + "GAEgASgJEg8KB2NoYW5uZWwYAiABKAkSDgoGdGFyZ2V0GAMgASgJEhMKC3Nv", + "dXJjZV9zaXRlGAQgASgJEg4KBnN0YXR1cxgFIAEoCRITCgtyZXRyeV9jb3Vu", + "dBgGIAEoBRISCgpsYXN0X2Vycm9yGAcgASgJEjAKC2h0dHBfc3RhdHVzGAgg", + "ASgLMhsuZ29vZ2xlLnByb3RvYnVmLkludDMyVmFsdWUSMgoOY3JlYXRlZF9h", + "dF91dGMYCSABKAsyGi5nb29nbGUucHJvdG9idWYuVGltZXN0YW1wEjIKDnVw", + "ZGF0ZWRfYXRfdXRjGAogASgLMhouZ29vZ2xlLnByb3RvYnVmLlRpbWVzdGFt", + "cBIzCg90ZXJtaW5hbF9hdF91dGMYCyABKAsyGi5nb29nbGUucHJvdG9idWYu", + "VGltZXN0YW1wEhMKC3NvdXJjZV9ub2RlGAwgASgJIoABChVDYWNoZWRUZWxl", + "bWV0cnlQYWNrZXQSLgoLYXVkaXRfZXZlbnQYASABKAsyGS5zaXRlc3RyZWFt", + "LkF1ZGl0RXZlbnREdG8SNwoLb3BlcmF0aW9uYWwYAiABKAsyIi5zaXRlc3Ry", + "ZWFtLlNpdGVDYWxsT3BlcmF0aW9uYWxEdG8iSgoUQ2FjaGVkVGVsZW1ldHJ5", + "QmF0Y2gSMgoHcGFja2V0cxgBIAMoCzIhLnNpdGVzdHJlYW0uQ2FjaGVkVGVs", + "ZW1ldHJ5UGFja2V0Im0KFlB1bGxBdWRpdEV2ZW50c1JlcXVlc3QSLQoJc2lu", + "Y2VfdXRjGAEgASgLMhouZ29vZ2xlLnByb3RvYnVmLlRpbWVzdGFtcBISCgpi", + "YXRjaF9zaXplGAIgASgFEhAKCGFmdGVyX2lkGAMgASgJIlwKF1B1bGxBdWRp", + "dEV2ZW50c1Jlc3BvbnNlEikKBmV2ZW50cxgBIAMoCzIZLnNpdGVzdHJlYW0u", + "QXVkaXRFdmVudER0bxIWCg5tb3JlX2F2YWlsYWJsZRgCIAEoCCKEAQoWUHVs", + "bFRyYWNlRXZlbnRzUmVxdWVzdBIQCghhZnRlcl9pZBgEIAEoCRIVCg1leGVj", + "dXRpb25faWRzGAEgAygJEi0KCXNpbmNlX3V0YxgCIAEoCzIaLmdvb2dsZS5w", + "cm90b2J1Zi5UaW1lc3RhbXASEgoKbWF4X2V2ZW50cxgDIAEoBSJEChdQdWxs", + "VHJhY2VFdmVudHNSZXNwb25zZRIpCgZldmVudHMYASADKAsyGS5zaXRlc3Ry", + "ZWFtLkF1ZGl0RXZlbnREdG8iawoUUHVsbFNpdGVDYWxsc1JlcXVlc3QSLQoJ", + "c2luY2VfdXRjGAEgASgLMhouZ29vZ2xlLnByb3RvYnVmLlRpbWVzdGFtcBIS", + "CgpiYXRjaF9zaXplGAIgASgFEhAKCGFmdGVyX2lkGAMgASgJImkKFVB1bGxT", + "aXRlQ2FsbHNSZXNwb25zZRI4CgxvcGVyYXRpb25hbHMYASADKAsyIi5zaXRl", + "c3RyZWFtLlNpdGVDYWxsT3BlcmF0aW9uYWxEdG8SFgoObW9yZV9hdmFpbGFi", + "bGUYAiABKAgqXAoHUXVhbGl0eRIXChNRVUFMSVRZX1VOU1BFQ0lGSUVEEAAS", + "EAoMUVVBTElUWV9HT09EEAESFQoRUVVBTElUWV9VTkNFUlRBSU4QAhIPCgtR", + "VUFMSVRZX0JBRBADKl0KDkFsYXJtU3RhdGVFbnVtEhsKF0FMQVJNX1NUQVRF", + "X1VOU1BFQ0lGSUVEEAASFgoSQUxBUk1fU1RBVEVfTk9STUFMEAESFgoSQUxB", + "Uk1fU1RBVEVfQUNUSVZFEAIqhQEKDkFsYXJtTGV2ZWxFbnVtEhQKEEFMQVJN", + "X0xFVkVMX05PTkUQABITCg9BTEFSTV9MRVZFTF9MT1cQARIXChNBTEFSTV9M", + "RVZFTF9MT1dfTE9XEAISFAoQQUxBUk1fTEVWRUxfSElHSBADEhkKFUFMQVJN", + "X0xFVkVMX0hJR0hfSElHSBAEMuIEChFTaXRlU3RyZWFtU2VydmljZRJVChFT", + "dWJzY3JpYmVJbnN0YW5jZRIhLnNpdGVzdHJlYW0uSW5zdGFuY2VTdHJlYW1S", + "ZXF1ZXN0Ghsuc2l0ZXN0cmVhbS5TaXRlU3RyZWFtRXZlbnQwARJNCg1TdWJz", + "Y3JpYmVTaXRlEh0uc2l0ZXN0cmVhbS5TaXRlU3RyZWFtUmVxdWVzdBobLnNp", + "dGVzdHJlYW0uU2l0ZVN0cmVhbUV2ZW50MAESRwoRSW5nZXN0QXVkaXRFdmVu", + "dHMSGy5zaXRlc3RyZWFtLkF1ZGl0RXZlbnRCYXRjaBoVLnNpdGVzdHJlYW0u", + "SW5nZXN0QWNrElAKFUluZ2VzdENhY2hlZFRlbGVtZXRyeRIgLnNpdGVzdHJl", + "YW0uQ2FjaGVkVGVsZW1ldHJ5QmF0Y2gaFS5zaXRlc3RyZWFtLkluZ2VzdEFj", + "axJaCg9QdWxsQXVkaXRFdmVudHMSIi5zaXRlc3RyZWFtLlB1bGxBdWRpdEV2", + "ZW50c1JlcXVlc3QaIy5zaXRlc3RyZWFtLlB1bGxBdWRpdEV2ZW50c1Jlc3Bv", + "bnNlEloKD1B1bGxUcmFjZUV2ZW50cxIiLnNpdGVzdHJlYW0uUHVsbFRyYWNl", + "RXZlbnRzUmVxdWVzdBojLnNpdGVzdHJlYW0uUHVsbFRyYWNlRXZlbnRzUmVz", + "cG9uc2USVAoNUHVsbFNpdGVDYWxscxIgLnNpdGVzdHJlYW0uUHVsbFNpdGVD", + "YWxsc1JlcXVlc3QaIS5zaXRlc3RyZWFtLlB1bGxTaXRlQ2FsbHNSZXNwb25z", + "ZUIrqgIoWkIuTU9NLldXLlNjYWRhQnJpZGdlLkNvbW11bmljYXRpb24uR3Jw", + "Y2IGcHJvdG8z")); descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData, new pbr::FileDescriptor[] { global::Google.Protobuf.WellKnownTypes.TimestampReflection.Descriptor, global::Google.Protobuf.WellKnownTypes.WrappersReflection.Descriptor, }, new pbr::GeneratedClrTypeInfo(new[] {typeof(global::ZB.MOM.WW.ScadaBridge.Communication.Grpc.Quality), typeof(global::ZB.MOM.WW.ScadaBridge.Communication.Grpc.AlarmStateEnum), typeof(global::ZB.MOM.WW.ScadaBridge.Communication.Grpc.AlarmLevelEnum), }, null, new pbr::GeneratedClrTypeInfo[] { @@ -131,7 +132,7 @@ namespace ZB.MOM.WW.ScadaBridge.Communication.Grpc { new pbr::GeneratedClrTypeInfo(typeof(global::ZB.MOM.WW.ScadaBridge.Communication.Grpc.SiteStreamEvent), global::ZB.MOM.WW.ScadaBridge.Communication.Grpc.SiteStreamEvent.Parser, new[]{ "CorrelationId", "AttributeChanged", "AlarmChanged", "Batch" }, new[]{ "Event" }, null, null, null), new pbr::GeneratedClrTypeInfo(typeof(global::ZB.MOM.WW.ScadaBridge.Communication.Grpc.SiteStreamEventBatch), global::ZB.MOM.WW.ScadaBridge.Communication.Grpc.SiteStreamEventBatch.Parser, new[]{ "Events" }, null, null, null, null), new pbr::GeneratedClrTypeInfo(typeof(global::ZB.MOM.WW.ScadaBridge.Communication.Grpc.AttributeValueUpdate), global::ZB.MOM.WW.ScadaBridge.Communication.Grpc.AttributeValueUpdate.Parser, new[]{ "InstanceUniqueName", "AttributePath", "AttributeName", "Value", "Quality", "Timestamp", "SourceExecutionId", "Trace" }, null, null, null, null), - new pbr::GeneratedClrTypeInfo(typeof(global::ZB.MOM.WW.ScadaBridge.Communication.Grpc.AlarmStateUpdate), global::ZB.MOM.WW.ScadaBridge.Communication.Grpc.AlarmStateUpdate.Parser, new[]{ "InstanceUniqueName", "AlarmName", "State", "Priority", "Timestamp", "Level", "Message", "Kind", "Active", "Acknowledged", "Confirmed", "ShelveState", "Suppressed", "SourceReference", "AlarmTypeName", "Category", "OperatorUser", "OperatorComment", "OriginalRaiseTime", "CurrentValue", "LimitValue", "NativeSourceCanonicalName", "IsConfiguredPlaceholder", "AckTime" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::ZB.MOM.WW.ScadaBridge.Communication.Grpc.AlarmStateUpdate), global::ZB.MOM.WW.ScadaBridge.Communication.Grpc.AlarmStateUpdate.Parser, new[]{ "InstanceUniqueName", "AlarmName", "State", "Priority", "Timestamp", "Level", "Message", "Kind", "Active", "Acknowledged", "Confirmed", "ShelveState", "Suppressed", "SourceReference", "AlarmTypeName", "Category", "OperatorUser", "OperatorComment", "OriginalRaiseTime", "CurrentValue", "LimitValue", "NativeSourceCanonicalName", "IsConfiguredPlaceholder", "AckTime", "IsMesReportable" }, null, null, null, null), new pbr::GeneratedClrTypeInfo(typeof(global::ZB.MOM.WW.ScadaBridge.Communication.Grpc.AuditEventDto), global::ZB.MOM.WW.ScadaBridge.Communication.Grpc.AuditEventDto.Parser, new[]{ "EventId", "OccurredAtUtc", "Channel", "Kind", "CorrelationId", "SourceSiteId", "SourceInstanceId", "SourceScript", "Actor", "Target", "Status", "HttpStatus", "DurationMs", "ErrorMessage", "ErrorDetail", "RequestSummary", "ResponseSummary", "PayloadTruncated", "Extra", "ExecutionId", "ParentExecutionId", "SourceNode" }, null, null, null, null), new pbr::GeneratedClrTypeInfo(typeof(global::ZB.MOM.WW.ScadaBridge.Communication.Grpc.AuditEventBatch), global::ZB.MOM.WW.ScadaBridge.Communication.Grpc.AuditEventBatch.Parser, new[]{ "Events" }, null, null, null, null), new pbr::GeneratedClrTypeInfo(typeof(global::ZB.MOM.WW.ScadaBridge.Communication.Grpc.IngestAck), global::ZB.MOM.WW.ScadaBridge.Communication.Grpc.IngestAck.Parser, new[]{ "AcceptedEventIds", "RejectedEventIds" }, null, null, null, null), @@ -1822,6 +1823,7 @@ namespace ZB.MOM.WW.ScadaBridge.Communication.Grpc { nativeSourceCanonicalName_ = other.nativeSourceCanonicalName_; isConfiguredPlaceholder_ = other.isConfiguredPlaceholder_; ackTime_ = other.ackTime_ != null ? other.ackTime_.Clone() : null; + isMesReportable_ = other.isMesReportable_; _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); } @@ -2159,6 +2161,23 @@ namespace ZB.MOM.WW.ScadaBridge.Communication.Grpc { } } + /// Field number for the "is_mes_reportable" field. + public const int IsMesReportableFieldNumber = 25; + private bool isMesReportable_; + /// + /// True when the alarm's deployed configuration flags it MES-reportable + /// (ResolvedAlarm.IsMesReportable, Gitea #60). Always false for native conditions, + /// which have no per-alarm config row; a pre-#60 site leaves it at the proto3 default. + /// + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public bool IsMesReportable { + get { return isMesReportable_; } + set { + isMesReportable_ = value; + } + } + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] public override bool Equals(object other) { @@ -2198,6 +2217,7 @@ namespace ZB.MOM.WW.ScadaBridge.Communication.Grpc { if (NativeSourceCanonicalName != other.NativeSourceCanonicalName) return false; if (IsConfiguredPlaceholder != other.IsConfiguredPlaceholder) return false; if (!object.Equals(AckTime, other.AckTime)) return false; + if (IsMesReportable != other.IsMesReportable) return false; return Equals(_unknownFields, other._unknownFields); } @@ -2229,6 +2249,7 @@ namespace ZB.MOM.WW.ScadaBridge.Communication.Grpc { if (NativeSourceCanonicalName.Length != 0) hash ^= NativeSourceCanonicalName.GetHashCode(); if (IsConfiguredPlaceholder != false) hash ^= IsConfiguredPlaceholder.GetHashCode(); if (ackTime_ != null) hash ^= AckTime.GetHashCode(); + if (IsMesReportable != false) hash ^= IsMesReportable.GetHashCode(); if (_unknownFields != null) { hash ^= _unknownFields.GetHashCode(); } @@ -2343,6 +2364,10 @@ namespace ZB.MOM.WW.ScadaBridge.Communication.Grpc { output.WriteRawTag(194, 1); output.WriteMessage(AckTime); } + if (IsMesReportable != false) { + output.WriteRawTag(200, 1); + output.WriteBool(IsMesReportable); + } if (_unknownFields != null) { _unknownFields.WriteTo(output); } @@ -2449,6 +2474,10 @@ namespace ZB.MOM.WW.ScadaBridge.Communication.Grpc { output.WriteRawTag(194, 1); output.WriteMessage(AckTime); } + if (IsMesReportable != false) { + output.WriteRawTag(200, 1); + output.WriteBool(IsMesReportable); + } if (_unknownFields != null) { _unknownFields.WriteTo(ref output); } @@ -2531,6 +2560,9 @@ namespace ZB.MOM.WW.ScadaBridge.Communication.Grpc { if (ackTime_ != null) { size += 2 + pb::CodedOutputStream.ComputeMessageSize(AckTime); } + if (IsMesReportable != false) { + size += 2 + 1; + } if (_unknownFields != null) { size += _unknownFields.CalculateSize(); } @@ -2624,6 +2656,9 @@ namespace ZB.MOM.WW.ScadaBridge.Communication.Grpc { } AckTime.MergeFrom(other.AckTime); } + if (other.IsMesReportable != false) { + IsMesReportable = other.IsMesReportable; + } _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); } @@ -2748,6 +2783,10 @@ namespace ZB.MOM.WW.ScadaBridge.Communication.Grpc { input.ReadMessage(AckTime); break; } + case 200: { + IsMesReportable = input.ReadBool(); + break; + } } } #endif @@ -2872,6 +2911,10 @@ namespace ZB.MOM.WW.ScadaBridge.Communication.Grpc { input.ReadMessage(AckTime); break; } + case 200: { + IsMesReportable = input.ReadBool(); + break; + } } } } diff --git a/src/ZB.MOM.WW.ScadaBridge.SiteRuntime/Actors/InstanceActor.cs b/src/ZB.MOM.WW.ScadaBridge.SiteRuntime/Actors/InstanceActor.cs index 3629352f..ddaf5344 100644 --- a/src/ZB.MOM.WW.ScadaBridge.SiteRuntime/Actors/InstanceActor.cs +++ b/src/ZB.MOM.WW.ScadaBridge.SiteRuntime/Actors/InstanceActor.cs @@ -1625,6 +1625,17 @@ public class InstanceActor : ReceiveActor /// private void HandleAlarmStateChanged(AlarmStateChanged changed) { + // Gitea #60: stamp the deployed MES-reportable flag before the event is retained + // AND published, so the live stream (Debug View, central's Alarm Summary cache) + // carries the same value the snapshot does. Alarm Actors never set it themselves. + // A native condition has no _alarmMesReportable entry and passes through as-is. + if (!changed.IsMesReportable + && _alarmMesReportable.TryGetValue(changed.AlarmName, out var mesReportable) + && mesReportable) + { + changed = changed with { IsMesReportable = true }; + } + _alarmStates[changed.AlarmName] = changed.State; _alarmTimestamps[changed.AlarmName] = changed.Timestamp; // Retain the full enriched event (Kind, Condition, native metadata) so the @@ -1713,11 +1724,12 @@ public class InstanceActor : ReceiveActor /// private List BuildAlarmStatesSnapshot() { - // The MES-reportable flag is stamped HERE and nowhere else (not at the Alarm - // Actor's emit sites), so the retained-event rows below and the fallback rows - // that follow always agree on it. A native condition has no _alarmMesReportable - // entry and is returned as-is (no record copy) — the default false is the intended - // result, and native rows dominate this list on a busy binding. + // The MES-reportable flag is stamped by the Instance Actor, never at the Alarm + // Actor's emit sites: HandleAlarmStateChanged stamps retained/published events + // (Gitea #60) and this projection re-applies it so the retained-event rows and + // the fallback rows below always agree on it. A native condition has no + // _alarmMesReportable entry and is returned as-is (no record copy) — the default + // false is the intended result, and native rows dominate this list on a busy binding. var states = _latestAlarmEvents.Values .Select(e => _alarmMesReportable.TryGetValue(e.AlarmName, out var mes) && mes ? e with { IsMesReportable = true } diff --git a/tests/ZB.MOM.WW.ScadaBridge.Communication.Tests/Grpc/StreamRelayActorTests.cs b/tests/ZB.MOM.WW.ScadaBridge.Communication.Tests/Grpc/StreamRelayActorTests.cs index 0d8a2248..d473b3dd 100644 --- a/tests/ZB.MOM.WW.ScadaBridge.Communication.Tests/Grpc/StreamRelayActorTests.cs +++ b/tests/ZB.MOM.WW.ScadaBridge.Communication.Tests/Grpc/StreamRelayActorTests.cs @@ -209,6 +209,40 @@ public class StreamRelayActorTests : TestKit SiteStreamGrpcClient.ConvertToDomainEvent(unackedProto)).AckTime); } + /// + /// Verifies that the MES-reportable flag survives the relay → proto → central decode + /// round trip (Gitea #60, AlarmStateUpdate field 25), and that an unflagged alarm + /// arrives as false. + /// + [Fact] + public void RelaysAlarmStateChanged_IsMesReportable_SurvivesFullRoundTrip() + { + var channel = Channel.CreateUnbounded(); + var actor = Sys.ActorOf(Props.Create(() => + new StreamRelayActor("corr-mes", channel.Writer))); + + var flagged = new AlarmStateChanged( + "Site1.Oven1", "HighTemp", AlarmState.Active, 700, + new DateTimeOffset(2026, 11, 9, 12, 0, 0, TimeSpan.Zero)) + { + IsMesReportable = true + }; + + actor.Tell(flagged); + var flaggedProto = ReadProtoEvent(channel); + Assert.True(flaggedProto.AlarmChanged.IsMesReportable); + Assert.True( + Assert.IsType( + SiteStreamGrpcClient.ConvertToDomainEvent(flaggedProto)).IsMesReportable); + + actor.Tell(flagged with { IsMesReportable = false }); + var plainProto = ReadProtoEvent(channel); + Assert.False(plainProto.AlarmChanged.IsMesReportable); + Assert.False( + Assert.IsType( + SiteStreamGrpcClient.ConvertToDomainEvent(plainProto)).IsMesReportable); + } + /// /// Reads the next relayed proto event, retrying once after a short pause because the /// relay actor writes to the channel asynchronously (mirrors the existing round-trip diff --git a/tests/ZB.MOM.WW.ScadaBridge.Communication.Tests/SiteCommandSamples.cs b/tests/ZB.MOM.WW.ScadaBridge.Communication.Tests/SiteCommandSamples.cs index c1497b37..f915ef1f 100644 --- a/tests/ZB.MOM.WW.ScadaBridge.Communication.Tests/SiteCommandSamples.cs +++ b/tests/ZB.MOM.WW.ScadaBridge.Communication.Tests/SiteCommandSamples.cs @@ -275,12 +275,16 @@ internal static class SiteCommandSamples private static AttributeValueChanged AttrValueList() => new("Site1.Pump1", "Pump1.Trend", "Trend", new List { 1, 2.5d, "x", null }, "Good", T1); - /// A computed alarm: Condition left implicit, which is the common case. + /// + /// A computed alarm: Condition left implicit, which is the common case. Flagged + /// MES-reportable so the golden pins DebugAlarmStateDto field 20 (Gitea #60). + /// private static AlarmStateChanged ComputedAlarm() => new("Site1.Pump1", "HighSpeed", AlarmState.Active, 700, T1) { Level = AlarmLevel.HighHigh, - Message = "Speed critically high" + Message = "Speed critically high", + IsMesReportable = true }; /// A mirrored native alarm: every native enrichment field populated, Condition explicit. diff --git a/tests/ZB.MOM.WW.ScadaBridge.SiteRuntime.Tests/Actors/InstanceActorMesReportableSnapshotTests.cs b/tests/ZB.MOM.WW.ScadaBridge.SiteRuntime.Tests/Actors/InstanceActorMesReportableSnapshotTests.cs index 87253828..bf034679 100644 --- a/tests/ZB.MOM.WW.ScadaBridge.SiteRuntime.Tests/Actors/InstanceActorMesReportableSnapshotTests.cs +++ b/tests/ZB.MOM.WW.ScadaBridge.SiteRuntime.Tests/Actors/InstanceActorMesReportableSnapshotTests.cs @@ -8,16 +8,18 @@ using ZB.MOM.WW.ScadaBridge.Commons.Types.Flattening; using ZB.MOM.WW.ScadaBridge.SiteRuntime; using ZB.MOM.WW.ScadaBridge.SiteRuntime.Actors; using ZB.MOM.WW.ScadaBridge.SiteRuntime.Persistence; +using ZB.MOM.WW.ScadaBridge.Commons.Messages.Streaming; using ZB.MOM.WW.ScadaBridge.SiteRuntime.Scripts; +using ZB.MOM.WW.ScadaBridge.SiteRuntime.Streaming; using ZB.MOM.WW.ScadaBridge.TestSupport; namespace ZB.MOM.WW.ScadaBridge.SiteRuntime.Tests.Actors; /// /// The deployed alarm's IsMesReportable flag must reach the site-local alarm -/// snapshot that Alarms.CurrentAsync() and the Debug View query both build (the -/// flag does not cross DebugAlarmStateDto to central in this slice). It is stamped in ONE -/// place — BuildAlarmStatesSnapshot — so a computed alarm that has fired (served +/// snapshot that Alarms.CurrentAsync() and the Debug View query both build, and the +/// events published to the site stream (Gitea #60). The snapshot projection stamps every +/// row in BuildAlarmStatesSnapshot, so a computed alarm that has fired (served /// from the retained AlarmStateChanged) and one that never has (served from the /// bare Normal fallback) can never disagree about the flag. /// @@ -154,6 +156,41 @@ public class InstanceActorMesReportableSnapshotTests : TestKit, IDisposable Assert.False(Assert.Single(snapshot.Alarms, a => a.AlarmName == "TempSpike").IsMesReportable); } + /// + /// Verifies that the event the Instance Actor publishes to the site stream — the one the + /// Debug View live feed and central's Alarm Summary cache consume — carries the deployed + /// MES-reportable flag, not only the snapshot (Gitea #60). + /// + [Fact] + public void PublishedAlarmEvent_CarriesIsMesReportable() + { + const string instance = "Oven3"; + var streamManager = new SiteStreamManager(_options, NullLogger.Instance); + streamManager.Initialize(Sys); + var subscriber = CreateTestProbe(); + streamManager.Subscribe(instance, subscriber.Ref); + + var actor = ActorOf(Props.Create(() => new InstanceActor( + instance, + JsonSerializer.Serialize(TwoComputedAlarmsConfig(instance)), + _storage, + _compilationService, + _sharedScriptLibrary, + streamManager, + _options, + NullLogger.Instance, + null))); + + actor.Tell(new SetStaticAttributeCommand( + "corr-temp", instance, "Temperature", "90", DateTimeOffset.UtcNow)); + Assert.True(ExpectMsg(TimeSpan.FromSeconds(5)).Success); + + var published = subscriber.FishForMessage( + m => m.AlarmName == "HighTemp" && m.State == AlarmState.Active, + TimeSpan.FromSeconds(5)); + Assert.True(published.IsMesReportable); + } + /// void IDisposable.Dispose() {