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>
118 lines
4.7 KiB
Markdown
118 lines
4.7 KiB
Markdown
# Service Host — Component Requirements
|
|
|
|
Parent: [HLR-006](HighLevelReqs.md#hlr-006-windows-service-hosting), [HLR-007](HighLevelReqs.md#hlr-007-logging)
|
|
|
|
## SVC-001: TopShelf Hosting
|
|
|
|
The application shall use TopShelf for Windows service lifecycle (install, uninstall, start, stop) and interactive console mode for development.
|
|
|
|
### Acceptance Criteria
|
|
|
|
- TopShelf HostFactory configures the service with name `LmxOpcUa`, display name `LMX OPC UA Server`.
|
|
- Service installs via command line: `ZB.MOM.WW.LmxOpcUa.Host.exe install`.
|
|
- Service uninstalls via: `ZB.MOM.WW.LmxOpcUa.Host.exe uninstall`.
|
|
- Service runs as LocalSystem account (needed for MXAccess COM access and Windows Auth to SQL Server).
|
|
- Interactive console mode (exe with no args) works for development/debugging.
|
|
- `StartAutomatically` is set for Windows service registration.
|
|
|
|
### Details
|
|
|
|
- Platform target: x86 (32-bit) — required for MXAccess COM interop.
|
|
- Service description: "OPC UA server exposing System Platform Galaxy tags via MXAccess."
|
|
|
|
---
|
|
|
|
## SVC-002: Serilog Logging
|
|
|
|
The application shall configure Serilog with a rolling daily file sink and console sink, with log files retained for a configurable number of days (default 31).
|
|
|
|
### Acceptance Criteria
|
|
|
|
- Console sink active (for interactive/debug mode).
|
|
- Rolling daily file sink writing to `logs/lmxopcua-YYYYMMDD.log`.
|
|
- Retained file count: configurable, default 31 days.
|
|
- Minimum log level: configurable, default Information.
|
|
- Log file path: configurable, default `logs/lmxopcua-.log`.
|
|
- Serilog is initialized before any other component (first thing in Main).
|
|
- `Log.CloseAndFlush()` called in finally block on exit.
|
|
|
|
### Details
|
|
|
|
- Structured logging with Serilog message templates (not string.Format).
|
|
- Log output includes timestamp, level, source context, message, and exception.
|
|
- Fatal exceptions are caught at the top level and logged before exit.
|
|
|
|
---
|
|
|
|
## SVC-003: Configuration
|
|
|
|
The application shall load configuration from appsettings.json with support for environment-specific overrides (appsettings.*.json) and environment variables.
|
|
|
|
### Acceptance Criteria
|
|
|
|
- `appsettings.json` is the primary configuration file.
|
|
- Environment-specific overrides via `appsettings.{environment}.json`.
|
|
- Configuration sections: `OpcUa`, `MxAccess`, `GalaxyRepository`, `Dashboard`.
|
|
- Missing optional configuration keys use documented defaults (service does not crash).
|
|
- Invalid configuration (e.g., port = -1) is detected at startup with a clear error message.
|
|
|
|
### Details
|
|
|
|
- Config is loaded once at startup. No hot-reload (service restart required for config changes). This is appropriate for an industrial service.
|
|
- All configurable values and their defaults are documented in `appsettings.json`.
|
|
|
|
---
|
|
|
|
## SVC-004: Graceful Shutdown
|
|
|
|
On service stop, the application shall gracefully shut down all components and flush logs before exiting.
|
|
|
|
### Acceptance Criteria
|
|
|
|
- TopShelf WhenStopped triggers orderly shutdown.
|
|
- Shutdown sequence: (1) stop change detection polling, (2) stop OPC UA server (stop accepting new sessions, complete pending operations), (3) disconnect MXAccess (cleanup all COM objects), (4) stop status dashboard HTTP listener, (5) flush Serilog.
|
|
- Shutdown completes within 30 seconds (Windows SCM timeout).
|
|
- All IDisposable components are disposed in reverse-creation order.
|
|
|
|
### Details
|
|
|
|
- `CancellationTokenSource` signals all background loops (monitor, change detection, HTTP listener) to stop.
|
|
- Log "Service shutdown complete" at Information level as the final log entry before flush.
|
|
|
|
---
|
|
|
|
## SVC-005: Startup Sequence
|
|
|
|
The service shall start components in a defined order, with failure handling at each step.
|
|
|
|
### Acceptance Criteria
|
|
|
|
- Startup sequence:
|
|
1. Load configuration
|
|
2. Initialize Serilog
|
|
3. Start STA thread
|
|
4. Connect to MXAccess
|
|
5. Query Galaxy Repository for initial build
|
|
6. Build OPC UA address space
|
|
7. Start OPC UA server listener
|
|
8. Start change detection polling
|
|
9. Start status dashboard HTTP listener
|
|
- Failure in steps 1-4 prevents startup (service fails to start).
|
|
- Failure in steps 5-9 logs Error but allows the service to run in degraded mode.
|
|
|
|
### Details
|
|
|
|
- Degraded mode means the service is running but may have an empty address space (waiting for Galaxy DB) or no dashboard (port conflict). MXAccess connection is the minimum required for the service to be useful.
|
|
|
|
---
|
|
|
|
## SVC-006: Unhandled Exception Handling
|
|
|
|
The service shall handle unexpected crashes gracefully.
|
|
|
|
### Acceptance Criteria
|
|
|
|
- Register `AppDomain.CurrentDomain.UnhandledException` handler that logs Fatal before the process terminates.
|
|
- TopShelf service recovery is configured: restart on failure with 60-second delay.
|
|
- Fatal-level log entry includes the full exception details.
|