3603 lines
40 KiB
Markdown
3603 lines
40 KiB
Markdown
# \# AquaCom Integration Gateway – Architecture
|
||
|
||
#
|
||
|
||
# \## 1. Purpose
|
||
|
||
#
|
||
|
||
# This document defines the high-level software architecture of the \*\*AquaCom Integration Gateway\*\*.
|
||
|
||
#
|
||
|
||
# It describes:
|
||
|
||
#
|
||
|
||
# \- major system components;
|
||
|
||
# \- dependency direction;
|
||
|
||
# \- data flows;
|
||
|
||
# \- architectural boundaries;
|
||
|
||
# \- live-data handling;
|
||
|
||
# \- historical-data handling;
|
||
|
||
# \- OPC UA integration;
|
||
|
||
# \- storage integration;
|
||
|
||
# \- diagnostics;
|
||
|
||
# \- security boundaries;
|
||
|
||
# \- extension points.
|
||
|
||
#
|
||
|
||
# Detailed functional requirements are defined in:
|
||
|
||
#
|
||
|
||
# ```text
|
||
|
||
# docs/product/software-specification.md
|
||
|
||
# ```
|
||
|
||
#
|
||
|
||
# Implementation requirements and Codex-specific development rules are defined in:
|
||
|
||
#
|
||
|
||
# ```text
|
||
|
||
# docs/product/codex-implementation-specification.md
|
||
|
||
# AGENTS.md
|
||
|
||
# ```
|
||
|
||
#
|
||
|
||
# Detailed subsystem architecture is documented under:
|
||
|
||
#
|
||
|
||
# ```text
|
||
|
||
# docs/architecture/
|
||
|
||
# ```
|
||
|
||
#
|
||
|
||
# AquaCom-specific protocol knowledge is documented under:
|
||
|
||
#
|
||
|
||
# ```text
|
||
|
||
# docs/protocol/
|
||
|
||
# ```
|
||
|
||
#
|
||
|
||
# \---
|
||
|
||
#
|
||
|
||
# \# 2. System purpose
|
||
|
||
#
|
||
|
||
# The AquaCom Integration Gateway provides a modern integration boundary between AquaCom-compatible field equipment and higher-level systems.
|
||
|
||
#
|
||
|
||
# The gateway shall:
|
||
|
||
#
|
||
|
||
# \- communicate with AquaCom field devices;
|
||
|
||
# \- acquire current process values;
|
||
|
||
# \- retrieve historical process values;
|
||
|
||
# \- normalize AquaCom-specific information into a protocol-independent model;
|
||
|
||
# \- expose current values using OPC UA;
|
||
|
||
# \- expose historical values using OPC UA Historical Access;
|
||
|
||
# \- store historical data in one or more configurable destinations;
|
||
|
||
# \- recover historical information following communication interruptions;
|
||
|
||
# \- provide operational and protocol diagnostics.
|
||
|
||
#
|
||
|
||
# The gateway shall not make higher-level systems dependent on AquaCom-specific behavior.
|
||
|
||
#
|
||
|
||
# \---
|
||
|
||
#
|
||
|
||
# \# 3. Architectural principle
|
||
|
||
#
|
||
|
||
# The central architecture is:
|
||
|
||
#
|
||
|
||
# ```text
|
||
|
||
# AquaCom field device
|
||
|
||
#   │
|
||
|
||
#   ▼
|
||
|
||
# AquaCom Transport
|
||
|
||
#   │
|
||
|
||
#   ▼
|
||
|
||
# AquaCom Protocol Engine
|
||
|
||
#   │
|
||
|
||
#   ▼
|
||
|
||
# Station / Session Manager
|
||
|
||
#   │
|
||
|
||
#   ▼
|
||
|
||
# Canonical Data Model
|
||
|
||
#   │
|
||
|
||
#   ├─────────────────────► Current-State Service
|
||
|
||
#   │ │
|
||
|
||
#   │ ▼
|
||
|
||
#   │ OPC UA Data Access
|
||
|
||
#   │
|
||
|
||
#   └─────────────────────► Historical Pipeline
|
||
|
||
#   │
|
||
|
||
#   ┌───────────┼────────────┐
|
||
|
||
#   │ │ │
|
||
|
||
#   ▼ ▼ ▼
|
||
|
||
#   Repository Storage A Storage B
|
||
|
||
#   │
|
||
|
||
#   ▼
|
||
|
||
#   OPC UA Historical Access
|
||
|
||
# ```
|
||
|
||
#
|
||
|
||
# The canonical data model forms the boundary between AquaCom-specific functionality and all northbound integrations.
|
||
|
||
#
|
||
|
||
# \---
|
||
|
||
#
|
||
|
||
# \# 4. Architectural goals
|
||
|
||
#
|
||
|
||
# The architecture shall support:
|
||
|
||
#
|
||
|
||
# \- protocol isolation;
|
||
|
||
# \- storage independence;
|
||
|
||
# \- stable internal identifiers;
|
||
|
||
# \- stable OPC UA NodeIds;
|
||
|
||
# \- correct handling of source timestamps;
|
||
|
||
# \- reliable history recovery;
|
||
|
||
# \- multiple historical storage destinations;
|
||
|
||
# \- store-and-forward;
|
||
|
||
# \- independent subsystem testing;
|
||
|
||
# \- restart recovery;
|
||
|
||
# \- future replacement of individual technologies;
|
||
|
||
# \- future addition of other northbound interfaces.
|
||
|
||
#
|
||
|
||
# The architecture shall avoid tight coupling between:
|
||
|
||
#
|
||
|
||
# ```text
|
||
|
||
# AquaCom
|
||
|
||
# OPC UA
|
||
|
||
# Database technology
|
||
|
||
# Historian technology
|
||
|
||
# SCADA platform
|
||
|
||
# ```
|
||
|
||
#
|
||
|
||
# \---
|
||
|
||
#
|
||
|
||
# \# 5. Architectural boundaries
|
||
|
||
#
|
||
|
||
# The following boundaries are mandatory.
|
||
|
||
#
|
||
|
||
# \## 5.1 AquaCom boundary
|
||
|
||
#
|
||
|
||
# Only the AquaCom subsystem may:
|
||
|
||
#
|
||
|
||
# \- encode AquaCom telegrams;
|
||
|
||
# \- decode AquaCom telegrams;
|
||
|
||
# \- calculate or verify AquaCom checksums;
|
||
|
||
# \- interpret AquaCom operation codes;
|
||
|
||
# \- interpret AquaCom addressing;
|
||
|
||
# \- interpret AquaCom-specific value formats.
|
||
|
||
#
|
||
|
||
# No OPC UA or storage module shall perform AquaCom protocol processing.
|
||
|
||
#
|
||
|
||
# \---
|
||
|
||
#
|
||
|
||
# \## 5.2 Canonical model boundary
|
||
|
||
#
|
||
|
||
# AquaCom data shall be converted into canonical gateway objects before being forwarded to:
|
||
|
||
#
|
||
|
||
# \- current-state handling;
|
||
|
||
# \- history handling;
|
||
|
||
# \- OPC UA;
|
||
|
||
# \- storage systems;
|
||
|
||
# \- diagnostics where appropriate.
|
||
|
||
#
|
||
|
||
# The canonical model shall remain independent of AquaCom and OPC UA.
|
||
|
||
#
|
||
|
||
# \---
|
||
|
||
#
|
||
|
||
# \## 5.3 OPC UA boundary
|
||
|
||
#
|
||
|
||
# The OPC UA subsystem shall consume canonical gateway information.
|
||
|
||
#
|
||
|
||
# It shall not:
|
||
|
||
#
|
||
|
||
# \- communicate directly with AquaCom stations;
|
||
|
||
# \- decode telegrams;
|
||
|
||
# \- synchronously request historical data from an RTU;
|
||
|
||
# \- depend upon a particular storage technology.
|
||
|
||
#
|
||
|
||
# \---
|
||
|
||
#
|
||
|
||
# \## 5.4 Storage boundary
|
||
|
||
#
|
||
|
||
# Storage destinations shall receive canonical historical records.
|
||
|
||
#
|
||
|
||
# Storage implementations shall not depend upon:
|
||
|
||
#
|
||
|
||
# \- AquaCom telegrams;
|
||
|
||
# \- AquaCom transport;
|
||
|
||
# \- OPC UA server internals.
|
||
|
||
#
|
||
|
||
# \---
|
||
|
||
#
|
||
|
||
# \# 6. Source tree
|
||
|
||
#
|
||
|
||
# The logical source structure is:
|
||
|
||
#
|
||
|
||
# ```text
|
||
|
||
# src/
|
||
|
||
# ├── core/
|
||
|
||
# ├── aquacom/
|
||
|
||
# ├── history/
|
||
|
||
# ├── storage/
|
||
|
||
# ├── opcua/
|
||
|
||
# ├── diagnostics/
|
||
|
||
# └── host/
|
||
|
||
# ```
|
||
|
||
#
|
||
|
||
# The exact language-specific package or project structure may differ, but the architectural responsibilities shall remain equivalent.
|
||
|
||
#
|
||
|
||
# \---
|
||
|
||
#
|
||
|
||
# \# 7. Dependency direction
|
||
|
||
#
|
||
|
||
# Allowed dependencies shall broadly follow:
|
||
|
||
#
|
||
|
||
# ```text
|
||
|
||
#   host
|
||
|
||
#   │
|
||
|
||
#   ┌───────────┼─────────────┐
|
||
|
||
#   │ │ │
|
||
|
||
#   ▼ ▼ ▼
|
||
|
||
#   opcua history diagnostics
|
||
|
||
#   │ │
|
||
|
||
#   │ storage
|
||
|
||
#   │ │
|
||
|
||
#   └──────┬────┘
|
||
|
||
#   ▼
|
||
|
||
#   core
|
||
|
||
#   ▲
|
||
|
||
#   │
|
||
|
||
#   aquacom
|
||
|
||
# ```
|
||
|
||
#
|
||
|
||
# The most important rule is:
|
||
|
||
#
|
||
|
||
# ```text
|
||
|
||
# core
|
||
|
||
# ```
|
||
|
||
#
|
||
|
||
# shall not depend upon:
|
||
|
||
#
|
||
|
||
# ```text
|
||
|
||
# aquacom
|
||
|
||
# opcua
|
||
|
||
# storage technology
|
||
|
||
# ```
|
||
|
||
#
|
||
|
||
# \---
|
||
|
||
#
|
||
|
||
# \# 8. Core subsystem
|
||
|
||
#
|
||
|
||
# The `core` subsystem contains protocol-independent domain concepts.
|
||
|
||
#
|
||
|
||
# Examples include:
|
||
|
||
#
|
||
|
||
# ```text
|
||
|
||
# StationId
|
||
|
||
# PointId
|
||
|
||
# CurrentValue
|
||
|
||
# HistoricalSample
|
||
|
||
# DataQuality
|
||
|
||
# AcquisitionSource
|
||
|
||
# CommunicationState
|
||
|
||
# StationState
|
||
|
||
# HistorySynchronizationState
|
||
|
||
# ```
|
||
|
||
#
|
||
|
||
# The core subsystem defines shared contracts used between other modules.
|
||
|
||
#
|
||
|
||
# It shall contain no AquaCom protocol logic.
|
||
|
||
#
|
||
|
||
# It shall contain no OPC UA-specific types.
|
||
|
||
#
|
||
|
||
# It shall contain no database-specific types.
|
||
|
||
#
|
||
|
||
# \---
|
||
|
||
#
|
||
|
||
# \# 9. AquaCom subsystem
|
||
|
||
#
|
||
|
||
# The AquaCom subsystem contains:
|
||
|
||
#
|
||
|
||
# ```text
|
||
|
||
# Transport
|
||
|
||
# Protocol codec
|
||
|
||
# Telegram validation
|
||
|
||
# Station/session handling
|
||
|
||
# Live acquisition
|
||
|
||
# Historical acquisition
|
||
|
||
# Protocol diagnostics
|
||
|
||
# ```
|
||
|
||
#
|
||
|
||
# Logical structure:
|
||
|
||
#
|
||
|
||
# ```text
|
||
|
||
# AquaCom Transport
|
||
|
||
#   │
|
||
|
||
#   ▼
|
||
|
||
# Protocol Codec
|
||
|
||
#   │
|
||
|
||
#   ▼
|
||
|
||
# Protocol Operations
|
||
|
||
#   │
|
||
|
||
#   ▼
|
||
|
||
# Station Session
|
||
|
||
#   │
|
||
|
||
#   ├── Live Acquisition
|
||
|
||
#   └── Historical Acquisition
|
||
|
||
# ```
|
||
|
||
#
|
||
|
||
# Protocol implementation shall be evidence-based.
|
||
|
||
#
|
||
|
||
# Undocumented AquaCom behavior shall not be guessed.
|
||
|
||
#
|
||
|
||
# \---
|
||
|
||
#
|
||
|
||
# \# 10. AquaCom transport
|
||
|
||
#
|
||
|
||
# The transport layer is responsible for communication only.
|
||
|
||
#
|
||
|
||
# It may support implementations such as:
|
||
|
||
#
|
||
|
||
# ```text
|
||
|
||
# TCP
|
||
|
||
# Serial
|
||
|
||
# Serial-over-IP
|
||
|
||
# Other supported AquaCom transport
|
||
|
||
# ```
|
||
|
||
#
|
||
|
||
# The transport layer shall not interpret process values.
|
||
|
||
#
|
||
|
||
# Conceptual interface:
|
||
|
||
#
|
||
|
||
# ```text
|
||
|
||
# open
|
||
|
||
# close
|
||
|
||
# send
|
||
|
||
# receive
|
||
|
||
# health
|
||
|
||
# ```
|
||
|
||
#
|
||
|
||
# \---
|
||
|
||
#
|
||
|
||
# \# 11. AquaCom protocol engine
|
||
|
||
#
|
||
|
||
# The protocol engine is responsible for:
|
||
|
||
#
|
||
|
||
# \- framing;
|
||
|
||
# \- telegram validation;
|
||
|
||
# \- checksum handling;
|
||
|
||
# \- request encoding;
|
||
|
||
# \- response decoding;
|
||
|
||
# \- protocol error interpretation.
|
||
|
||
#
|
||
|
||
# Conceptual transformation:
|
||
|
||
#
|
||
|
||
# ```text
|
||
|
||
# raw bytes
|
||
|
||
#   │
|
||
|
||
#   ▼
|
||
|
||
# AquaCom message
|
||
|
||
#   │
|
||
|
||
#   ▼
|
||
|
||
# logical protocol result
|
||
|
||
# ```
|
||
|
||
#
|
||
|
||
# The codec shall be independently testable without a physical AquaCom device.
|
||
|
||
#
|
||
|
||
# \---
|
||
|
||
#
|
||
|
||
# \# 12. Station/session manager
|
||
|
||
#
|
||
|
||
# Each AquaCom station has an independent logical session.
|
||
|
||
#
|
||
|
||
# Conceptual station states:
|
||
|
||
#
|
||
|
||
# ```text
|
||
|
||
# DISABLED
|
||
|
||
# INITIALIZING
|
||
|
||
# CONNECTING
|
||
|
||
# ONLINE
|
||
|
||
# DEGRADED
|
||
|
||
# OFFLINE
|
||
|
||
# RECOVERING
|
||
|
||
# ```
|
||
|
||
#
|
||
|
||
# One failing station shall not stop communication with unrelated stations.
|
||
|
||
#
|
||
|
||
# The Station Manager owns:
|
||
|
||
#
|
||
|
||
# \- station lifecycle;
|
||
|
||
# \- communication status;
|
||
|
||
# \- retries;
|
||
|
||
# \- scheduling;
|
||
|
||
# \- station diagnostics;
|
||
|
||
# \- history recovery coordination.
|
||
|
||
#
|
||
|
||
# \---
|
||
|
||
#
|
||
|
||
# \# 13. Canonical data model
|
||
|
||
#
|
||
|
||
# The gateway uses a protocol-independent canonical model.
|
||
|
||
#
|
||
|
||
# \## 13.1 CurrentValue
|
||
|
||
#
|
||
|
||
# Conceptually:
|
||
|
||
#
|
||
|
||
# ```text
|
||
|
||
# CurrentValue
|
||
|
||
#   StationId
|
||
|
||
#   PointId
|
||
|
||
#   Value
|
||
|
||
#   DataType
|
||
|
||
#   Quality
|
||
|
||
#   SourceTimestamp
|
||
|
||
#   ReceivedTimestamp
|
||
|
||
#   UpdatedTimestamp
|
||
|
||
#   AcquisitionSource
|
||
|
||
# ```
|
||
|
||
#
|
||
|
||
# \---
|
||
|
||
#
|
||
|
||
# \## 13.2 HistoricalSample
|
||
|
||
#
|
||
|
||
# Conceptually:
|
||
|
||
#
|
||
|
||
# ```text
|
||
|
||
# HistoricalSample
|
||
|
||
#   StationId
|
||
|
||
#   PointId
|
||
|
||
#   Value
|
||
|
||
#   DataType
|
||
|
||
#   Quality
|
||
|
||
#   SourceTimestamp
|
||
|
||
#   ReceivedTimestamp
|
||
|
||
#   AcquisitionSource
|
||
|
||
#   AcquisitionId
|
||
|
||
# ```
|
||
|
||
#
|
||
|
||
# Historical samples shall retain the timestamp associated with the process state.
|
||
|
||
#
|
||
|
||
# \---
|
||
|
||
#
|
||
|
||
# \# 14. Timestamp model
|
||
|
||
#
|
||
|
||
# The gateway shall distinguish at least:
|
||
|
||
#
|
||
|
||
# ```text
|
||
|
||
# SourceTimestamp
|
||
|
||
# ReceivedTimestamp
|
||
|
||
# ```
|
||
|
||
#
|
||
|
||
# Where applicable also:
|
||
|
||
#
|
||
|
||
# ```text
|
||
|
||
# UpdatedTimestamp
|
||
|
||
# ServerTimestamp
|
||
|
||
# ```
|
||
|
||
#
|
||
|
||
# Their meanings are:
|
||
|
||
#
|
||
|
||
# | Timestamp | Meaning |
|
||
|
||
# |---|---|
|
||
|
||
# | SourceTimestamp | Time associated with the value at the source |
|
||
|
||
# | ReceivedTimestamp | Time the gateway received the information |
|
||
|
||
# | UpdatedTimestamp | Time current gateway state was changed |
|
||
|
||
# | ServerTimestamp | Timestamp used by the OPC UA server |
|
||
|
||
#
|
||
|
||
# The following must never be assumed:
|
||
|
||
#
|
||
|
||
# ```text
|
||
|
||
# ReceivedTimestamp = SourceTimestamp
|
||
|
||
# ```
|
||
|
||
#
|
||
|
||
# \---
|
||
|
||
#
|
||
|
||
# \# 15. Fundamental historical rule
|
||
|
||
#
|
||
|
||
# The fundamental historical-data rule is:
|
||
|
||
#
|
||
|
||
# > A historical sample represents the process at its SourceTimestamp, not at the time the gateway receives the sample.
|
||
|
||
#
|
||
|
||
# Example:
|
||
|
||
#
|
||
|
||
# ```text
|
||
|
||
# Historical value:
|
||
|
||
#   SourceTimestamp = 14:05
|
||
|
||
#   ReceivedTimestamp = 18:30
|
||
|
||
# ```
|
||
|
||
#
|
||
|
||
# The value belongs to history at:
|
||
|
||
#
|
||
|
||
# ```text
|
||
|
||
# 14:05
|
||
|
||
# ```
|
||
|
||
#
|
||
|
||
# It shall not become a new current process value at:
|
||
|
||
#
|
||
|
||
# ```text
|
||
|
||
# 18:30
|
||
|
||
# ```
|
||
|
||
#
|
||
|
||
# \---
|
||
|
||
#
|
||
|
||
# \# 16. Live-data architecture
|
||
|
||
#
|
||
|
||
# Live AquaCom values follow:
|
||
|
||
#
|
||
|
||
# ```text
|
||
|
||
# AquaCom response
|
||
|
||
#   │
|
||
|
||
#   ▼
|
||
|
||
# Protocol decode
|
||
|
||
#   │
|
||
|
||
#   ▼
|
||
|
||
# Point mapping
|
||
|
||
#   │
|
||
|
||
#   ▼
|
||
|
||
# Canonical CurrentValue
|
||
|
||
#   │
|
||
|
||
#   ▼
|
||
|
||
# Current-State Service
|
||
|
||
#   │
|
||
|
||
#   ├────────► OPC UA
|
||
|
||
#   │
|
||
|
||
#   └────────► Historical pipeline
|
||
|
||
#   if live historization is enabled
|
||
|
||
# ```
|
||
|
||
#
|
||
|
||
# The Current-State Service maintains the latest accepted value for each configured point.
|
||
|
||
#
|
||
|
||
# \---
|
||
|
||
#
|
||
|
||
# \# 17. Current-State Service
|
||
|
||
#
|
||
|
||
# Responsibilities:
|
||
|
||
#
|
||
|
||
# \- maintain the latest current value;
|
||
|
||
# \- reject obsolete current-state updates where applicable;
|
||
|
||
# \- expose current values to OPC UA;
|
||
|
||
# \- notify subscribers of valid changes;
|
||
|
||
# \- preserve quality and timestamps.
|
||
|
||
#
|
||
|
||
# Conceptual interface:
|
||
|
||
#
|
||
|
||
# ```text
|
||
|
||
# update(CurrentValue)
|
||
|
||
#
|
||
|
||
# get(PointId)
|
||
|
||
#
|
||
|
||
# getAll(StationId)
|
||
|
||
#
|
||
|
||
# subscribe(PointId)
|
||
|
||
# ```
|
||
|
||
#
|
||
|
||
# Historical backfill shall not directly call `update(CurrentValue)`.
|
||
|
||
#
|
||
|
||
# \---
|
||
|
||
#
|
||
|
||
# \# 18. Historical-data architecture
|
||
|
||
#
|
||
|
||
# Historical AquaCom data follows:
|
||
|
||
#
|
||
|
||
# ```text
|
||
|
||
# AquaCom history
|
||
|
||
#   │
|
||
|
||
#   ▼
|
||
|
||
# Historical Acquisition Manager
|
||
|
||
#   │
|
||
|
||
#   ▼
|
||
|
||
# Canonical HistoricalSample
|
||
|
||
#   │
|
||
|
||
#   ▼
|
||
|
||
# Historical Pipeline
|
||
|
||
#   │
|
||
|
||
#   ├────────► History Repository
|
||
|
||
#   ├────────► Storage Sink A
|
||
|
||
#   ├────────► Storage Sink B
|
||
|
||
#   └────────► Other configured destinations
|
||
|
||
# ```
|
||
|
||
#
|
||
|
||
# The historical pipeline is independent from OPC UA.
|
||
|
||
#
|
||
|
||
# \---
|
||
|
||
#
|
||
|
||
# \# 19. Historical Acquisition Manager
|
||
|
||
#
|
||
|
||
# The Historical Acquisition Manager is responsible for:
|
||
|
||
#
|
||
|
||
# \- determining missing intervals;
|
||
|
||
# \- requesting AquaCom history;
|
||
|
||
# \- processing historical responses;
|
||
|
||
# \- maintaining synchronization state;
|
||
|
||
# \- managing watermarks;
|
||
|
||
# \- performing reconnect/backfill;
|
||
|
||
# \- throttling history retrieval;
|
||
|
||
# \- avoiding interference with live polling.
|
||
|
||
#
|
||
|
||
# Live acquisition shall normally have higher communication priority than bulk history recovery.
|
||
|
||
#
|
||
|
||
# \---
|
||
|
||
#
|
||
|
||
# \# 20. Historical synchronization
|
||
|
||
#
|
||
|
||
# Each station may maintain persistent synchronization state.
|
||
|
||
#
|
||
|
||
# Conceptually:
|
||
|
||
#
|
||
|
||
# ```text
|
||
|
||
# StationId
|
||
|
||
# HistoryStreamId
|
||
|
||
# LastCompleteTimestamp
|
||
|
||
# LastAttemptTimestamp
|
||
|
||
# LastSuccessfulTimestamp
|
||
|
||
# SynchronizationState
|
||
|
||
# ```
|
||
|
||
#
|
||
|
||
# Example:
|
||
|
||
#
|
||
|
||
# ```text
|
||
|
||
# 12:00 history synchronized
|
||
|
||
#
|
||
|
||
# 12:03 communication lost
|
||
|
||
#
|
||
|
||
# 17:24 communication restored
|
||
|
||
#
|
||
|
||
# 12:00 → 17:24
|
||
|
||
#   identified as recovery interval
|
||
|
||
# ```
|
||
|
||
#
|
||
|
||
# The gateway then retrieves available AquaCom history for that interval.
|
||
|
||
#
|
||
|
||
# \---
|
||
|
||
#
|
||
|
||
# \# 21. Watermark rule
|
||
|
||
#
|
||
|
||
# A history synchronization watermark shall only advance after the corresponding interval has been successfully handled according to the configured persistence policy.
|
||
|
||
#
|
||
|
||
# The following is prohibited:
|
||
|
||
#
|
||
|
||
# ```text
|
||
|
||
# receive historical packet
|
||
|
||
#   │
|
||
|
||
#   ▼
|
||
|
||
# advance watermark
|
||
|
||
#   │
|
||
|
||
#   ▼
|
||
|
||
# storage fails
|
||
|
||
# ```
|
||
|
||
#
|
||
|
||
# Preferred behavior is:
|
||
|
||
#
|
||
|
||
# ```text
|
||
|
||
# receive
|
||
|
||
#   ↓
|
||
|
||
# validate
|
||
|
||
#   ↓
|
||
|
||
# persist/durably queue
|
||
|
||
#   ↓
|
||
|
||
# advance synchronization state
|
||
|
||
# ```
|
||
|
||
#
|
||
|
||
# \---
|
||
|
||
#
|
||
|
||
# \# 22. Historical pipeline
|
||
|
||
#
|
||
|
||
# The historical pipeline shall conceptually perform:
|
||
|
||
#
|
||
|
||
# ```text
|
||
|
||
# HistoricalSample
|
||
|
||
#   │
|
||
|
||
#   ▼
|
||
|
||
# Validation
|
||
|
||
#   │
|
||
|
||
#   ▼
|
||
|
||
# Normalization
|
||
|
||
#   │
|
||
|
||
#   ▼
|
||
|
||
# Deduplication
|
||
|
||
#   │
|
||
|
||
#   ▼
|
||
|
||
# Durable Spool
|
||
|
||
#   │
|
||
|
||
#   ▼
|
||
|
||
# Distribution
|
||
|
||
# ```
|
||
|
||
#
|
||
|
||
# This pipeline provides a stable boundary between acquisition and storage.
|
||
|
||
#
|
||
|
||
# \---
|
||
|
||
#
|
||
|
||
# \# 23. Deduplication
|
||
|
||
#
|
||
|
||
# The default historical logical identity is:
|
||
|
||
#
|
||
|
||
# ```text
|
||
|
||
# StationId
|
||
|
||
# \+
|
||
|
||
# PointId
|
||
|
||
# \+
|
||
|
||
# SourceTimestamp
|
||
|
||
# ```
|
||
|
||
#
|
||
|
||
# A stronger AquaCom-provided identifier may be used where verified.
|
||
|
||
#
|
||
|
||
# Identical samples shall not create unintended duplicate history.
|
||
|
||
#
|
||
|
||
# Conflicting samples sharing the same logical identity shall generate diagnostics.
|
||
|
||
#
|
||
|
||
# The default conflict strategy should favor explicit conflict detection rather than silent overwrite.
|
||
|
||
#
|
||
|
||
# \---
|
||
|
||
#
|
||
|
||
# \# 24. Durable spool
|
||
|
||
#
|
||
|
||
# The historical spool provides restart-safe delivery.
|
||
|
||
#
|
||
|
||
# Conceptually:
|
||
|
||
#
|
||
|
||
# ```text
|
||
|
||
# HistoricalSample
|
||
|
||
#   │
|
||
|
||
#   ▼
|
||
|
||
# Persistent spool
|
||
|
||
#   │
|
||
|
||
#   ├────► Repository
|
||
|
||
#   ├────► Sink A
|
||
|
||
#   └────► Sink B
|
||
|
||
# ```
|
||
|
||
#
|
||
|
||
# Each destination maintains independent acknowledgement.
|
||
|
||
#
|
||
|
||
# Example:
|
||
|
||
#
|
||
|
||
# ```text
|
||
|
||
# Record 4711
|
||
|
||
#
|
||
|
||
# Repository ACK
|
||
|
||
# CentralHistorian ACK
|
||
|
||
# Archive PENDING
|
||
|
||
# ```
|
||
|
||
#
|
||
|
||
# The record remains until configured delivery requirements have been fulfilled.
|
||
|
||
#
|
||
|
||
# \---
|
||
|
||
#
|
||
|
||
# \# 25. History Repository
|
||
|
||
#
|
||
|
||
# A History Repository is a queryable historical source.
|
||
|
||
#
|
||
|
||
# It provides operations conceptually equivalent to:
|
||
|
||
#
|
||
|
||
# ```text
|
||
|
||
# store
|
||
|
||
# storeBatch
|
||
|
||
# readRaw
|
||
|
||
# readAtTime
|
||
|
||
# getBounds
|
||
|
||
# health
|
||
|
||
# ```
|
||
|
||
#
|
||
|
||
# The repository used by OPC UA Historical Access is selected by configuration.
|
||
|
||
#
|
||
|
||
# The OPC UA implementation shall not know whether the repository is:
|
||
|
||
#
|
||
|
||
# ```text
|
||
|
||
# relational database
|
||
|
||
# time-series database
|
||
|
||
# embedded historian
|
||
|
||
# industrial historian
|
||
|
||
# other queryable implementation
|
||
|
||
# ```
|
||
|
||
#
|
||
|
||
# \---
|
||
|
||
#
|
||
|
||
# \# 26. Storage Sink
|
||
|
||
#
|
||
|
||
# A Storage Sink is a destination receiving historical records.
|
||
|
||
#
|
||
|
||
# Conceptual interface:
|
||
|
||
#
|
||
|
||
# ```text
|
||
|
||
# initialize
|
||
|
||
# write
|
||
|
||
# writeBatch
|
||
|
||
# flush
|
||
|
||
# health
|
||
|
||
# shutdown
|
||
|
||
# ```
|
||
|
||
#
|
||
|
||
# A sink does not need to support historical queries.
|
||
|
||
#
|
||
|
||
# Examples:
|
||
|
||
#
|
||
|
||
# ```text
|
||
|
||
# SQL database
|
||
|
||
# time-series database
|
||
|
||
# enterprise historian
|
||
|
||
# file archive
|
||
|
||
# message broker
|
||
|
||
# data lake connector
|
||
|
||
# ```
|
||
|
||
#
|
||
|
||
# \---
|
||
|
||
#
|
||
|
||
# \# 27. Repository versus sink
|
||
|
||
#
|
||
|
||
# These shall remain separate concepts:
|
||
|
||
#
|
||
|
||
# ```text
|
||
|
||
# Repository
|
||
|
||
#   = query historical data
|
||
|
||
#
|
||
|
||
# Sink
|
||
|
||
#   = receive historical data
|
||
|
||
# ```
|
||
|
||
#
|
||
|
||
# One implementation may support both.
|
||
|
||
#
|
||
|
||
# Example:
|
||
|
||
#
|
||
|
||
# ```text
|
||
|
||
# Local historian
|
||
|
||
#   Repository: yes
|
||
|
||
#   Sink: yes
|
||
|
||
#
|
||
|
||
# Archive export
|
||
|
||
#   Repository: no
|
||
|
||
#   Sink: yes
|
||
|
||
# ```
|
||
|
||
#
|
||
|
||
# \---
|
||
|
||
#
|
||
|
||
# \# 28. Multiple storage destinations
|
||
|
||
#
|
||
|
||
# A historical record may be delivered to multiple independent destinations.
|
||
|
||
#
|
||
|
||
# Example:
|
||
|
||
#
|
||
|
||
# ```text
|
||
|
||
#   Historical Pipeline
|
||
|
||
#   │
|
||
|
||
#   ┌───────────────┼────────────────┐
|
||
|
||
#   │ │ │
|
||
|
||
#   ▼ ▼ ▼
|
||
|
||
#   Local Repository Central DB Archive
|
||
|
||
# ```
|
||
|
||
#
|
||
|
||
# Failure of one destination shall not unnecessarily block successful destinations.
|
||
|
||
#
|
||
|
||
# \---
|
||
|
||
#
|
||
|
||
# \# 29. OPC UA architecture
|
||
|
||
#
|
||
|
||
# The OPC UA subsystem provides northbound access to normalized gateway information.
|
||
|
||
#
|
||
|
||
# Logical components:
|
||
|
||
#
|
||
|
||
# ```text
|
||
|
||
# OPC UA Server
|
||
|
||
#   │
|
||
|
||
#   ├── Namespace Manager
|
||
|
||
#   ├── Current Value Provider
|
||
|
||
#   ├── Historical Provider
|
||
|
||
#   ├── Quality Mapper
|
||
|
||
#   ├── Diagnostics Provider
|
||
|
||
#   └── Security
|
||
|
||
# ```
|
||
|
||
#
|
||
|
||
# \---
|
||
|
||
#
|
||
|
||
# \# 30. OPC UA current data
|
||
|
||
#
|
||
|
||
# Current values are exposed through normal OPC UA Data Access.
|
||
|
||
#
|
||
|
||
# Mapping:
|
||
|
||
#
|
||
|
||
# ```text
|
||
|
||
# CurrentValue.Value
|
||
|
||
#   ↓
|
||
|
||
# OPC UA Value
|
||
|
||
#
|
||
|
||
# CurrentValue.SourceTimestamp
|
||
|
||
#   ↓
|
||
|
||
# OPC UA SourceTimestamp
|
||
|
||
#
|
||
|
||
# Gateway server time
|
||
|
||
#   ↓
|
||
|
||
# OPC UA ServerTimestamp
|
||
|
||
#
|
||
|
||
# CurrentValue.Quality
|
||
|
||
#   ↓
|
||
|
||
# OPC UA StatusCode
|
||
|
||
# ```
|
||
|
||
#
|
||
|
||
# \---
|
||
|
||
#
|
||
|
||
# \# 31. OPC UA Historical Access
|
||
|
||
#
|
||
|
||
# Historical Access shall query the configured History Repository.
|
||
|
||
#
|
||
|
||
# Correct flow:
|
||
|
||
#
|
||
|
||
# ```text
|
||
|
||
# OPC UA Client
|
||
|
||
#   │
|
||
|
||
#   │ HistoryRead
|
||
|
||
#   ▼
|
||
|
||
# OPC UA Server
|
||
|
||
#   │
|
||
|
||
#   ▼
|
||
|
||
# Historical Provider
|
||
|
||
#   │
|
||
|
||
#   ▼
|
||
|
||
# History Repository
|
||
|
||
#   │
|
||
|
||
#   ▼
|
||
|
||
# HistoricalSample\[]
|
||
|
||
#   │
|
||
|
||
#   ▼
|
||
|
||
# OPC UA DataValue\[]
|
||
|
||
# ```
|
||
|
||
#
|
||
|
||
# \---
|
||
|
||
#
|
||
|
||
# \# 32. Prohibited HistoryRead architecture
|
||
|
||
#
|
||
|
||
# The following architecture is prohibited:
|
||
|
||
#
|
||
|
||
# ```text
|
||
|
||
# OPC UA HistoryRead
|
||
|
||
#   │
|
||
|
||
#   ▼
|
||
|
||
# AquaCom request
|
||
|
||
#   │
|
||
|
||
#   ▼
|
||
|
||
# wait for RTU
|
||
|
||
#   │
|
||
|
||
#   ▼
|
||
|
||
# OPC UA response
|
||
|
||
# ```
|
||
|
||
#
|
||
|
||
# Historical synchronization and historical client access must be decoupled.
|
||
|
||
#
|
||
|
||
# \---
|
||
|
||
#
|
||
|
||
# \# 33. OPC UA namespace
|
||
|
||
#
|
||
|
||
# The default logical namespace shall resemble:
|
||
|
||
#
|
||
|
||
# ```text
|
||
|
||
# AquaCom
|
||
|
||
# │
|
||
|
||
# ├── Gateway
|
||
|
||
# │ ├── Status
|
||
|
||
# │ ├── Version
|
||
|
||
# │ ├── StartTime
|
||
|
||
# │ ├── ConfigurationVersion
|
||
|
||
# │ ├── HistoricalQueueDepth
|
||
|
||
# │ └── Storage
|
||
|
||
# │
|
||
|
||
# └── Stations
|
||
|
||
#   │
|
||
|
||
#   ├── PS001
|
||
|
||
#   │ ├── Process
|
||
|
||
#   │ │ ├── Level
|
||
|
||
#   │ │ ├── Pump01Running
|
||
|
||
#   │ │ └── Pump02Running
|
||
|
||
#   │ │
|
||
|
||
#   │ └── Diagnostics
|
||
|
||
#   │ ├── CommunicationState
|
||
|
||
#   │ ├── LastCommunication
|
||
|
||
#   │ ├── HistoryState
|
||
|
||
#   │ └── HistoryWatermark
|
||
|
||
#   │
|
||
|
||
#   └── PS002
|
||
|
||
# ```
|
||
|
||
#
|
||
|
||
# Exact organization may be configurable.
|
||
|
||
#
|
||
|
||
# \---
|
||
|
||
#
|
||
|
||
# \# 34. Stable OPC UA NodeIds
|
||
|
||
#
|
||
|
||
# OPC UA NodeIds shall derive from stable engineering identifiers.
|
||
|
||
#
|
||
|
||
# Example:
|
||
|
||
#
|
||
|
||
# ```text
|
||
|
||
# station/PS001/point/LEVEL
|
||
|
||
# ```
|
||
|
||
#
|
||
|
||
# Changing:
|
||
|
||
#
|
||
|
||
# ```text
|
||
|
||
# Wet well level
|
||
|
||
# ```
|
||
|
||
#
|
||
|
||
# to:
|
||
|
||
#
|
||
|
||
# ```text
|
||
|
||
# Inlet sump level
|
||
|
||
# ```
|
||
|
||
#
|
||
|
||
# shall not normally change the NodeId.
|
||
|
||
#
|
||
|
||
# Stable NodeIds are required to preserve client configuration.
|
||
|
||
#
|
||
|
||
# \---
|
||
|
||
#
|
||
|
||
# \# 35. Diagnostics architecture
|
||
|
||
#
|
||
|
||
# Diagnostics are separate from process data.
|
||
|
||
#
|
||
|
||
# Conceptually:
|
||
|
||
#
|
||
|
||
# ```text
|
||
|
||
# Diagnostics
|
||
|
||
# │
|
||
|
||
# ├── Gateway
|
||
|
||
# │
|
||
|
||
# ├── Station
|
||
|
||
# │
|
||
|
||
# ├── AquaCom Protocol
|
||
|
||
# │
|
||
|
||
# ├── History
|
||
|
||
# │
|
||
|
||
# ├── Storage
|
||
|
||
# └── OPC UA
|
||
|
||
# ```
|
||
|
||
#
|
||
|
||
# Diagnostics may be exposed through:
|
||
|
||
#
|
||
|
||
# \- logs;
|
||
|
||
# \- metrics;
|
||
|
||
# \- OPC UA diagnostic nodes;
|
||
|
||
# \- future management interfaces.
|
||
|
||
#
|
||
|
||
# \---
|
||
|
||
#
|
||
|
||
# \# 36. Gateway diagnostics
|
||
|
||
#
|
||
|
||
# Examples:
|
||
|
||
#
|
||
|
||
# ```text
|
||
|
||
# GatewayState
|
||
|
||
# Version
|
||
|
||
# ConfigurationVersion
|
||
|
||
# StartTime
|
||
|
||
# Uptime
|
||
|
||
# StationCount
|
||
|
||
# OnlineStationCount
|
||
|
||
# HistoricalQueueDepth
|
||
|
||
# SpoolDiskUsage
|
||
|
||
# OPCUAState
|
||
|
||
# ```
|
||
|
||
#
|
||
|
||
# \---
|
||
|
||
#
|
||
|
||
# \# 37. Station diagnostics
|
||
|
||
#
|
||
|
||
# Examples:
|
||
|
||
#
|
||
|
||
# ```text
|
||
|
||
# CommunicationState
|
||
|
||
# LastRequest
|
||
|
||
# LastResponse
|
||
|
||
# LastSuccessfulCommunication
|
||
|
||
# ConsecutiveFailures
|
||
|
||
# ProtocolErrors
|
||
|
||
# HistorySynchronizationState
|
||
|
||
# HistoryWatermark
|
||
|
||
# HistoricalBacklog
|
||
|
||
# ```
|
||
|
||
#
|
||
|
||
# \---
|
||
|
||
#
|
||
|
||
# \# 38. Storage diagnostics
|
||
|
||
#
|
||
|
||
# Per destination:
|
||
|
||
#
|
||
|
||
# ```text
|
||
|
||
# State
|
||
|
||
# LastSuccessfulWrite
|
||
|
||
# LastFailure
|
||
|
||
# PendingRecords
|
||
|
||
# RetryCount
|
||
|
||
# Latency
|
||
|
||
# ```
|
||
|
||
#
|
||
|
||
# A storage failure shall be identifiable independently from an AquaCom communication failure.
|
||
|
||
#
|
||
|
||
# \---
|
||
|
||
#
|
||
|
||
# \# 39. Logging
|
||
|
||
#
|
||
|
||
# Structured logging is preferred.
|
||
|
||
#
|
||
|
||
# Useful context includes:
|
||
|
||
#
|
||
|
||
# ```text
|
||
|
||
# timestamp
|
||
|
||
# severity
|
||
|
||
# component
|
||
|
||
# stationId
|
||
|
||
# pointId
|
||
|
||
# operation
|
||
|
||
# correlationId
|
||
|
||
# message
|
||
|
||
# error
|
||
|
||
# ```
|
||
|
||
#
|
||
|
||
# Raw AquaCom telegram logging shall be separately configurable.
|
||
|
||
#
|
||
|
||
# \---
|
||
|
||
#
|
||
|
||
# \# 40. Configuration architecture
|
||
|
||
#
|
||
|
||
# Configuration shall be external and machine-readable.
|
||
|
||
#
|
||
|
||
# Conceptual structure:
|
||
|
||
#
|
||
|
||
# ```text
|
||
|
||
# Gateway Configuration
|
||
|
||
# │
|
||
|
||
# ├── Gateway
|
||
|
||
# ├── AquaCom
|
||
|
||
# ├── Stations
|
||
|
||
# ├── Points
|
||
|
||
# ├── History
|
||
|
||
# ├── Storage
|
||
|
||
# ├── OPC UA
|
||
|
||
# ├── Security
|
||
|
||
# ├── Diagnostics
|
||
|
||
# └── Logging
|
||
|
||
# ```
|
||
|
||
#
|
||
|
||
# Configuration validation occurs before activation.
|
||
|
||
#
|
||
|
||
# \---
|
||
|
||
#
|
||
|
||
# \# 41. Station configuration
|
||
|
||
#
|
||
|
||
# A station definition contains concepts equivalent to:
|
||
|
||
#
|
||
|
||
# ```text
|
||
|
||
# StationId
|
||
|
||
# Enabled
|
||
|
||
# Transport
|
||
|
||
# AquaComAddress
|
||
|
||
# ProtocolProfile
|
||
|
||
# LiveAcquisition
|
||
|
||
# HistoricalAcquisition
|
||
|
||
# PointDefinitionSource
|
||
|
||
# Timezone
|
||
|
||
# ```
|
||
|
||
#
|
||
|
||
# Station configuration shall not be embedded directly in protocol source code.
|
||
|
||
#
|
||
|
||
# \---
|
||
|
||
#
|
||
|
||
# \# 42. Point configuration
|
||
|
||
#
|
||
|
||
# A point contains concepts equivalent to:
|
||
|
||
#
|
||
|
||
# ```text
|
||
|
||
# PointId
|
||
|
||
# DisplayName
|
||
|
||
# Description
|
||
|
||
# SourceReference
|
||
|
||
# DataType
|
||
|
||
# EngineeringUnit
|
||
|
||
# Scaling
|
||
|
||
# LiveEnabled
|
||
|
||
# HistoryEnabled
|
||
|
||
# OPCUAEnabled
|
||
|
||
# Historizing
|
||
|
||
# StoragePolicy
|
||
|
||
# ```
|
||
|
||
#
|
||
|
||
# `PointId` shall remain stable even if presentation metadata changes.
|
||
|
||
#
|
||
|
||
# \---
|
||
|
||
#
|
||
|
||
# \# 43. Security boundaries
|
||
|
||
#
|
||
|
||
# The architecture assumes AquaCom is a legacy field protocol.
|
||
|
||
#
|
||
|
||
# Security shall therefore be applied around the AquaCom communication environment.
|
||
|
||
#
|
||
|
||
# Conceptually:
|
||
|
||
#
|
||
|
||
# ```text
|
||
|
||
# SCADA / client network
|
||
|
||
#   │
|
||
|
||
#   ▼
|
||
|
||
# Firewall / segmentation
|
||
|
||
#   │
|
||
|
||
#   ▼
|
||
|
||
# AquaCom Gateway
|
||
|
||
#   │
|
||
|
||
#   ▼
|
||
|
||
# OT communication network
|
||
|
||
#   │
|
||
|
||
#   ▼
|
||
|
||
# Site firewall/router/VPN
|
||
|
||
#   │
|
||
|
||
#   ▼
|
||
|
||
# AquaCom RTU
|
||
|
||
# ```
|
||
|
||
#
|
||
|
||
# The gateway shall not assume that AquaCom itself provides modern confidentiality, authentication or authorization.
|
||
|
||
#
|
||
|
||
# \---
|
||
|
||
#
|
||
|
||
# \# 44. OPC UA security
|
||
|
||
#
|
||
|
||
# OPC UA security is handled within the OPC UA subsystem.
|
||
|
||
#
|
||
|
||
# Production architecture shall support:
|
||
|
||
#
|
||
|
||
# ```text
|
||
|
||
# application certificates
|
||
|
||
# trusted client management
|
||
|
||
# secure channels
|
||
|
||
# authentication
|
||
|
||
# authorization
|
||
|
||
# encrypted communication
|
||
|
||
# ```
|
||
|
||
#
|
||
|
||
# Insecure endpoints shall not be the normal production default.
|
||
|
||
#
|
||
|
||
# \---
|
||
|
||
#
|
||
|
||
# \# 45. Secrets boundary
|
||
|
||
#
|
||
|
||
# Secrets shall not form part of normal version-controlled configuration.
|
||
|
||
#
|
||
|
||
# Examples:
|
||
|
||
#
|
||
|
||
# ```text
|
||
|
||
# database passwords
|
||
|
||
# API tokens
|
||
|
||
# private keys
|
||
|
||
# certificate private keys
|
||
|
||
# ```
|
||
|
||
#
|
||
|
||
# These shall be injected through an external secret mechanism.
|
||
|
||
#
|
||
|
||
# \---
|
||
|
||
#
|
||
|
||
# \# 46. Host subsystem
|
||
|
||
#
|
||
|
||
# The `host` subsystem composes the application.
|
||
|
||
#
|
||
|
||
# Responsibilities include:
|
||
|
||
#
|
||
|
||
# \- configuration loading;
|
||
|
||
# \- dependency construction;
|
||
|
||
# \- subsystem startup;
|
||
|
||
# \- lifecycle management;
|
||
|
||
# \- shutdown;
|
||
|
||
# \- top-level health state.
|
||
|
||
#
|
||
|
||
# The host shall not become a location for protocol or business logic.
|
||
|
||
#
|
||
|
||
# \---
|
||
|
||
#
|
||
|
||
# \# 47. Startup architecture
|
||
|
||
#
|
||
|
||
# Conceptual startup sequence:
|
||
|
||
#
|
||
|
||
# ```text
|
||
|
||
# Load configuration
|
||
|
||
#   │
|
||
|
||
#   ▼
|
||
|
||
# Validate configuration
|
||
|
||
#   │
|
||
|
||
#   ▼
|
||
|
||
# Load persistent state
|
||
|
||
#   │
|
||
|
||
#   ▼
|
||
|
||
# Initialize storage
|
||
|
||
#   │
|
||
|
||
#   ▼
|
||
|
||
# Initialize historical services
|
||
|
||
#   │
|
||
|
||
#   ▼
|
||
|
||
# Initialize OPC UA
|
||
|
||
#   │
|
||
|
||
#   ▼
|
||
|
||
# Initialize AquaCom stations
|
||
|
||
#   │
|
||
|
||
#   ▼
|
||
|
||
# Start live acquisition
|
||
|
||
#   │
|
||
|
||
#   ▼
|
||
|
||
# Start historical synchronization
|
||
|
||
# ```
|
||
|
||
#
|
||
|
||
# A temporary failure of a non-critical secondary storage destination should not necessarily prevent the gateway from starting.
|
||
|
||
#
|
||
|
||
# \---
|
||
|
||
#
|
||
|
||
# \# 48. Shutdown architecture
|
||
|
||
#
|
||
|
||
# Conceptual controlled shutdown:
|
||
|
||
#
|
||
|
||
# ```text
|
||
|
||
# Stop accepting administrative changes
|
||
|
||
#   │
|
||
|
||
#   ▼
|
||
|
||
# Stop scheduling new acquisition
|
||
|
||
#   │
|
||
|
||
#   ▼
|
||
|
||
# Complete/cancel active transactions safely
|
||
|
||
#   │
|
||
|
||
#   ▼
|
||
|
||
# Persist synchronization state
|
||
|
||
#   │
|
||
|
||
#   ▼
|
||
|
||
# Flush durable state
|
||
|
||
#   │
|
||
|
||
#   ▼
|
||
|
||
# Stop OPC UA
|
||
|
||
#   │
|
||
|
||
#   ▼
|
||
|
||
# Close storage
|
||
|
||
#   │
|
||
|
||
#   ▼
|
||
|
||
# Terminate
|
||
|
||
# ```
|
||
|
||
#
|
||
|
||
# \---
|
||
|
||
#
|
||
|
||
# \# 49. Restart recovery
|
||
|
||
#
|
||
|
||
# After an unclean restart:
|
||
|
||
#
|
||
|
||
# ```text
|
||
|
||
# Load configuration
|
||
|
||
#   │
|
||
|
||
#   ▼
|
||
|
||
# Recover persistent spool
|
||
|
||
#   │
|
||
|
||
#   ▼
|
||
|
||
# Restore synchronization watermarks
|
||
|
||
#   │
|
||
|
||
#   ▼
|
||
|
||
# Reconnect AquaCom stations
|
||
|
||
#   │
|
||
|
||
#   ▼
|
||
|
||
# Resume live acquisition
|
||
|
||
#   │
|
||
|
||
#   ▼
|
||
|
||
# Resume historical recovery
|
||
|
||
# ```
|
||
|
||
#
|
||
|
||
# Live acquisition should resume before large backlog processing.
|
||
|
||
#
|
||
|
||
# \---
|
||
|
||
#
|
||
|
||
# \# 50. Scheduling priorities
|
||
|
||
#
|
||
|
||
# Where AquaCom communication capacity is limited, scheduling shall conceptually prioritize:
|
||
|
||
#
|
||
|
||
# ```text
|
||
|
||
# 1\. communication/session health
|
||
|
||
# 2\. current/live acquisition
|
||
|
||
# 3\. alarms/events when implemented
|
||
|
||
# 4\. explicit configuration operations
|
||
|
||
# 5\. historical backfill
|
||
|
||
# 6\. low-priority maintenance
|
||
|
||
# ```
|
||
|
||
#
|
||
|
||
# Historical synchronization shall be throttleable.
|
||
|
||
#
|
||
|
||
# \---
|
||
|
||
#
|
||
|
||
# \# 51. Resource boundaries
|
||
|
||
#
|
||
|
||
# All queues and caches shall be bounded.
|
||
|
||
#
|
||
|
||
# This applies to:
|
||
|
||
#
|
||
|
||
# ```text
|
||
|
||
# AquaCom request queues
|
||
|
||
# history queues
|
||
|
||
# storage retry queues
|
||
|
||
# OPC UA historical result sets
|
||
|
||
# continuation state
|
||
|
||
# logging buffers
|
||
|
||
# spool storage
|
||
|
||
# ```
|
||
|
||
#
|
||
|
||
# Overflow behavior shall be explicit and observable.
|
||
|
||
#
|
||
|
||
# \---
|
||
|
||
#
|
||
|
||
# \# 52. Testing architecture
|
||
|
||
#
|
||
|
||
# The system shall support independent testing of each architectural boundary.
|
||
|
||
#
|
||
|
||
# Conceptually:
|
||
|
||
#
|
||
|
||
# ```text
|
||
|
||
# Protocol Fixtures
|
||
|
||
#   │
|
||
|
||
#   ▼
|
||
|
||
# AquaCom Codec Tests
|
||
|
||
#
|
||
|
||
# Simulator
|
||
|
||
#   │
|
||
|
||
#   ▼
|
||
|
||
# Session / Acquisition Tests
|
||
|
||
#
|
||
|
||
# Historical Fixtures
|
||
|
||
#   │
|
||
|
||
#   ▼
|
||
|
||
# History Pipeline Tests
|
||
|
||
#
|
||
|
||
# Repository
|
||
|
||
#   │
|
||
|
||
#   ▼
|
||
|
||
# OPC UA HA Tests
|
||
|
||
#
|
||
|
||
# Current-State Service
|
||
|
||
#   │
|
||
|
||
#   ▼
|
||
|
||
# OPC UA DA Tests
|
||
|
||
# ```
|
||
|
||
#
|
||
|
||
# \---
|
||
|
||
#
|
||
|
||
# \# 53. AquaCom simulator
|
||
|
||
#
|
||
|
||
# The simulator shall permit development without operational AquaCom equipment.
|
||
|
||
#
|
||
|
||
# Supported scenarios shall eventually include:
|
||
|
||
#
|
||
|
||
# ```text
|
||
|
||
# normal live values
|
||
|
||
# normal history
|
||
|
||
# timeouts
|
||
|
||
# disconnects
|
||
|
||
# delayed response
|
||
|
||
# malformed telegram
|
||
|
||
# bad checksum
|
||
|
||
# duplicate history
|
||
|
||
# conflicting history
|
||
|
||
# clock error
|
||
|
||
# reconnect
|
||
|
||
# backfill
|
||
|
||
# ```
|
||
|
||
#
|
||
|
||
# The simulator is part of the architecture, not merely a temporary development tool.
|
||
|
||
#
|
||
|
||
# \---
|
||
|
||
#
|
||
|
||
# \# 54. Protocol evidence architecture
|
||
|
||
#
|
||
|
||
# AquaCom implementation is linked to documented evidence.
|
||
|
||
#
|
||
|
||
# Relevant repository area:
|
||
|
||
#
|
||
|
||
# ```text
|
||
|
||
# docs/protocol/
|
||
|
||
# ```
|
||
|
||
#
|
||
|
||
# Recommended structure:
|
||
|
||
#
|
||
|
||
# ```text
|
||
|
||
# aquacom.md
|
||
|
||
# known-operations.md
|
||
|
||
# protocol-gaps.md
|
||
|
||
# test-vectors.md
|
||
|
||
# ```
|
||
|
||
#
|
||
|
||
# Every implemented AquaCom behavior should be traceable to:
|
||
|
||
#
|
||
|
||
# ```text
|
||
|
||
# Specification
|
||
|
||
# Capture
|
||
|
||
# Known-good implementation
|
||
|
||
# Approved test vector
|
||
|
||
# ```
|
||
|
||
#
|
||
|
||
# Unknown behavior remains explicitly unresolved.
|
||
|
||
#
|
||
|
||
# \---
|
||
|
||
#
|
||
|
||
# \# 55. Error isolation
|
||
|
||
#
|
||
|
||
# Failures shall remain contained where possible.
|
||
|
||
#
|
||
|
||
# Examples:
|
||
|
||
#
|
||
|
||
# | Failure | Expected isolation |
|
||
|
||
# |---|---|
|
||
|
||
# | Station A offline | Station B continues |
|
||
|
||
# | Storage A offline | Storage B continues |
|
||
|
||
# | OPC UA client disconnect | Acquisition continues |
|
||
|
||
# | OPC UA server problem | AquaCom acquisition should continue where possible |
|
||
|
||
# | Historical backfill fails | Live acquisition continues |
|
||
|
||
# | Malformed AquaCom telegram | Telegram rejected, station diagnostics updated |
|
||
|
||
# | Secondary storage failure | Durable spool retains pending delivery |
|
||
|
||
#
|
||
|
||
# \---
|
||
|
||
#
|
||
|
||
# \# 56. Future extension points
|
||
|
||
#
|
||
|
||
# The architecture shall permit future addition of:
|
||
|
||
#
|
||
|
||
# ```text
|
||
|
||
# OPC UA Alarms \& Conditions
|
||
|
||
# AquaCom alarms/events
|
||
|
||
# AquaCom commands
|
||
|
||
# setpoint changes
|
||
|
||
# MQTT
|
||
|
||
# REST API
|
||
|
||
# external analytics
|
||
|
||
# central configuration
|
||
|
||
# redundant gateways
|
||
|
||
# high availability
|
||
|
||
# additional history repositories
|
||
|
||
# additional storage sinks
|
||
|
||
# ```
|
||
|
||
#
|
||
|
||
# These shall be added behind explicit subsystem interfaces.
|
||
|
||
#
|
||
|
||
# \---
|
||
|
||
#
|
||
|
||
# \# 57. Future process-control architecture
|
||
|
||
#
|
||
|
||
# If control functionality is introduced later, it shall use a separate command pipeline:
|
||
|
||
#
|
||
|
||
# ```text
|
||
|
||
# Northbound request
|
||
|
||
#   │
|
||
|
||
#   ▼
|
||
|
||
# Authentication
|
||
|
||
#   │
|
||
|
||
#   ▼
|
||
|
||
# Authorization
|
||
|
||
#   │
|
||
|
||
#   ▼
|
||
|
||
# Command validation
|
||
|
||
#   │
|
||
|
||
#   ▼
|
||
|
||
# Command service
|
||
|
||
#   │
|
||
|
||
#   ▼
|
||
|
||
# AquaCom command
|
||
|
||
#   │
|
||
|
||
#   ▼
|
||
|
||
# Confirmation / readback
|
||
|
||
#   │
|
||
|
||
#   ▼
|
||
|
||
# Audit
|
||
|
||
# ```
|
||
|
||
#
|
||
|
||
# A direct mapping from arbitrary OPC UA writes to raw AquaCom telegrams is not an acceptable control architecture.
|
||
|
||
#
|
||
|
||
# \---
|
||
|
||
#
|
||
|
||
# \# 58. Architectural invariants
|
||
|
||
#
|
||
|
||
# The following invariants shall hold throughout implementation.
|
||
|
||
#
|
||
|
||
# \## INV-001
|
||
|
||
#
|
||
|
||
# AquaCom-specific logic exists only behind the AquaCom abstraction.
|
||
|
||
#
|
||
|
||
# \## INV-002
|
||
|
||
#
|
||
|
||
# The canonical model contains no AquaCom telegram representation.
|
||
|
||
#
|
||
|
||
# \## INV-003
|
||
|
||
#
|
||
|
||
# The canonical model contains no OPC UA-specific representation.
|
||
|
||
#
|
||
|
||
# \## INV-004
|
||
|
||
#
|
||
|
||
# Historical samples do not update current state solely because they were recently retrieved.
|
||
|
||
#
|
||
|
||
# \## INV-005
|
||
|
||
#
|
||
|
||
# Historical SourceTimestamp is preserved.
|
||
|
||
#
|
||
|
||
# \## INV-006
|
||
|
||
#
|
||
|
||
# OPC UA HistoryRead queries a repository, not an AquaCom device.
|
||
|
||
#
|
||
|
||
# \## INV-007
|
||
|
||
#
|
||
|
||
# A storage failure does not directly stop unrelated live AquaCom acquisition.
|
||
|
||
#
|
||
|
||
# \## INV-008
|
||
|
||
#
|
||
|
||
# Point identity remains stable across display-name changes.
|
||
|
||
#
|
||
|
||
# \## INV-009
|
||
|
||
#
|
||
|
||
# OPC UA NodeIds remain stable across restart and normal upgrades.
|
||
|
||
#
|
||
|
||
# \## INV-010
|
||
|
||
#
|
||
|
||
# Unverified AquaCom protocol details are not implemented as guesses.
|
||
|
||
#
|
||
|
||
# \## INV-011
|
||
|
||
#
|
||
|
||
# Synchronization state required for recovery is persistent.
|
||
|
||
#
|
||
|
||
# \## INV-012
|
||
|
||
#
|
||
|
||
# Historical delivery supports bounded persistent buffering.
|
||
|
||
#
|
||
|
||
# \---
|
||
|
||
#
|
||
|
||
# \# 59. Primary end-to-end data flows
|
||
|
||
#
|
||
|
||
# \## 59.1 Live data
|
||
|
||
#
|
||
|
||
# ```text
|
||
|
||
# AquaCom RTU
|
||
|
||
#   │
|
||
|
||
#   ▼
|
||
|
||
# Transport
|
||
|
||
#   │
|
||
|
||
#   ▼
|
||
|
||
# Protocol Engine
|
||
|
||
#   │
|
||
|
||
#   ▼
|
||
|
||
# Station Manager
|
||
|
||
#   │
|
||
|
||
#   ▼
|
||
|
||
# CurrentValue
|
||
|
||
#   │
|
||
|
||
#   ▼
|
||
|
||
# Current-State Service
|
||
|
||
#   │
|
||
|
||
#   ├────► OPC UA
|
||
|
||
#   │
|
||
|
||
#   └────► Historical Pipeline
|
||
|
||
#   when live historization is enabled
|
||
|
||
# ```
|
||
|
||
#
|
||
|
||
# \---
|
||
|
||
#
|
||
|
||
# \## 59.2 AquaCom historical recovery
|
||
|
||
#
|
||
|
||
# ```text
|
||
|
||
# AquaCom RTU
|
||
|
||
#   │
|
||
|
||
#   ▼
|
||
|
||
# Historical Acquisition
|
||
|
||
#   │
|
||
|
||
#   ▼
|
||
|
||
# HistoricalSample
|
||
|
||
#   │
|
||
|
||
#   ▼
|
||
|
||
# Validation
|
||
|
||
#   │
|
||
|
||
#   ▼
|
||
|
||
# Deduplication
|
||
|
||
#   │
|
||
|
||
#   ▼
|
||
|
||
# Durable Spool
|
||
|
||
#   │
|
||
|
||
#   ├────► Repository
|
||
|
||
#   ├────► Storage A
|
||
|
||
#   └────► Storage B
|
||
|
||
# ```
|
||
|
||
#
|
||
|
||
# \---
|
||
|
||
#
|
||
|
||
# \## 59.3 OPC UA historical request
|
||
|
||
#
|
||
|
||
# ```text
|
||
|
||
# OPC UA Client
|
||
|
||
#   │
|
||
|
||
#   ▼
|
||
|
||
# HistoryRead
|
||
|
||
#   │
|
||
|
||
#   ▼
|
||
|
||
# OPC UA Historical Provider
|
||
|
||
#   │
|
||
|
||
#   ▼
|
||
|
||
# History Repository
|
||
|
||
#   │
|
||
|
||
#   ▼
|
||
|
||
# HistoricalSample\[]
|
||
|
||
#   │
|
||
|
||
#   ▼
|
||
|
||
# OPC UA DataValue\[]
|
||
|
||
# ```
|
||
|
||
#
|
||
|
||
# \---
|
||
|
||
#
|
||
|
||
# \# 60. Reference architecture
|
||
|
||
#
|
||
|
||
# The complete reference architecture is:
|
||
|
||
#
|
||
|
||
# ```text
|
||
|
||
#   FIELD / AQUACOM
|
||
|
||
#   │
|
||
|
||
#   ▼
|
||
|
||
#   ┌─────────────────────┐
|
||
|
||
#   │ AquaCom Transport │
|
||
|
||
#   └──────────┬──────────┘
|
||
|
||
#   │
|
||
|
||
#   ▼
|
||
|
||
#   ┌─────────────────────┐
|
||
|
||
#   │ Protocol Engine │
|
||
|
||
#   └──────────┬──────────┘
|
||
|
||
#   │
|
||
|
||
#   ▼
|
||
|
||
#   ┌─────────────────────┐
|
||
|
||
#   │ Station Manager │
|
||
|
||
#   └──────────┬──────────┘
|
||
|
||
#   │
|
||
|
||
#   ▼
|
||
|
||
#   ┌─────────────────────┐
|
||
|
||
#   │ Canonical Model │
|
||
|
||
#   └───────┬───────┬─────┘
|
||
|
||
#   │ │
|
||
|
||
#   LIVE HISTORY
|
||
|
||
#   │ │
|
||
|
||
#   ▼ ▼
|
||
|
||
#   ┌──────────────┐ ┌──────────────────┐
|
||
|
||
#   │Current-State │ │Historical │
|
||
|
||
#   │Service │ │Acquisition │
|
||
|
||
#   └──────┬───────┘ └────────┬─────────┘
|
||
|
||
#   │ │
|
||
|
||
#   │ ▼
|
||
|
||
#   │ ┌──────────────────┐
|
||
|
||
#   │ │Historical │
|
||
|
||
#   │ │Pipeline │
|
||
|
||
#   │ └────────┬─────────┘
|
||
|
||
#   │ │
|
||
|
||
#   │ ┌──────────┼───────────┐
|
||
|
||
#   │ │ │ │
|
||
|
||
#   │ ▼ ▼ ▼
|
||
|
||
#   │ Repository Sink A Sink B
|
||
|
||
#   │ │
|
||
|
||
#   │ │
|
||
|
||
#   ▼ ▼
|
||
|
||
#   ┌────────────────────────────┐
|
||
|
||
#   │ OPC UA Server │
|
||
|
||
#   │ │
|
||
|
||
#   │ Data Access │
|
||
|
||
#   │ Historical Access │
|
||
|
||
#   │ Diagnostics │
|
||
|
||
#   └──────────────┬─────────────┘
|
||
|
||
#   │
|
||
|
||
#   ▼
|
||
|
||
#   SCADA / Clients
|
||
|
||
# ```
|
||
|
||
#
|
||
|
||
# \---
|
||
|
||
#
|
||
|
||
# \# 61. Architecture decision summary
|
||
|
||
#
|
||
|
||
# The gateway is intentionally designed as an:
|
||
|
||
#
|
||
|
||
# ```text
|
||
|
||
# AquaCom Integration Gateway
|
||
|
||
# ```
|
||
|
||
#
|
||
|
||
# rather than merely an:
|
||
|
||
#
|
||
|
||
# ```text
|
||
|
||
# AquaCom OPC UA Server
|
||
|
||
# ```
|
||
|
||
#
|
||
|
||
# This allows:
|
||
|
||
#
|
||
|
||
# \- OPC UA to be replaced or supplemented;
|
||
|
||
# \- storage technology to change;
|
||
|
||
# \- multiple historians to coexist;
|
||
|
||
# \- AquaCom equipment to be gradually retired;
|
||
|
||
# \- other northbound interfaces to be added;
|
||
|
||
# \- historical acquisition to continue independently of OPC UA clients.
|
||
|
||
#
|
||
|
||
# The long-term architectural asset is therefore the normalized integration layer and historical recovery mechanism, not any single external interface.
|
||
|
||
#
|
||
|
||
# \---
|
||
|
||
#
|
||
|
||
# \# 62. Final architectural rule
|
||
|
||
#
|
||
|
||
# The most important data rule is:
|
||
|
||
#
|
||
|
||
# > Historical data is stored and exposed according to when the process value was valid, not when the gateway happened to retrieve it.
|
||
|
||
#
|
||
|
||
# The most important protocol rule is:
|
||
|
||
#
|
||
|
||
# > AquaCom behavior must be based on verified protocol knowledge and must never be invented merely to complete an implementation.
|
||
|
||
#
|
||
|
||
# The most important software rule is:
|
||
|
||
#
|
||
|
||
# > AquaCom, canonical data handling, historical persistence and OPC UA shall remain separate architectural concerns.
|
||
|