Sidecar now serves a length-prefixed, kind-tagged MessagePack pipe protocol mirroring Galaxy.Host's: 4-byte BE length + 1-byte MessageKind + body, 16 MiB cap. Hello handshake validates per-process shared secret + protocol major version + caller SID via ImpersonateNamedPipeClient before any work frame runs. Five contract pairs ship in this PR: ReadRawRequest ↔ ReadRawReply ReadProcessedRequest ↔ ReadProcessedReply ReadAtTimeRequest ↔ ReadAtTimeReply ReadEventsRequest ↔ ReadEventsReply WriteAlarmEventsRequest ↔ WriteAlarmEventsReply Timestamps cross the wire as DateTime ticks (long) to dodge MessagePack's DateTime kind/timezone quirks; both sides convert with DateTime(ticks, Utc). Sample values cross as MessagePack-serialized byte[] so the .NET 10 client (PR 3.4) deserializes per the tag's mx_data_type without the sidecar needing to know OPC UA types. HistorianFrameHandler dispatches by MessageKind to IHistorianDataSource (the PR 3.2 lifted interface) for reads, and to a new IAlarmEventWriter strategy for the alarm-event persistence path. Per-call exceptions surface as Success=false replies so a single bad request doesn't kill the connection. WriteAlarmEvents replies carry per-event success flags; the SQLite store-and-forward sink retries failed slots on the next drain tick. Program.cs spins the pipe server when OTOPCUA_HISTORIAN_ENABLED=true. Pipe- only mode (default false) preserves PR 3.1's smoke-test behaviour: the host still validates env vars and waits for Ctrl-C, but doesn't initialize the Wonderware SDK. Sidecar test project gains 8 round-trip tests (37 total now): every contract pair round-trips through FrameReader/FrameWriter via in-memory streams, the handler surfaces historian exceptions cleanly, WriteAlarmEvents per-event status flows through, and the no-writer-configured path returns a clean error reply. Added MessagePack 2.5.187 to the sidecar csproj. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
13 KiB
13 KiB