Full OPC UA server on .NET Framework 4.8 (x86) exposing AVEVA System Platform Galaxy tags via MXAccess. Mirrors Galaxy object hierarchy as OPC UA address space, translating contained-name browse paths to tag-name runtime references. Components implemented: - Configuration: AppConfiguration with 4 sections, validator - Domain: ConnectionState, Quality, Vtq, MxDataTypeMapper, error codes - MxAccess: StaComThread, MxAccessClient (partial classes), MxProxyAdapter using strongly-typed ArchestrA.MxAccess COM interop - Galaxy Repository: SQL queries (hierarchy, attributes, change detection), ChangeDetectionService with auto-rebuild on deploy - OPC UA Server: LmxNodeManager (CustomNodeManager2), LmxOpcUaServer, OpcUaServerHost with programmatic config, SecurityPolicy None - Status Dashboard: HTTP server with HTML/JSON/health endpoints - Integration: Full 14-step startup, graceful shutdown, component wiring 175 tests (174 unit + 1 integration), all passing. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
122 lines
5.7 KiB
Markdown
122 lines
5.7 KiB
Markdown
# Galaxy Repository — Component Requirements
|
|
|
|
Parent: [HLR-002](HighLevelReqs.md#hlr-002-galaxy-hierarchy-as-opc-ua-address-space), [HLR-005](HighLevelReqs.md#hlr-005-dynamic-address-space-rebuild)
|
|
|
|
## GR-001: Hierarchy Extraction
|
|
|
|
The system shall query the Galaxy Repository database to extract all deployed objects with their parent-child containment relationships, contained names, and tag names.
|
|
|
|
### Acceptance Criteria
|
|
|
|
- Executes `queries/hierarchy.sql` against the ZB database.
|
|
- Returns a list of objects with: `gobject_id`, `tag_name`, `contained_name`, `browse_name`, `parent_gobject_id`, `is_area`.
|
|
- Objects with `parent_gobject_id = 0` are children of the root ZB node.
|
|
- Only deployed, non-template objects matching the category filter (areas, engines, user-defined objects, etc.) are returned.
|
|
- Query completes within 10 seconds on a typical Galaxy (hundreds of objects). Log a Warning if it takes longer.
|
|
|
|
### Details
|
|
|
|
- Results are ordered by `parent_gobject_id, tag_name` for deterministic tree building.
|
|
- If the query returns zero rows, log a Warning (Galaxy may have no deployed objects, or the DB connection may be misconfigured).
|
|
- Orphan detection: if a row references a `parent_gobject_id` that does not exist in the result set and is not 0, log a Warning and skip that node.
|
|
|
|
---
|
|
|
|
## GR-002: Attribute Extraction
|
|
|
|
The system shall query user-defined (dynamic) attributes for deployed objects, including data type, array flag, and array dimensions.
|
|
|
|
### Acceptance Criteria
|
|
|
|
- Executes `queries/attributes.sql` using the template chain CTE to resolve inherited attributes.
|
|
- Returns: `gobject_id`, `tag_name`, `attribute_name`, `full_tag_reference`, `mx_data_type`, `is_array`, `array_dimension`, `security_classification`.
|
|
- Attributes starting with `_` are filtered out by the query.
|
|
- `array_dimension` is correctly extracted from the `mx_value` hex bytes (positions 13-16, little-endian uint16).
|
|
|
|
### Details
|
|
|
|
- CTE recursion depth is limited to 10 levels (per the query). This is sufficient for Galaxy template hierarchies.
|
|
- If `mx_data_type` is null or not in the known set (1-8, 13-16), default to String.
|
|
- If `gobject_id` from an attribute row does not match any hierarchy object, skip that attribute (object may not be deployed).
|
|
|
|
---
|
|
|
|
## GR-003: Change Detection
|
|
|
|
The system shall poll `galaxy.time_of_last_deploy` at a configurable interval to detect when a new deployment has occurred.
|
|
|
|
### Acceptance Criteria
|
|
|
|
- Polls `SELECT time_of_last_deploy FROM galaxy` at a configurable interval (`GalaxyRepository:ChangeDetectionIntervalSeconds`, default 30 seconds).
|
|
- Compares the returned timestamp to the last known value stored in memory.
|
|
- If different, triggers a rebuild (re-run hierarchy + attributes queries, notify OPC UA server).
|
|
- First poll after startup always triggers an initial build.
|
|
- If the query fails (SQL timeout, connection error), log Warning and retry at next interval. Do not trigger a rebuild on failure.
|
|
|
|
### Details
|
|
|
|
- Polling runs on a background timer thread, not blocking the STA thread.
|
|
- `time_of_last_deploy` is a datetime column. Compare using exact equality (not range).
|
|
|
|
---
|
|
|
|
## GR-004: Rebuild on Change
|
|
|
|
When a deployment change is detected, the system shall re-query hierarchy and attributes and provide the updated structure to the OPC UA server for address space rebuild.
|
|
|
|
### Acceptance Criteria
|
|
|
|
- On change detection, re-query both hierarchy and attributes.
|
|
- Provide the new data set to the OPC UA server component for address space replacement.
|
|
- Log at Information level: "Galaxy deployment change detected. Rebuilding address space. ({ObjectCount} objects, {AttributeCount} attributes)".
|
|
- Log total rebuild time at Information level.
|
|
- If the re-query fails, log Error and keep the existing address space (do not clear it).
|
|
|
|
### Details
|
|
|
|
- Rebuild is not atomic from the DB perspective — hierarchy and attributes are two separate queries. This is acceptable; deployment is an infrequent operation.
|
|
- Raise an event/callback that the OPC UA server subscribes to: `OnGalaxyChanged(hierarchyData, attributeData)`.
|
|
|
|
---
|
|
|
|
## GR-005: Connection Configuration
|
|
|
|
Database connection parameters shall be configurable via appsettings.json (connection string using Windows Authentication by default).
|
|
|
|
### Acceptance Criteria
|
|
|
|
- Connection string in `appsettings.json` under `GalaxyRepository:ConnectionString`.
|
|
- Default: `Server=localhost;Database=ZB;Integrated Security=true` (Windows Auth).
|
|
- ADO.NET `SqlConnection` used for queries (.NET Framework 4.8 built-in).
|
|
- Connection is opened per-query (not kept open). Connection pooling handles efficiency.
|
|
- If the initial connection test at startup fails, log Error with the connection string and continue attempting (change detection polls will keep retrying).
|
|
|
|
### Details
|
|
|
|
- Command timeout: configurable via `GalaxyRepository:CommandTimeoutSeconds`, default 30 seconds.
|
|
- No ORM. Raw ADO.NET with `SqlCommand` and `SqlDataReader`. SQL text is embedded as constants (not dynamically constructed).
|
|
|
|
---
|
|
|
|
## GR-006: Query Safety
|
|
|
|
All SQL queries shall be static read-only SELECT statements. No writes to the Galaxy Repository database.
|
|
|
|
### Acceptance Criteria
|
|
|
|
- All queries are hardcoded SQL strings with no string concatenation or user-supplied parameters.
|
|
- No INSERT, UPDATE, DELETE, or DDL statements are ever executed against the Galaxy database.
|
|
- Queries use only SELECT with read-only intent.
|
|
|
|
---
|
|
|
|
## GR-007: Startup Validation
|
|
|
|
On startup, the Galaxy Repository component shall validate database connectivity.
|
|
|
|
### Acceptance Criteria
|
|
|
|
- Execute a simple test query (`SELECT 1`) against the configured database.
|
|
- If the database is unreachable, log an Error but do not prevent service startup.
|
|
- The service runs in degraded mode (empty address space) until the database becomes available and the next change detection poll succeeds.
|