Phase 2 PR 5 — Wonderware Historian SDK port into Driver.Galaxy.Host #4
Closed
dohertj2
wants to merge 1 commits from
phase-2-pr5-historian into phase-2-pr4-findings
pull from: phase-2-pr5-historian
merge into: dohertj2:phase-2-pr4-findings
dohertj2:master
dohertj2:v2
dohertj2:abcip-pr4-iwritable
dohertj2:abcip-pr3-ireadable
dohertj2:abcip-pr2-scaffolding
dohertj2:abcip-pr1-pollgroupengine
dohertj2:phase-6-1-stream-e3-inflight-counter
dohertj2:phase-6-4-stream-b-staging-tables
dohertj2:phase-6-1-resilience-status-publisher
dohertj2:phase-6-1-stream-a-multihost-dispatch
dohertj2:phase-6-1-stream-a-resilience-config
dohertj2:phase-6-4-stream-d-identification
dohertj2:phase-6-1-stream-b4-hosted-service
dohertj2:v2-release-readiness-blocker3-closed
dohertj2:phase-6-3-stream-c-state-publisher
dohertj2:phase-6-3-stream-a-topology-loader
dohertj2:v2-release-readiness-blocker2-closed
dohertj2:phase-6-1-stream-d-wiring-followup
dohertj2:v2-release-readiness-blocker1-closed
dohertj2:phase-6-2-stream-c-dispatch-wiring-followup
dohertj2:v2-release-readiness-capstone
dohertj2:phase-6-4-exit-gate
dohertj2:phase-6-4-stream-ab-data-layer
dohertj2:phase-6-3-exit-gate
dohertj2:phase-6-3-stream-b-service-level
dohertj2:phase-6-2-exit-gate
dohertj2:phase-6-2-stream-d-validated-authoring
dohertj2:phase-6-2-stream-c-dispatch-wiring
dohertj2:phase-6-2-stream-b-permission-trie
dohertj2:phase-6-2-stream-a-ldap-role-mapping
dohertj2:phase-6-1-exit-gate
dohertj2:phase-6-1-stream-e-admin-hosts
dohertj2:phase-6-1-stream-d-litedb-sealed-cache
dohertj2:phase-6-1-stream-c-health-logging
dohertj2:phase-6-1-stream-b-stability
dohertj2:phase-6-1-stream-a-resilience
dohertj2:phase-6-reconcile
dohertj2:phase-6-plans-drafts
dohertj2:phase-3-pr76-opcua-client-history
dohertj2:phase-3-pr75-opcua-client-alarms
dohertj2:phase-3-pr74-opcua-client-session-reconnect
dohertj2:phase-3-pr73-opcua-client-browse-enrichment
dohertj2:phase-3-pr72-opcua-client-failover
dohertj2:phase-3-pr71-opcua-client-cert-auth
dohertj2:phase-3-pr70-opcua-client-security-policy
dohertj2:phase-3-pr69-opcua-client-subscribe-probe
dohertj2:phase-3-pr68-opcua-client-discovery
dohertj2:phase-3-pr67-opcua-client-read-write
dohertj2:phase-3-pr66-opcua-client-scaffold
dohertj2:phase-3-pr65-s7-discovery-subscribe-probe
dohertj2:phase-3-pr64-s7-read-write
dohertj2:phase-3-pr63-s7-address-parser
dohertj2:phase-3-pr62-s7-driver-scaffold
dohertj2:phase-2-pr61-scrub-v1-archive-residue
dohertj2:phase-3-pr60-mitsubishi-quirk-tests
dohertj2:phase-3-pr59-melsec-address-helper
dohertj2:phase-3-pr58-mitsubishi-sim-profile
dohertj2:phase-3-pr57-s7-quirk-tests
dohertj2:phase-3-pr56-s7-sim-profile
dohertj2:phase-3-pr55-mitsubishi-research-doc
dohertj2:phase-3-pr54-s7-research-doc
dohertj2:phase-3-pr53-dl205-reconnect
dohertj2:phase-3-pr52-dl205-exception-codes
dohertj2:phase-3-pr51-dl205-xinput
dohertj2:phase-3-pr50-dl205-coil-mapping
dohertj2:phase-3-pr49-dl205-fc-caps
dohertj2:phase-3-pr48-dl205-cdab-float
dohertj2:phase-3-pr47-dl205-vmemory
dohertj2:phase-3-pr46-dl205-bcd
dohertj2:phase-3-pr45-dl205-string-byte-order
dohertj2:phase-3-pr44-pymodbus-validation-fixes
dohertj2:phase-3-pr43-pymodbus-swap
dohertj2:phase-3-pr42-modbuspal-profiles
dohertj2:phase-3-pr41-dl205-quirks-doc
dohertj2:phase-3-pr40-livestack-write-subscribe
dohertj2:phase-3-pr39-elevated-shell-skip
dohertj2:phase-3-pr38-historyread-servicehandler
dohertj2:phase-3-pr37-live-stack-smoke
dohertj2:phase-3-pr36-aveva-prerequisites
dohertj2:phase-3-pr35-history-readtime-readevents
dohertj2:phase-3-pr34-host-status-publisher-page
dohertj2:phase-3-pr33-driverhoststatus-entity
dohertj2:phase-3-pr32-multi-driver-integration
dohertj2:phase-3-pr31-live-ldap-ad-compat
dohertj2:phase-3-pr30-modbus-integration-scaffold
dohertj2:phase-3-pr29-account-page
dohertj2:phase-3-pr28-cert-trust
dohertj2:phase-3-pr27-fleet-dashboard
dohertj2:phase-3-pr26-server-write-authz
dohertj2:phase-3-pr25-modbus-test-plan
dohertj2:phase-3-pr24-modbus-types
dohertj2:phase-3-pr23-modbus-probe
dohertj2:phase-3-pr22-modbus-subscribe
dohertj2:phase-3-pr21-modbus-driver
dohertj2:phase-3-pr20-lmx-followups
dohertj2:phase-3-pr19-ldap-security
dohertj2:phase-3-pr18-delete-v1
dohertj2:phase-3-pr17-server-startup
dohertj2:phase-3-pr16-opcua-server
dohertj2:phase-3-pr15-alarm-contract
dohertj2:phase-2-pr14-alarm-subsystem
dohertj2:phase-2-pr13-runtime-probe
dohertj2:phase-2-pr12-quality-mapper
dohertj2:phase-2-pr11-history-events
dohertj2:phase-2-pr10-history-attime
dohertj2:phase-2-pr9-alarms
dohertj2:phase-2-pr8-alarms-hoststatus
dohertj2:phase-2-pr7-history-processed
dohertj2:phase-2-pr6-monitor-findings
dohertj2:phase-2-pr4-findings
dohertj2:phase-2-stream-d
dohertj2:phase-1-configuration
dohertj2:phase-0-rename
Reference in New Issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Delete Branch "phase-2-pr5-historian"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
Phase 2 PR 5 — port the Wonderware Historian SDK into
Driver.Galaxy.Host/Backend/Historian/, wiringMxAccessGalaxyBackend.HistoryReadAsyncend-to-end and closing the last Phase 2 Task B.1.h follow-up that was still returning a placeholder error.Key decisions:
Opc.Ua.DataValueon the hot historian path, which would have required draggingOPCFoundation.NetStandard.Opc.Ua.Serverinto net48 x86 Galaxy.Host and leaking OPC types across the IPC boundary. Instead, PR 5 introducesHistorianSample+HistorianAggregateSamplePOCOs that carry the raw MX quality byte through the pipe unchanged; the Proxy side does the OPC translation via the existingQualityMapperalready used for live reads. Decision #13'sGalaxyDataValuecontract survives intact — no Shared wire break vs PR 4.HistorianPluginLoader+AssemblyResolve+Assembly.LoadFrom. That indirection existed solely because the plugin was staged inHost/bin/Debug/net48/Historian/at deploy time. Since Driver.Galaxy.Host is already Galaxy-specific, the plugin boundary is pure overhead here — the port lives directly underBackend/Historian/and Galaxy.Host.csproj carries the SDK refs + native DLL staging inline.HistorianClusterEndpointPickeris the thread-safe pure-logic picker ported unchanged (injected clock, per-node cooldown, case-insensitive de-dup).ConnectToAnyHealthyNodeiterates healthy candidates, clones config per attempt, marks healthy-on-success / failed-on-exception, and throws with the last exception chained when all nodes exhaust.ReadRawAsyncis wired through IPC now (HistoryReadRequestwas already in Shared.Contracts).ReadAggregateAsync/ReadAtTimeAsync/ReadEventsAsync/GetHealthSnapshotare ported-but-not-yet-IPC-exposed — they stay internal to Galaxy.Host until PR 6+ surfaces them via new contract message kinds.Changes
src/.../Backend/Historian/Backend/MxAccessGalaxyBackend.csHistoryReadAsyncnow delegates toIHistorianDataSource.ReadRawAsync+ maps samples toGalaxyDataValue; gainsIDisposableto close historian connections at shutdownProgram.csBuildHistorianIfEnabled()readsOTOPCUA_HISTORIAN_*env vars, returns null when disabled so the backend surfaces a cleanHistorian disablederrorDriver.Galaxy.Host.csprojaahClientManaged+aahClientCommon; stagesaahClient.dll+Historian.CBE.dll+Historian.DPAPI.dll+ArchestrA.CloudHistorian.Contract.dllalongside the host exe;InternalsVisibleTo("...Host.Tests")added so the endpoint picker stays testabletests/.../Host.Tests/HistorianClusterEndpointPickerTests.csServerName, cooldown enters/expires, MarkHealthy clears, all-in-cooldown empty list, Snapshot reports state, case-insensitive de-duptests/.../Host.Tests/HistorianWiringTests.csHistorianSample(42.5, Good, ts)toGalaxyDataValue{StatusCode=0u, source ts matches, MessagePack bytes non-null}Test plan
dotnet build src/ZB.MOM.WW.OtOpcUa.Driver.Galaxy.Host/— 0 errorsdotnet build ZB.MOM.WW.OtOpcUa.slnx— 0 errors, 202 pre-existing warningsdotnet test tests/ZB.MOM.WW.OtOpcUa.Driver.Galaxy.Host.Tests/ --filter "Category=Unit"— 24/24 pass (9 new + 15 pre-existing)dotnet test ZB.MOM.WW.OtOpcUa.slnx— expect full solution pass count consistent with PR 4 baselineOTOPCUA_HISTORIAN_ENABLED=true OTOPCUA_HISTORIAN_SERVER=<hostname>and fire a HistoryRead from the Client CLI — should return live historical samples instead of the PR 4 placeholder errorFollow-ups / deferred
IHistoryProvider.ReadProcessedAsyncwiring.AlarmExtension→OnAlarmEvent) fromMxAccessGalaxyBackend. Shares the IPCConnectionSinkpath that PR 4 built forOnDataChange.GalaxyRuntimeProbeManager→OnHostStatusChanged. Same pattern.Historian.Aveva+Historian.Aveva.Testsprojects (the two remaining archived-but-still-building v1 surfaces) can be removed alongside the rest of the v1 stack.🤖 Generated with Claude Code
Closing � the PR5 historian commit (
6df1a79) was already an ancestor of v2 when PR #3 merged (it sat on the pr4-findings branch). No additional work required; the Historian port is live on v2.Pull request closed