--- # SOURCE: docs/01_Open_Canonical_Energy_Telemetry_Standard_v1.1.md --- title: "Open Canonical Energy Telemetry Standard" subtitle: "Normative Architecture and Information Model for Vendor-Independent Energy Telemetry Platforms" version: "1.1" status: "Architecture Review Candidate" release: "July 2026" identifier: "OCETS-CORE-1.1" --- # Open Canonical Energy Telemetry Standard **Document:** 1 of 5 **Type:** Normative Standard **Version:** 1.1 **Status:** Architecture Review Candidate **Release:** July 2026 **Compatibility:** Reference Implementation 1.x ## 1. Purpose The Open Canonical Energy Telemetry Standard (OCETS) defines a vendor-independent information model for acquiring, validating, storing, and consuming telemetry from energy systems. OCETS standardizes the semantic shape of observations and events: identities, metrics, units, labels, timestamps, quality, provenance, topology, registry requirements, security, and lifecycle behavior. It does not standardize a particular software stack or vendor integration method. ## 2. Scope This document specifies: - normative terminology; - the canonical information model; - identity scope and label semantics; - canonical metric and unit rules; - role-based power sign convention; - controlled vocabularies; - measurement point, asset, device, and plant modeling; - Plant Registry requirements; - timestamp semantics; - telemetry health; - downsampling semantics; - governance and conformance rules. - canonical observations, events, quality, and provenance; - organizations, portfolios, relationships, and topology; - Registry API interoperability and a normative security baseline. This document does not specify implementation details such as collector configuration, transport topics, storage deployment, dashboard construction, vendor register maps, polling templates, or transformation scripts. Those topics belong to the Reference Implementation Guide. OCETS v1.1 is telemetry-only. A `controls` relationship describes topology; it does not authorize or define a write operation. ### 2.1 Architecture Constraints OCETS intentionally does not standardize: - control systems, SCADA commands, setpoints, dispatch, or actuator writes; - optimization algorithms or forecast-generation models; - market communication, billing, settlement, or tariff calculation; - asset-management, maintenance-management, ERP, or procurement workflows; - vendor register maps, protocol configuration, dashboards, or a specific database. Externally generated forecasts MAY be represented as observations with `origin=forecast`, but SHALL include both `issued_at` and `valid_at`. Their generation, model lifecycle, confidence model, and revision policy remain outside OCETS v1.1. ### 2.2 Reference Architecture ```text Organization / Portfolio / Plant Registry | v Configuration Generator | Field Device -> Edge or Central Collector -> Transport -> Storage -> API -> Grafana | | | +------ Observations --------+-----------+ +------ Events / Health / Quality / Provenance ``` Every component MAY be replaced independently if it preserves the canonical contracts defined by OCETS. ## 3. Normative Language The key words `SHALL`, `SHALL NOT`, `SHOULD`, `SHOULD NOT`, and `MAY` are to be interpreted as normative requirement levels. - `SHALL` indicates a mandatory requirement. - `SHALL NOT` indicates a mandatory prohibition. - `SHOULD` indicates a recommended requirement that may be waived only with documented rationale. - `MAY` indicates an optional capability. ## 4. Terminology | Term | Definition | |---|---| | Plant | A physical or operational site that produces, consumes, stores, converts, or measures energy. | | Asset | A physical energy-system component within one Plant. | | Device | A logical telemetry-producing or telemetry-relevant function within one Plant. | | Measurement Point | A semantic location where a Metric applies. | | Metric | A canonical physical or operational quantity identified by metric name only. | | Capability | A declared ability of a Device or Measurement Point to provide one or more canonical Metrics. | | Registry | The authoritative schema-enforced declaration of Plants, Assets, Devices, Measurement Points, Capabilities, and relationships. | | Label | A bounded metadata field attached to telemetry to identify context without changing the Metric name. | | Organization | A tenant and governance boundary that owns Plants and Portfolios. | | Portfolio | A named grouping of Plants within one Organization. | | Observation | A metric value with identity, acquisition time, quality, and provenance. | | Event | A point-in-time or interval occurrence with lifecycle, severity, source, and correlation. | | Relationship | A stable, typed connection between registered objects. | | Topology | A versioned graph of Relationships for one Plant and one topology kind. | ## 5. Architectural Principles ### 5.1 Semantic Before Technical The platform SHALL standardize physical and operational concepts rather than protocol objects, register names, addresses, hostnames, or vendor terminology. Vendor-specific telemetry SHALL be mapped into canonical concepts before it is stored as OCETS telemetry. ### 5.2 Stable Identity Telemetry identity SHALL be independent of network addresses, collector placement, gateway topology, source file layout, and deployment topology. Logical identities SHALL remain stable throughout the lifecycle of the platform. Replacing a collector, gateway, protocol adapter, or physical communication path SHALL NOT require a semantic identity change. ### 5.3 Canonical Representation Every physical quantity SHALL have one canonical metric name, one canonical engineering unit, and one semantic definition. The canonical metric representation is the metric name itself, such as `active_power`, `voltage`, or `state_of_charge`. OCETS telemetry SHALL NOT require or add a redundant `metric` label to restate the metric name. Multiple canonical representations of the same physical quantity SHALL NOT coexist in the canonical model. Domain-specific metric names SHALL be used only where the domain concept changes the meaning of the quantity. ### 5.4 Separation of Concerns The following concepts SHALL remain independent: - Plant; - Asset; - Device; - Measurement Point; - Metric; - Capability. No concept SHALL implicitly define another. For example, `active_power` defines what is measured; the Measurement Point and labels define where and in what role it is measured. ### 5.5 Declarative Configuration The platform SHALL be described by an authoritative Plant Registry. Operational configuration SHOULD be generated from the registry. Manual duplication of plant, asset, device, measurement point, and label definitions SHOULD be avoided. ### 5.6 Acquisition Independence The canonical model SHALL NOT depend on where telemetry acquisition takes place. Central acquisition, edge acquisition, and hybrid acquisition are conformant if they emit identical canonical telemetry for identical measurements. ### 5.7 Operational State Is Telemetry Operational health SHALL be represented explicitly. Device health, communication health, collector health, timestamp synchronization, freshness, and validation health SHALL NOT be inferred only from process values. ## 6. Canonical Information Model The canonical information model defines the semantic structure of telemetry: ```text Plant -> Asset -> Device -> Measurement Point -> Metric ``` The ownership and grouping model is: ```text Organization -> Portfolio -> Plant ``` The telemetry model produces two distinct records: Observations and Events. Relationships form versioned physical, electrical, and telemetry Topologies around registered objects. ### 6.1 Plant A Plant is a physical or operational site that produces, consumes, stores, converts, or measures energy. A Plant SHALL have a globally unique stable identifier. ### 6.2 Asset An Asset is a physical energy-system component, such as an inverter, meter, battery system, transformer, gateway enclosure, or switchgear cabinet. An Asset SHALL belong to exactly one Plant. An Asset identifier SHALL be unique within its Plant. ### 6.3 Device A Device is a logical telemetry-producing or telemetry-relevant function. A physical Asset MAY expose more than one Device. A Device SHALL belong to exactly one Plant and SHALL have an identifier unique within that Plant. ### 6.4 Measurement Point A Measurement Point is a semantic location where a Metric applies. Examples include: - grid connection; - inverter AC output; - inverter DC input; - PV string; - MPPT channel; - battery DC bus; - site load; - transformer secondary. A Measurement Point SHALL belong to exactly one Plant and SHALL have an identifier unique within that Plant. ### 6.5 Metric A Metric is a canonical physical or operational quantity. Examples include `active_power`, `energy_import`, `voltage`, `current`, `frequency`, `state_of_charge`, `device_available`, `communication_status`, and `timestamp_skew`. Raw vendor register names, dashboard aliases, protocol field names, and implementation-specific source names SHALL NOT be treated as canonical metric names. ## 7. Identity and Label Model The canonical identity of a telemetry series is the combination of: - canonical metric name; - `plant`; - `asset`, where applicable; - `device`, where applicable; - `measurement_point`, where applicable; - additional allowed labels required to disambiguate the measurement, such as `phase`, `string`, `mppt`, or `direction`. The `plant` label value SHALL be globally unique. `asset`, `device`, and `measurement_point` label values SHALL be unique within a Plant. Labels SHALL use controlled values where this standard or the Plant Registry Specification defines a vocabulary. Labels SHALL NOT encode multiple concepts in one field when separate fields are defined. Implementation labels MAY exist outside the canonical model, but they SHALL NOT be required to interpret OCETS telemetry semantics. ## 8. Controlled Vocabularies OCETS v1.1 defines the following controlled vocabularies. The Plant Registry Specification may add stricter schema placement rules for these values. ### 8.1 Role Allowed `role` values: | Value | Meaning | |---|---| | `grid` | Grid interconnection or utility-facing measurement. | | `load` | Consumer or site load measurement. | | `pv` | Photovoltaic generation measurement. | | `battery` | Electrical storage measurement. | | `inverter` | Power conversion device or measurement. | | `meter` | Metering device or measurement. | | `transformer` | Transformer device or measurement. | | `busbar` | Electrical busbar or bus section. | | `collector` | Telemetry acquisition or collection component. | | `environment` | Environmental sensing component. | ### 8.2 Energy Form Allowed `energy_form` values: | Value | Meaning | |---|---| | `electricity_ac` | Alternating-current electricity. | | `electricity_dc` | Direct-current electricity. | | `thermal` | Thermal energy or temperature-related telemetry. | | `environmental` | Environmental conditions. | | `operational` | Platform or equipment health telemetry. | ### 8.3 Status Allowed `status` values: | Value | Meaning | |---|---| | `planned` | Defined but not yet commissioned. | | `active` | In normal service. | | `maintenance` | Temporarily under maintenance. | | `disabled` | Intentionally disabled. | | `retired` | No longer active but retained for history. | ### 8.4 Phase, Direction, and Lifecycle Allowed `phase` values are `l1`, `l2`, `l3`, `n`, and `total`. Allowed `direction` values are `import`, `export`, `charge`, `discharge`, `generation`, `consumption`, and `bidirectional`. Allowed metric lifecycle values are `active`, `proposed`, `deprecated`, and `removed`. ## 9. Power Sign Convention OCETS v1.1 uses a role-based sign convention for instantaneous power metrics. For `active_power`, `reactive_power`, and `apparent_power`: | Role or Measurement Context | Positive Value Means | Negative Value Means | |---|---|---| | `pv` generation or export | Generation/export from the PV source | Reverse flow into the PV source, if measured | | `load` or consumer | Consumption by the load | Reverse export from the load context, if measured | | `battery` | Charging into storage | Discharge/export from storage | | `grid` | Import from grid into the plant | Export from plant to grid | | `inverter` | Direction defined by the associated Measurement Point role | Opposite of the associated Measurement Point role | Implementations SHALL apply this convention before canonical storage. Where the physical source exposes only unsigned values, the Measurement Point role and `direction` label SHALL make the interpretation explicit. Energy counters SHOULD use direction-specific metrics such as `energy_import`, `energy_export`, `energy_charged`, and `energy_discharged` rather than signed accumulated counters. ## 10. Canonical Metrics Canonical metrics SHALL be defined in the Canonical Metric Catalogue. Each canonical metric definition SHALL include: - metric name; - canonical unit; - value type; - aggregation semantics; - semantic definition; - allowed labels; - source class; - lifecycle status. - immutable definition version; - introduction, deprecation, removal, and replacement versions where applicable. Generic electrical metrics SHALL be preferred wherever possible. For example, battery power is represented as `active_power` at a battery Measurement Point, using the role-based sign convention. Domain-specific metric names are reserved for true domain concepts such as `state_of_charge`. ## 11. Canonical Units Each physical quantity SHALL use one canonical storage unit. Unit conversion SHALL occur before canonical storage unless the source value is already in the canonical unit. Reference canonical units include: | Quantity | Canonical Unit | |---|---:| | Active power | kW | | Reactive power | kvar | | Apparent power | kVA | | Energy | kWh | | Voltage | V | | Current | A | | Frequency | Hz | | Temperature | degC | | Ratio | percent | Dashboards and downstream systems SHOULD NOT apply corrective unit conversion to canonical telemetry. ## 12. Plant Registry The Plant Registry SHALL be the authoritative source for: - plants; - assets; - devices; - measurement points; - capabilities; - relationships; - lifecycle status; - canonical labels. The registry SHALL be schema-enforced. Registry data SHALL be validatable before generated configuration or documentation is produced. Collectors, dashboards, alert rules, deployment artifacts, and implementation configuration SHOULD derive from the registry. ## 13. Acquisition Topologies OCETS supports three acquisition topologies: | Topology | Description | |---|---| | Central acquisition | Central systems acquire telemetry from plants. | | Edge acquisition | Plant-local systems acquire and forward telemetry. | | Hybrid acquisition | Edge and central systems share acquisition responsibilities. | All acquisition topologies SHALL emit canonical telemetry with identical identity, units, metrics, labels, and timestamp semantics for the same physical measurement. ## 14. Time Model Telemetry timestamps SHALL represent acquisition time. Processing time, transport time, receive time, storage write time, and dashboard render time SHALL NOT replace acquisition time. All stored timestamps SHALL be represented in UTC. Acquisition systems SHALL synchronize against a centrally managed platform time service or an equivalent redundant time source. ## 15. Telemetry Health Telemetry health SHALL be modeled explicitly. Health telemetry SHOULD include: - device availability; - communication status; - collector status; - last successful acquisition; - timestamp skew; - pipeline status; - data freshness; - validation errors. Missing values SHALL NOT be silently converted to zero. Stale values SHALL NOT be presented as fresh measurements. ### 15.1 Edge Collector Observability Profile The Edge Collector Observability Profile is an optional OCETS conformance profile for plant-local systems that acquire, buffer, or forward telemetry. Implementations that claim this profile SHALL represent the edge collector as a stable Device with `role=collector` and `energy_form=operational`. The profile SHALL expose: - `device_available` for independently observed collector availability; - `collector_status`, `pipeline_status`, and upstream `communication_status`; - `data_freshness` as the age of the latest successful acquisition; - `time_sync_status` and `timestamp_skew`; - `buffer_utilization` and `buffer_oldest_age`; - `storage_utilization` and `storage_status`; - `transport_error_count`, `collector_restart_count`, `mapping_error_count`, and `validation_error_count`. An implementation MAY additionally expose `cpu_utilization`, `memory_utilization`, and `host_temperature`. Where suitable power-monitoring hardware exists, it MAY expose `external_power_available`, `backup_power_status`, and `backup_power_runtime`. Unsupported optional metrics SHALL be absent, not reported as zero or a healthy state. A required metric that cannot currently be determined SHALL use its defined `unknown` state where the metric type permits it. Hostnames, IP addresses, operating-system interface names, mount paths, and hardware serial numbers SHALL NOT form canonical identity. Edge Collector Observability conformance SHALL NOT be required from central-only deployments or from implementations that do not claim the profile. ## 16. Data Lifecycle and Downsampling Telemetry SHALL progress through the following lifecycle: ```text Acquisition -> Validation -> Canonical Mapping -> Storage -> Downsampling -> Long-Term Retention -> Consumption ``` Each lifecycle stage SHALL preserve semantic correctness. Downsampling SHALL respect metric semantics. The aggregation behavior for each metric SHALL be defined in the Canonical Metric Catalogue. Missing values SHALL NOT be converted to zero during downsampling. Retention durations are reference policy, not normative OCETS v1.1 requirements. A conforming implementation MAY choose different retention durations if it preserves the normative downsampling semantics of each metric. ## 17. Canonical Observation Model An Observation is the logical, implementation-independent representation of one telemetry value. Every Observation SHALL be resolvable to: - canonical metric name and catalogue version; - value and the canonical unit implied by the metric definition; - Plant and, where applicable, Asset, Device, and Measurement Point; - `acquired_at` in UTC; - quality; - provenance. The logical model MAY be stored as one record, multiple fields, or coordinated series. A storage implementation SHALL preserve or reconstruct every required property. Quality, provenance, catalogue version, calculation identifiers, and source references SHALL NOT be encoded as unbounded TSDB labels. Forecast-origin Observations SHALL additionally contain `issued_at` and `valid_at`. Derived or calculated Observations SHOULD identify the calculation definition and source Observations or source series. ## 18. Quality Model Every Observation SHALL carry or inherit exactly one quality value: | Value | Meaning | |---|---| | `GOOD` | Valid according to all applicable acquisition and validation rules. | | `BAD` | Known to be invalid and unsuitable for normal consumption. | | `UNCERTAIN` | Available, but validity cannot be established completely. | | `ESTIMATED` | Produced by an estimation method instead of direct acquisition. | | `SUBSTITUTED` | Replaced by an approved alternate value. | | `MISSING` | An explicit gap marker; it SHALL NOT contain a fabricated numeric zero. | | `SIMULATED` | Produced by a simulation rather than the physical process. | Downsampling SHALL report `GOOD` only when every contributing Observation is `GOOD`. Otherwise the conservative precedence from worst to best is `BAD`, `MISSING`, `UNCERTAIN`, `SUBSTITUTED`, `ESTIMATED`, `SIMULATED`, `GOOD`. Implementations MAY retain additional contributing-quality detail. ## 19. Provenance Model Every Observation and Event SHALL declare one origin: | Origin | Meaning | |---|---| | `device` | Directly acquired from a physical or logical Device. | | `calculated` | Deterministically calculated from other data. | | `forecast` | Produced externally as a prediction. | | `estimated` | Inferred because a direct value was unavailable or incomplete. | | `manual` | Supplied or corrected by an authenticated human workflow. | | `simulated` | Produced by a simulation or test environment. | Provenance SHALL identify the originating Device, calculation, model, or authenticated actor as applicable. Manual changes and substitutions SHALL be auditable. Provenance describes origin; quality describes confidence or usability, and neither SHALL replace the other. ## 20. Canonical Event Model Events are not Metrics and SHALL NOT be modeled as ordinary time-series samples. A canonical Event SHALL include: - globally unique `event_id`; - canonical `event_type` and `severity`; - typed source reference to a registered object; - `begin_at` and optional `end_at`, in UTC; - lifecycle state `open`, `acknowledged`, `closed`, or `cancelled`; - quality and provenance; - optional `correlation_id` and `causation_id`. Severity values are `info`, `warning`, `minor`, `major`, and `critical`. Initial event types are `alarm`, `warning`, `fault`, `maintenance`, `restart`, `firmware_update`, and `grid_failure`. Acknowledgement SHALL record actor, timestamp, and optional comment without overwriting event history. Re-delivery or update of an `event_id` SHALL be idempotent. `end_at` SHALL NOT precede `begin_at`. Event payloads MAY contain bounded type-specific attributes but SHALL NOT contain secrets. ## 21. Relationship and Topology Model A Relationship SHALL have a stable ID, Plant, Topology, type, typed `from` and `to` endpoints, lifecycle status, and validity interval. Allowed relationship types are: - `contains`; - `feeds`; - `connected_to`; - `measures`; - `controls`; - `powered_by`. `contains`, `feeds`, `measures`, `controls`, and `powered_by` are directed. `connected_to` is symmetric and SHALL NOT be duplicated in reverse order. A `controls` Relationship records semantic responsibility only and SHALL NOT imply command authorization or OCETS control conformance. A Topology is an immutable versioned graph for exactly one Plant. Its kind SHALL be `electrical`, `physical`, or `telemetry`. Grid connections, transformers, busbars, inverters, batteries, loads, collectors, Devices, and Measurement Points SHALL be represented using registered objects rather than topology-only identifiers. `contains` Relationships SHALL be acyclic. Electrical networks MAY be meshed; cycles in `feeds` and `connected_to` are permitted. Topology versions SHALL have non-overlapping validity intervals when they claim to be the active version of the same topology. ## 22. Multi-Tenancy An Organization is the tenant, ownership, authorization, and governance boundary. An Organization SHALL have a globally unique stable ID. A Portfolio SHALL belong to exactly one Organization. A Plant SHALL belong to exactly one Organization and MAY belong to zero or more Portfolios of that Organization. Canonical Plant identity remains globally unique and SHALL NOT depend on an Organization or Portfolio name. Relationships and Topologies SHALL NOT cross Organization boundaries. Cross-organization analysis MAY occur in an authorized consumer but SHALL NOT create cross-tenant registry ownership. Organization and Plant metadata MAY declare a data residency region. Such metadata informs deployment policy but does not replace applicable law or operator policy. ## 23. Registry API Profile A conforming Registry API SHALL provide authenticated, read-only HTTP/JSON access under `/api/ocets/registry/v1` to: - service metadata and available Registry revisions; - Organizations, Portfolios, Plants, Assets, Devices, Measurement Points; - Relationships, Topologies, Metric Definitions, and Event Types; - one consistent bulk snapshot; - changes since a retained Registry revision. Collections SHALL support opaque cursor pagination, a bounded `limit`, and filters for tenant, lifecycle status, and `updated_since`. Every response SHALL identify one immutable Registry revision. Implementations SHALL support `ETag` and `If-None-Match`; pagination across one traversal SHALL remain snapshot-consistent. Errors SHALL use a JSON object containing stable `code`, human-readable `message`, and `request_id`. Resource absence SHALL be distinguishable from lack of authorization without leaking cross-tenant existence. Mutation, approval, and deployment APIs are outside this profile. ## 24. Security Model OCETS implementations SHALL: - use distinct identities for people, services, collectors, and Devices; - authenticate every non-public Registry API and telemetry connection; - encrypt telemetry and Registry traffic in transit; - apply default-deny authorization by Organization, resource, and action; - prevent credentials, private keys, tokens, and other secrets from entering Registry data, labels, Events, or logs; - protect sensitive data at rest according to its classification and residency policy; - audit Registry changes, manual provenance, Event acknowledgement, authorization changes, and security-relevant access; - support credential and certificate rotation without semantic identity changes. Network location alone SHALL NOT establish trust. Service and collector permissions SHALL follow least privilege. Audit records SHOULD be tamper-evident and retained under governed policy. Security incidents and credential compromise SHALL have documented revocation and recovery procedures. ## 25. Governance OCETS uses semantic versioning. Governance roles are Maintainer, Architecture Review Board, and Extension Owner. Normative changes SHALL have an identified owner, review record, compatibility assessment, and, when architectural, an ADR. Version 1.x releases MAY add canonical metrics, labels, capabilities, optional registry fields, event types, and non-breaking clarifications. Version 2.0 is required for changed identity semantics, changed canonical units, removed required fields, incompatible timestamp rules, or incompatible metric meanings. Metric definitions SHALL record `definition_version`, `introduced_in`, `deprecated_in`, `removed_in`, and `replaced_by` where applicable. A released definition is immutable. Deprecation SHALL provide a replacement or rationale and remain supported for at least one subsequent minor release before removal. Local extensions SHALL use `x--` namespaces and SHALL NOT redefine canonical names or controlled values. Released catalogue and conformance-profile versions SHALL remain retrievable. Security reports SHALL have a documented confidential disclosure and remediation process. ## 26. Conformance Core OCETS v1.1 conformance requires an implementation to: - implement the canonical information and Observation models; - use canonical metric names, units, quality, and provenance; - use the role-based power sign convention and OCETS timestamp rules; - expose telemetry health and enforce the Security Model; - validate Registry data against a schema or equivalent enforceable contract; - satisfy all mandatory `SHALL` requirements and preserve implementation separation. Event, Topology, Multi-Tenancy, Registry API, and Edge Collector Observability are claimable conformance profiles. An implementation SHALL satisfy every mandatory rule of each profile it claims. Representing only one Organization does not waive tenant isolation requirements if the Multi-Tenancy profile is claimed. Conformance does not require a specific software stack, control capability, or preservation of legacy and vendor-specific names. --- # SOURCE: docs/03_Canonical_Metric_Catalogue_v1.1.md --- title: "OCETS Canonical Metric Catalogue" version: "1.1" status: "Architecture Review Candidate" release: "July 2026" identifier: "OCETS-METRICS-1.1" --- # OCETS Canonical Metric Catalogue **Document:** 3 of 5 **Type:** Normative Catalogue **Version:** 1.1 **Status:** Architecture Review Candidate **Compatibility:** OCETS 1.1 ## 1. Purpose The Canonical Metric Catalogue defines the canonical metrics used by OCETS. Each metric has one semantic meaning, one canonical unit, one value type, defined aggregation behavior, allowed labels, and lifecycle status. ## 2. Catalogue Rules Metric names are canonical by themselves. OCETS telemetry SHALL NOT require a redundant label that repeats the metric name. Generic electrical metrics SHALL be preferred. For example, battery charge or discharge power is represented as `active_power` at a battery Measurement Point with role-based sign semantics, not as a separate `battery_power` metric. Forecast-generation models are outside OCETS v1.1. An externally generated forecast Observation MAY use an existing canonical Metric with `origin=forecast` only when it carries explicit `issued_at` and `valid_at` timestamps. ## 3. Metric Definition Fields Each metric definition SHALL include: | Field | Description | |---|---| | Name | Canonical metric identifier | | Unit | Canonical storage unit | | Type | Value type | | Aggregation | Downsampling or rollup behavior | | Description | Semantic definition | | Labels | Allowed or expected labels | | Source | Measured, derived, or operational | | Status | Active, proposed, deprecated, or removed | | Definition Version | Immutable semantic version of this definition | | Introduced In | First OCETS release containing the definition | | Deprecated In | OCETS release that deprecated it, where applicable | | Removed In | OCETS release that removed it, where applicable | | Replaced By | Canonical replacement metric, where applicable | Every active v1.1 metric has `definition_version=1.0.0` and `introduced_in=1.1` unless its row explicitly states otherwise. Empty lifecycle fields mean not deprecated, not removed, and not replaced. Released definitions SHALL NOT be edited in place. ## 4. Value Types | Type | Meaning | |---|---| | gauge | Instantaneous value | | counter | Monotonically increasing value | | state | Discrete state value | | event | Point-in-time event | | derived | Calculated value | ## 5. Aggregation Types | Aggregation | Meaning | |---|---| | avg | Average over time window | | min | Minimum over time window | | max | Maximum over time window | | sum | Sum over time window | | delta | Difference over time window | | last | Last known value | | worst | Worst observed state | | none | No aggregation permitted | ## 6. Common Allowed Labels Common labels include: - `plant`; - `asset`; - `device`; - `measurement_point`; - `role`; - `energy_form`; - `phase`; - `direction`; - `string`; - `mppt`; - `status`. The Plant Registry Specification defines allowed values and placement rules for these labels. ## 7. Power Sign Convention Instantaneous power metrics SHALL follow the role-based power sign convention defined in OCETS: - PV generation/export is positive. - Consumer/load power is positive. - Battery charging is positive. - Battery discharge/export is negative. - Grid import into the plant is positive. - Grid export from the plant is negative. Energy counters SHOULD use direction-specific metric names and SHOULD NOT rely on signed accumulated counter values. ## 8. Electrical Metrics | Name | Unit | Type | Aggregation | Labels | Source | Status | Description | |---|---:|---|---|---|---|---|---| | `active_power` | kW | gauge | avg,min,max | role, energy_form, phase, direction | measured or derived | active | Instantaneous active power with OCETS sign convention. | | `reactive_power` | kvar | gauge | avg,min,max | role, energy_form, phase, direction | measured or derived | active | Instantaneous reactive power. | | `apparent_power` | kVA | gauge | avg,min,max | role, energy_form, phase, direction | measured or derived | active | Instantaneous apparent power. | | `power_factor` | percent | gauge | avg,min,max | role, energy_form, phase | measured or derived | active | Ratio of active power to apparent power. | | `frequency` | Hz | gauge | avg,min,max | role, energy_form | measured | active | Electrical frequency. | | `voltage` | V | gauge | avg,min,max | role, energy_form, phase, string, mppt | measured | active | Electrical voltage. | | `current` | A | gauge | avg,min,max | role, energy_form, phase, string, mppt, direction | measured | active | Electrical current. | ## 9. Energy Metrics | Name | Unit | Type | Aggregation | Labels | Source | Status | Description | |---|---:|---|---|---|---|---|---| | `energy_import` | kWh | counter | delta,sum | role, energy_form, direction | measured or derived | active | Electrical energy imported into a Measurement Point. | | `energy_export` | kWh | counter | delta,sum | role, energy_form, direction | measured or derived | active | Electrical energy exported from a Measurement Point. | | `energy_generated` | kWh | counter | delta,sum | role, energy_form | measured or derived | active | Electrical energy generated by a source. | | `energy_consumed` | kWh | counter | delta,sum | role, energy_form | measured or derived | active | Electrical energy consumed by a load. | | `energy_charged` | kWh | counter | delta,sum | role=battery, energy_form | measured or derived | active | Energy charged into storage. | | `energy_discharged` | kWh | counter | delta,sum | role=battery, energy_form | measured or derived | active | Energy discharged from storage. | ## 10. Battery State Metrics | Name | Unit | Type | Aggregation | Labels | Source | Status | Description | |---|---:|---|---|---|---|---|---| | `state_of_charge` | percent | gauge | avg,min,max,last | role=battery | measured or derived | active | Battery state of charge from 0 to 100 percent. | | `state_of_health` | percent | gauge | avg,min,max,last | role=battery | measured or derived | active | Battery state of health from 0 to 100 percent. | | `charge_limit` | kW | gauge | min,last | role=battery | measured or derived | active | Current maximum charging power limit. | | `discharge_limit` | kW | gauge | min,last | role=battery | measured or derived | active | Current maximum discharging power limit. | Battery voltage, current, temperature, and power SHALL use the generic metrics `voltage`, `current`, `temperature`, and `active_power` with battery Measurement Points and labels. ## 11. Environmental Metrics | Name | Unit | Type | Aggregation | Labels | Source | Status | Description | |---|---:|---|---|---|---|---|---| | `temperature` | degC | gauge | avg,min,max | role, measurement_point | measured | active | Generic temperature measurement. | | `ambient_temperature` | degC | gauge | avg,min,max | role=environment | measured | active | Ambient air temperature. | | `irradiance` | W_per_m2 | gauge | avg,min,max | role=environment, plane | measured | active | Solar irradiance. | | `wind_speed` | m_per_s | gauge | avg,min,max | role=environment | measured | active | Wind speed. | ## 12. Telemetry Health Metrics | Name | Unit | Type | Aggregation | Labels | Source | Status | Description | |---|---:|---|---|---|---|---|---| | `device_available` | bool | state | worst,last | status | operational | active | Whether the device is available for telemetry. | | `communication_status` | enum | state | worst,last | status | operational | active | Communication state for a device or path. | | `collector_status` | enum | state | worst,last | status | operational | active | Collector process or service state. | | `data_freshness` | s | gauge | max,last | role | operational | active | Age of the latest successful telemetry sample. | | `timestamp_skew` | s | gauge | avg,max | role | operational | active | Difference between acquisition clock and reference time. | | `mapping_error_count` | count | counter | delta,sum | role | operational | active | Count of mapping errors. | | `validation_error_count` | count | counter | delta,sum | role | operational | active | Count of validation errors. | | `pipeline_status` | enum | state | worst,last | role=collector, status | operational | active | End-to-end acquisition, mapping, buffering, and forwarding state. | | `time_sync_status` | enum | state | worst,last | role=collector, status | operational | active | Whether the acquisition clock is synchronized to an approved reference. | | `buffer_utilization` | percent | gauge | avg,max,last | role=collector | operational | active | Used capacity of the telemetry buffer from 0 to 100 percent. | | `buffer_oldest_age` | s | gauge | max,last | role=collector | operational | Age of the oldest telemetry sample awaiting successful forwarding. | | `storage_utilization` | percent | gauge | avg,max,last | role=collector, measurement_point | operational | active | Used capacity of storage required by the telemetry pipeline. | | `storage_status` | enum | state | worst,last | role=collector, measurement_point, status | operational | active | Health of storage required by the telemetry pipeline. | | `transport_error_count` | count | counter | delta,sum | role=collector | operational | active | Count of failures while forwarding telemetry upstream. | | `collector_restart_count` | count | counter | delta,sum | role=collector | operational | Count of collector process restarts. Counter resets SHALL be handled as counter resets, not negative deltas. | | `cpu_utilization` | percent | gauge | avg,max | role=collector | operational | active | Optional aggregate CPU utilization from 0 to 100 percent. | | `memory_utilization` | percent | gauge | avg,max | role=collector | operational | active | Optional non-reclaimable memory utilization from 0 to 100 percent. | | `host_temperature` | degC | gauge | avg,max | role=collector, measurement_point | operational | active | Optional edge-host component temperature; not an environmental measurement. | | `external_power_available` | bool | state | worst,last | role=collector, measurement_point | operational | active | Optional indication that the edge collector's external power source is available. | | `backup_power_status` | enum | state | worst,last | role=collector, measurement_point, status | operational | active | Optional backup-power operating state. | | `backup_power_runtime` | s | gauge | min,last | role=collector, measurement_point | operational | active | Optional estimated remaining backup-power runtime. | ### 12.1 Operational State Values State metrics SHALL use the following values: | Metric | Allowed values | |---|---| | `collector_status`, `pipeline_status`, `storage_status` | `healthy`, `degraded`, `failed`, `unknown` | | `communication_status` | `connected`, `degraded`, `disconnected`, `unknown` | | `time_sync_status` | `synchronized`, `unsynchronized`, `unknown` | | `backup_power_status` | `charging`, `charged`, `discharging`, `low`, `failed`, `unknown` | `unknown` means that state cannot currently be determined. It SHALL NOT be treated as healthy. For worst-state aggregation, the order from best to worst is the order shown in each row, except that `unknown` is always worse than a known healthy or connected state and better than a known failed or disconnected state. Backup-power states SHALL use `last`; `worst` refers to `failed`, then `low`, for alert rollups. ## 13. Status Lifecycle | Status | Meaning | |---|---| | active | Metric is part of OCETS v1.1. | | proposed | Metric is under review and not required for conformance. | | deprecated | Metric remains documented for migration but should not be used for new telemetry. | | removed | Metric is no longer part of the catalogue. | Changing a metric's meaning, canonical unit, or aggregation behavior is a breaking change unless a new metric name is introduced. Deprecated metrics SHOULD remain documented until retained data and reference implementations have migrated. ## 14. Observation Metadata Quality and provenance are properties of an Observation, not additional Metrics and not part of the Metric name. Every catalogue Metric SHALL be usable with the OCETS quality values `GOOD`, `BAD`, `UNCERTAIN`, `ESTIMATED`, `SUBSTITUTED`, `MISSING`, and `SIMULATED` and origins `device`, `calculated`, `forecast`, `estimated`, `manual`, and `simulated`. Aggregation SHALL propagate Observation quality according to the OCETS Quality Model. Aggregating a Metric SHALL NOT erase provenance needed to distinguish measured, calculated, estimated, manual, forecast, or simulated data. --- # SOURCE: docs/04_Plant_Registry_Specification_v1.1.md --- title: "OCETS Plant Registry Specification" version: "1.1" status: "Architecture Review Candidate" release: "July 2026" identifier: "OCETS-REGISTRY-1.1" --- # OCETS Plant Registry Specification **Document:** 4 of 5 **Type:** Normative Registry Specification **Version:** 1.1 **Status:** Architecture Review Candidate **Compatibility:** OCETS 1.1 ## 1. Purpose The Plant Registry is the authoritative, schema-enforced source of truth for OCETS platform objects, ownership, topology, capabilities, and controlled metadata. It supports validation, configuration generation, discovery, authorization scope, documentation, and historical interpretation. ## 2. Registry Principles - Every logical object has exactly one authoritative definition and stable ID. - Plant and Organization IDs are globally unique; other IDs are unique within their documented scope. - Transport addresses, hostnames, protocol fields, and replaceable hardware identifiers are not semantic identity. - Released Registry revisions are immutable, traceable, and available to interpret retained data. - Generated configuration derives from Registry data and does not become another source of truth. - Credentials, private keys, tokens, and other secrets SHALL NOT be stored in the Registry. ## 3. Object Model ```text Organization -> Portfolio -> Plant -> Asset -> Device -> Measurement Point -> Capability Plant -> Topology -> Relationship -> typed registered endpoints ``` A Plant belongs to exactly one Organization and MAY belong to multiple Portfolios of that Organization. Relationships do not replace the required ownership references in the hierarchy. ## 4. Controlled Vocabularies | Vocabulary | Allowed values | |---|---| | lifecycle `status` | `planned`, `active`, `maintenance`, `disabled`, `retired` | | `role` | `grid`, `load`, `pv`, `battery`, `inverter`, `meter`, `transformer`, `busbar`, `collector`, `environment` | | `energy_form` | `electricity_ac`, `electricity_dc`, `thermal`, `environmental`, `operational` | | `phase` | `l1`, `l2`, `l3`, `n`, `total` | | `direction` | `import`, `export`, `charge`, `discharge`, `generation`, `consumption`, `bidirectional` | | topology `kind` | `electrical`, `physical`, `telemetry` | | relationship `type` | `contains`, `feeds`, `connected_to`, `measures`, `controls`, `powered_by` | | endpoint `kind` | `plant`, `asset`, `device`, `measurement_point` | ## 5. Organization and Portfolio An Organization requires `id`, `name`, and `status`; it MAY declare `data_residency_region` and tags. Its ID is globally unique and establishes the tenant, governance, and authorization boundary. A Portfolio requires `id`, `organization_id`, `name`, and `status`. Portfolio IDs are unique within one Organization. Portfolios group Plants and do not change Plant identity or ownership. ## 6. Plant A Plant requires `id`, `organization_id`, `name`, `timezone`, and `status`. It MAY declare `portfolio_ids`, `country`, `operator`, `commissioned_at`, `data_residency_region`, and tags. Every `portfolio_id` SHALL resolve to a Portfolio in the same Organization. Plant IDs are globally unique. Country values SHOULD use ISO 3166-1 alpha-2 and timezone values SHOULD use IANA timezone identifiers. ## 7. Asset and Device An Asset requires `id`, `plant_id`, `type`, `name`, and `status`. It MAY declare vendor, model, serial number, location, and commissioning time. Asset IDs are unique within a Plant. A Device requires `id`, `plant_id`, `asset_id`, `role`, `energy_form`, and `status`. It MAY declare vendor, model, protocols, implementation-specific communication data, profiles, and capabilities. Device IDs are unique within a Plant. A Device claiming `edge_collector_observability` SHALL use `role=collector`, `energy_form=operational`, and list every required profile Metric. Its ID SHALL NOT derive solely from hostname, IP address, or replaceable serial number. ## 8. Measurement Point and Capability A Measurement Point requires `id`, `plant_id`, `device_id`, `type`, and `name`. It MAY declare role, energy form, phase, string, MPPT, direction, nominal voltage, or parent Measurement Point. IDs are unique within a Plant. A Capability references a canonical Metric name from the versioned Canonical Metric Catalogue. Local capabilities SHALL use an `x--` namespace. Capabilities do not imply that current data is healthy or available. ## 9. Topology A Topology requires `id`, `plant_id`, `kind`, immutable positive integer `version`, `name`, `status`, and `valid_from`; it MAY declare `valid_to`. Topology IDs are unique within a Plant, while `(plant_id, id, version)` identifies a specific graph version. Versions of the same active Topology SHALL have non-overlapping validity intervals. `valid_to` SHALL be later than `valid_from`. Grid connections, transformers, busbars, inverters, batteries, loads, collectors, and their semantic points SHALL be registered as Assets, Devices, or Measurement Points rather than embedded anonymous nodes. ## 10. Relationship A Relationship requires `id`, `plant_id`, `topology_id`, `topology_version`, `type`, `from`, `to`, `status`, and `valid_from`; it MAY declare `valid_to`. Endpoints are objects with `kind` and `id`. All endpoints SHALL exist in the Relationship Plant. `contains` SHALL be acyclic. `connected_to` is symmetric and SHALL occur only once for an unordered endpoint pair. Other relationship types are directed. Electrical `feeds` and `connected_to` graphs MAY contain cycles. Recommended endpoint constraints are: | Type | From | To | |---|---|---| | `contains` | Plant, Asset, or Device | Asset, Device, or Measurement Point | | `feeds` | Asset or Measurement Point | Asset or Measurement Point | | `connected_to` | Asset or Measurement Point | Asset or Measurement Point | | `measures` | Device or Measurement Point | Asset or Measurement Point | | `controls` | Device | Asset or Device | | `powered_by` | Asset or Device | Asset or Measurement Point | `controls` records a semantic relationship only; command authorization and behavior remain outside OCETS v1.1. ## 11. Registry Example ```yaml version: "1.1" registry_id: "example-registry" revision: "2026-07-13T10:00:00Z" organizations: - id: "example-energy" name: "Example Energy" status: "active" portfolios: - id: "germany" organization_id: "example-energy" name: "German Plants" status: "active" plants: - id: "plant-example" organization_id: "example-energy" portfolio_ids: ["germany"] name: "Example Plant" timezone: "Europe/Berlin" country: "DE" status: "active" assets: - id: "transformer-01" plant_id: "plant-example" type: "transformer" name: "Transformer 01" status: "active" - id: "busbar-01" plant_id: "plant-example" type: "busbar" name: "Main Busbar" status: "active" devices: - id: "meter-01" plant_id: "plant-example" asset_id: "transformer-01" role: "meter" energy_form: "electricity_ac" status: "active" capabilities: ["active_power", "voltage", "current"] measurement_points: - id: "mp-transformer-secondary" plant_id: "plant-example" device_id: "meter-01" type: "transformer_secondary" name: "Transformer Secondary" role: "transformer" energy_form: "electricity_ac" topologies: - id: "primary-electrical" plant_id: "plant-example" kind: "electrical" version: 1 name: "Primary Electrical Topology" status: "active" valid_from: "2026-07-01T00:00:00Z" relationships: - id: "rel-transformer-busbar" plant_id: "plant-example" topology_id: "primary-electrical" topology_version: 1 type: "feeds" from: {kind: "asset", id: "transformer-01"} to: {kind: "asset", id: "busbar-01"} status: "active" valid_from: "2026-07-01T00:00:00Z" ``` ## 12. Normative JSON Schema Registry implementations SHALL validate against JSON Schema Draft 2020-12 or an equivalent enforceable contract. The complete normative schema is maintained as `implementation/registry/schema/plant-registry-v1.1.schema.json`; its `$id`, version constant, definitions, and controlled vocabularies are part of OCETS-REGISTRY-1.1. Implementations MAY add stricter local validation but SHALL NOT accept data forbidden by the normative schema. Cross-reference, tenant-boundary, graph, interval, catalogue, and profile rules from Section 13 remain mandatory even where JSON Schema cannot express them. ## 13. Validation Rules Validation SHALL ensure: - all required IDs are unique in their documented scopes; - ownership and endpoint references exist and remain within one Organization and Plant; - Portfolio membership never crosses an Organization; - Topology and Relationship validity intervals are ordered and active versions do not overlap; - `contains` graphs are acyclic and symmetric Relationships are not duplicated; - capabilities reference known versioned Metrics or valid local extensions; - claimed conformance profiles are complete; - implementation addresses and secrets do not replace or enter semantic identity. ## 14. Registry API Profile The base path is `/api/ocets/registry/v1`. `GET /` returns service metadata and the current immutable Registry revision. Collections and `/{id}` resources SHALL exist for `organizations`, `portfolios`, `plants`, `assets`, `devices`, `measurement-points`, `relationships`, `topologies`, `metric-definitions`, and `event-types`. `GET /snapshot` returns one revision-consistent bulk representation. `GET /changes?since=` returns retained changes after a known revision. Collections use opaque `cursor`, bounded `limit`, and optional `organization_id`, `plant_id`, `status`, and `updated_since` filters where applicable. Every success response identifies `registry_revision` and emits an `ETag`. `If-None-Match` SHALL be supported. Cursors SHALL remain bound to the revision that created them. Errors contain `code`, `message`, and `request_id`. Authentication and tenant authorization are mandatory; an implementation SHALL avoid revealing whether an unauthorized cross-tenant resource exists. The profile is read-only. Registry mutation, approval, deployment, and rollback APIs are implementation-specific. ## 15. Generated Outputs The Registry MAY generate collector configuration, transport mappings, storage labels, dashboards, alerts, API caches, documentation, and topology diagrams. Outputs SHALL identify their source Registry revision and SHALL NOT become independent sources of truth. ## 16. Change Governance Registry changes SHALL be reviewed, attributable, and associated with an immutable revision. Breaking identity changes require a migration plan. Deprecated and retired objects remain resolvable for historical interpretation. Security-sensitive changes and manual corrections require an audit record. --- # SOURCE: docs/05_Architecture_Decision_Records_v1.1.md --- title: "OCETS Architecture Decision Records" version: "1.1" status: "Architecture Review Candidate" release: "July 2026" identifier: "OCETS-ADR-1.1" --- # OCETS Architecture Decision Records **Document:** 5 of 5 **Type:** Architecture Decision Log **Version:** 1.1 **Status:** Architecture Review Candidate **Compatibility:** OCETS 1.1 ## 1. Purpose Architecture Decision Records document why OCETS decisions were made. The standard defines the rules. ADRs preserve the reasoning behind those rules so future maintainers can distinguish intentional design from historical accident. ## 2. ADR Format Each ADR SHOULD include: - identifier; - title; - status; - date; - context; - decision; - consequences; - alternatives considered; - affected documents. ## ADR-001: Canonical Units **Status:** Accepted **Date:** July 2026 **Affected Documents:** OCETS, Canonical Metric Catalogue ### Context Energy telemetry arrives from different vendors and protocols using different units, scale factors, register encodings, and firmware conventions. One inverter may report watts, another kilowatts, and a meter may expose scaled integer registers. If unit conversion is deferred to dashboards or queries, different consumers may interpret the same value differently. This produces inconsistent visualizations, invalid comparisons, and fragile alert rules. ### Decision Each physical quantity has exactly one canonical storage unit. Unit conversion occurs during ingestion before canonical storage. Stored OCETS telemetry uses practical engineering units such as `kW`, `kWh`, `V`, `A`, `Hz`, `degC`, and `percent`. ### Consequences Dashboards and downstream consumers can assume stable units. Ingestion mappings must handle vendor-specific scale factors correctly and must be tested with captured source data. Changing a canonical unit is a breaking change because retained data, dashboards, and alert rules depend on the stored meaning. ### Alternatives Considered Storing vendor-native units was rejected because it pushes semantic repair into every consumer. Storing SI base units everywhere was rejected because it makes operational dashboards less practical and increases the likelihood of display-time conversion mistakes. ## ADR-002: Measurement Points **Status:** Accepted **Date:** July 2026 **Affected Documents:** OCETS, Plant Registry Specification ### Context The same metric may apply to different physical or electrical locations. For example, active power may be measured at an inverter output, grid connection, battery interface, site load, PV string, or transformer secondary. Creating a separate metric name for each location causes metric proliferation and makes cross-system comparison difficult. ### Decision OCETS separates Metric from Measurement Point. The Metric defines what is measured. The Measurement Point defines where it is measured. Labels such as `role`, `phase`, `direction`, `string`, and `mppt` further qualify the measurement when needed. ### Consequences Queries can compare the same metric across multiple locations without creating many metric names. The registry must define Measurement Points explicitly and keep their identifiers stable. Implementations must map vendor fields into both a canonical metric name and a Measurement Point, not merely rename fields. ### Alternatives Considered Encoding location into metric names was rejected because it creates avoidable duplicates such as battery-specific or PV-string-specific power metrics. Relying only on device identity was rejected because one Device may expose several semantically distinct points. ## ADR-003: Timestamp Assignment **Status:** Accepted **Date:** July 2026 **Affected Documents:** OCETS ### Context Telemetry may pass through collectors, brokers, queues, processors, and databases. Each stage has a different processing time and can experience delay or retry behavior. Using storage time or receive time as the measurement timestamp makes delayed telemetry appear to have occurred later than it did. ### Decision Telemetry timestamps represent acquisition time. Processing time, transport time, receive time, and storage time do not replace acquisition time. Stored timestamps are represented in UTC. ### Consequences Acquisition components must assign or preserve timestamps. Pipeline delay can be monitored separately from measurement time. Backfilled or delayed telemetry remains analytically useful because the original measurement time is retained. ### Alternatives Considered Using storage time was rejected because it hides transport delay. Using dashboard render time was rejected because it changes every time data is viewed. Allowing each layer to overwrite timestamps was rejected because it destroys event ordering. ## ADR-004: Central Time Service **Status:** Accepted **Date:** July 2026 **Affected Documents:** OCETS, Reference Implementation Guide ### Context Distributed acquisition systems require consistent time. Edge collectors may run independently and continue collecting during connectivity interruptions. Clock skew across collectors makes plant-level correlation unreliable, especially when comparing fast-changing power, frequency, and communication-health signals. ### Decision Acquisition systems synchronize against a centrally managed time service or an equivalent redundant time source. Timestamp generation remains local to acquisition, but the local clock must be monitored and corrected. ### Consequences The platform can detect timestamp skew. Telemetry remains usable during temporary transport disruptions if local clocks remain synchronized. Operational monitoring must include time synchronization health. ### Alternatives Considered Relying on database write time was rejected for the reasons in ADR-003. Requiring a single central acquisition point was rejected because OCETS must support edge and hybrid topologies. ## ADR-005: Retention and Downsampling **Status:** Accepted **Date:** July 2026 **Affected Documents:** OCETS, Canonical Metric Catalogue ### Context High-resolution telemetry is valuable for short-term diagnosis, while long-term storage requires downsampling. Different metrics require different aggregation behavior: gauges may average cleanly, counters require deltas, and states often need worst or last semantics. Retention duration depends on operational, legal, and storage-cost policy. Downsampling semantics depend on metric meaning. ### Decision OCETS v1.1 makes downsampling semantics normative and treats retention durations as reference policy. The metric catalogue defines aggregation behavior for each metric. Implementations may choose retention durations appropriate to their operating environment if the semantic aggregation rules are preserved. ### Consequences Retention can be optimized without destroying semantic meaning. The metric catalogue must define aggregation behavior. Operators can adjust storage policy without creating a new OCETS version, provided they do not change metric semantics. ### Alternatives Considered Mandating exact retention periods was rejected because storage constraints vary by deployment. Leaving downsampling entirely implementation-specific was rejected because it leads to invalid long-term aggregates. ## ADR-006: Acquisition Topologies **Status:** Accepted **Date:** July 2026 **Affected Documents:** OCETS, Reference Implementation Guide ### Context Plants may be connected through different network conditions and operational models. Some installations favor central collection. Others require edge buffering, local polling, or hybrid acquisition. Topology differences should not change telemetry semantics. ### Decision OCETS supports central, edge, and hybrid acquisition topologies. All topologies must emit identical canonical telemetry for identical measurements. ### Consequences The standard remains independent of deployment topology. Reference implementations can evolve without changing canonical semantics. Implementation-specific routing, buffering, and transport details remain outside the normative model. ### Alternatives Considered Mandating edge acquisition was rejected because some plants are reachable and simple enough for central acquisition. Mandating central acquisition was rejected because it cannot handle every site topology or resilience requirement. ## ADR-007: Schema-Enforced Registry as Source of Truth **Status:** Accepted **Date:** July 2026 **Affected Documents:** OCETS, Plant Registry Specification, Reference Implementation Guide ### Context Manual duplication of plant, device, label, dashboard, and collector configuration causes drift. Drift leads to inconsistent labels, duplicate time series, onboarding errors, and difficult audits. A prose-only registry definition is not enough because invalid data can still be merged or deployed. ### Decision The Plant Registry is the authoritative source of truth for logical platform objects and is schema-enforced. Operational configuration should be generated from the registry. Registry data must be validatable before generated configuration or documentation is produced. ### Consequences New plant onboarding becomes primarily a configuration task. Registry governance becomes operationally important. Implementations must maintain validation checks for required fields, controlled vocabularies, references, and identity scope. ### Alternatives Considered Using generated collector configuration as the source of truth was rejected because generated files are implementation artifacts. Maintaining a spreadsheet-only registry was rejected because it is hard to validate rigorously and integrate into deployment workflows. ## ADR-008: Telemetry Health as First-Class Telemetry **Status:** Accepted **Date:** July 2026 **Affected Documents:** OCETS, Canonical Metric Catalogue ### Context Missing data, stale data, measured zero, communication failure, device failure, and validation failure are different conditions. If health is inferred only from process values, dashboards and automation may make incorrect assumptions. For example, missing inverter power is not the same as zero inverter power. ### Decision Telemetry health is modeled explicitly using canonical operational metrics. Health includes device availability, communication status, collector status, freshness, timestamp skew, mapping errors, and validation errors. ### Consequences Consumers can distinguish process state from telemetry pipeline state. Implementations must collect and expose health signals. Alerting can be based on explicit operational conditions rather than fragile inference. ### Alternatives Considered Inferring health from absent samples was rejected because it cannot distinguish outage classes. Using implementation-specific process checks alone was rejected because consumers need health in the same semantic model as process telemetry. ## ADR-009: Implementation Separation **Status:** Accepted **Date:** July 2026 **Affected Documents:** All OCETS documents ### Context The platform may use concrete tools and vendor integrations, but those tools will evolve. Vendor register maps, collector configurations, storage backends, and dashboard frameworks change faster than the canonical information model. Embedding tool-specific implementation details in the normative standard would make the standard unstable. ### Decision The normative standard excludes collector configuration, transport topic examples, vendor register maps, transformation scripts, dashboard definitions, and deployment details. Those details belong in the Reference Implementation Guide or implementation-specific appendices. ### Consequences The normative standard can remain stable while implementation documentation changes. Conformance is based on emitted canonical telemetry and registry semantics, not on using a particular software stack. ### Alternatives Considered Making the current implementation the standard was rejected because it would freeze incidental choices. Keeping all content in one document was rejected because it mixes durable semantics with operational recipes. ## ADR-010: Metric Name Only Representation **Status:** Accepted **Date:** July 2026 **Affected Documents:** OCETS, Canonical Metric Catalogue, Reference Implementation Guide ### Context Time-series systems commonly represent a series using a metric name plus labels. Some implementations also add a label that repeats the metric name. Duplicating the metric name as both name and label creates unnecessary cardinality and introduces opportunities for contradiction. ### Decision OCETS uses the metric name itself as the canonical metric representation. Telemetry does not need a redundant label that restates the metric name. Labels describe context such as Plant, Asset, Device, Measurement Point, role, phase, direction, string, or MPPT channel. ### Consequences The model is simpler and easier to validate. Queries should use metric names directly. Implementations with legacy redundant labels may retain them as non-canonical implementation metadata during migration, but they are not OCETS compatibility requirements. ### Alternatives Considered Keeping a redundant metric label was rejected because it adds no semantic value. Using only labels without canonical metric names was rejected because it makes storage and query behavior harder to standardize. ## ADR-011: Role-Based Power Sign Convention **Status:** Accepted **Date:** July 2026 **Affected Documents:** OCETS, Canonical Metric Catalogue, Reference Implementation Guide ### Context Power sign conventions vary by vendor and by device. Battery power is especially inconsistent: some devices report discharge as positive, others report charge as positive. Grid meters may also differ on import and export signs. Without a common convention, dashboards and derived metrics are unreliable. ### Decision OCETS defines a role-based sign convention for instantaneous power. PV generation/export is positive. Consumer/load power is positive. Battery charging is positive and battery discharge/export is negative. Grid import into the plant is positive and grid export from the plant is negative. ### Consequences Ingestion mappings must apply sign normalization before canonical storage. The same generic metric, such as `active_power`, can represent different roles without domain-specific duplicate metric names. Documentation and tests must make the convention explicit for each vendor mapping. ### Alternatives Considered Adopting vendor-native signs was rejected because signs would vary within one platform. Making all export positive was rejected because load and battery operational views become less intuitive. Using separate metric names for charge and discharge power was rejected for instantaneous power because it fragments a single physical quantity. ## ADR-012: Telemetry-Only v1.1 Scope **Status:** Accepted **Date:** July 2026 **Affected Documents:** OCETS, Plant Registry Specification ### Context Energy platforms often evolve from monitoring into control, dispatch, and optimization. Those domains introduce safety, authorization, audit, failure-mode, and write-side semantics that are materially different from telemetry semantics. Including control in v1.1 would slow down the telemetry model and risk underspecified write behavior. ### Decision OCETS v1.1 is telemetry-only. Control commands, setpoints, dispatch semantics, actuator writes, and optimization requests are outside the normative v1.1 scope. ### Consequences The v1.1 model can focus on stable telemetry semantics. Control-capable devices can still be represented as Assets and Devices, but their write-side behavior is not standardized by v1.1. Future control work can define separate safety and authorization requirements. ### Alternatives Considered Including minimal setpoint support was rejected because even simple writes require policy and safety semantics. Ignoring control-capable equipment entirely was rejected because such equipment still emits telemetry. ## ADR-013: Forecast Generation Deferral **Status:** Accepted **Date:** July 2026 **Affected Documents:** OCETS, Canonical Metric Catalogue ### Context Forecasts have different semantics from observed telemetry. They require issue time, validity time, horizon, model identity, confidence, and revision behavior. Mixing forecasts into the v1.1 telemetry catalogue without those semantics would create ambiguity. ### Decision Forecast-generation models are deferred from OCETS v1.1. Externally generated forecast Observations may use canonical Metrics with `origin=forecast` only when they carry explicit issue and validity times. ### Consequences The catalogue remains focused while consumers can distinguish forecast values from measurements. Model training, confidence, revisions, and generation remain outside OCETS conformance. ### Alternatives Considered Adding simple forecast metric names was rejected because it would not define enough context to compare or revise forecasts. Treating forecasts as ordinary gauges was rejected because forecast validity time is not acquisition time. ## ADR-014: Legacy Clean Break **Status:** Accepted **Date:** July 2026 **Affected Documents:** All OCETS documents ### Context Existing deployments may contain legacy names, vendor-derived field names, or locally meaningful labels. Preserving those names as normative compatibility requirements would permanently couple OCETS to historical implementation details. Migration still matters, but it should not define the standard. ### Decision OCETS v1.1 makes a clean break from legacy and vendor-specific naming. Legacy migration may be documented separately in implementation notes or migration guides. It is not part of the normative compatibility model. ### Consequences The standard can optimize for long-term clarity rather than short-term name preservation. Implementations must provide mapping and migration logic where existing deployments need continuity. Conformance is evaluated against canonical output, not historical source names. ### Alternatives Considered Preserving legacy names as aliases was rejected because aliases tend to become permanent compatibility burdens. Omitting migration guidance entirely was rejected because deployments still need practical transition paths. ## ADR-015: Edge Collector Observability Boundary **Status:** Accepted **Date:** July 2026 **Affected Documents:** OCETS, Canonical Metric Catalogue, Plant Registry Specification, Reference Implementation Guide ### Context Plant-local collectors can remain reachable while silently losing data through clock drift, full storage, exhausted buffers, failed mapping, or upstream transport failure. Collector status alone does not establish that telemetry is current, correct, or recoverable. Conversely, standardizing every operating-system metric would turn OCETS into a general infrastructure-monitoring standard. ### Decision OCETS defines an optional Edge Collector Observability Profile. The canonical baseline covers availability, collector and pipeline state, acquisition freshness, clock synchronization, buffering, telemetry storage, transport errors, restarts, mapping, and validation. Portable CPU, memory, temperature, external-power, and backup-power signals are optional. Hardware-specific sensors, kernel diagnostics, interface and filesystem names, certificate details, authentication logs, and configuration-integrity mechanisms remain implementation monitoring. They may support canonical state derivation but do not define canonical identity. ### Consequences Operators can distinguish a healthy measured zero from a collector, clock, storage, buffering, or delivery failure. Central-only implementations remain conformant without claiming the profile. Edge implementations can expose additional diagnostics without making consumers depend on Ubuntu, Raspberry Pi, Telegraf, or another implementation choice. ### Alternatives Considered Making host monitoring mandatory for every deployment was rejected because central-only topologies do not have an edge host. Guidance without a claimable profile was rejected because it cannot be tested consistently. Canonicalizing all operating-system metrics was rejected because those metrics are platform-specific and extend beyond energy telemetry continuity. ## ADR-016: Observation Quality and Provenance **Status:** Accepted **Date:** July 2026 **Affected Documents:** OCETS, Canonical Metric Catalogue, Reference Implementation Guide ### Context A value and timestamp cannot distinguish direct acquisition from estimation, substitution, simulation, manual correction, or an invalid sample. ### Decision OCETS defines Observation as the logical telemetry record and makes quality and provenance mandatory, orthogonal properties. Storage may split the logical record if every property remains reconstructable. ### Consequences Consumers can apply explicit trust policy. Ingestion and downsampling must preserve metadata without creating unbounded label cardinality. ### Alternatives Considered Inferring quality from missing samples and encoding origin in metric names were rejected because both lose information and fragment canonical identity. ## ADR-017: Events Are Separate from Metrics **Status:** Accepted **Date:** July 2026 **Affected Documents:** OCETS, Plant Registry Specification ### Context Alarms, faults, maintenance, restarts, and acknowledgements have identity, interval, correlation, and lifecycle semantics that ordinary samples do not have. ### Decision OCETS defines a canonical Event envelope and event-type vocabulary separate from Metrics and Observations. ### Consequences Implementations need a durable event representation with idempotent updates and audit history. Time-series values remain free of event lifecycle ambiguity. ### Alternatives Considered Boolean alarm Metrics and free-form logs were rejected because they cannot preserve acknowledgement, correlation, or interval history consistently. ## ADR-018: Versioned Relationship Graphs **Status:** Accepted **Date:** July 2026 **Affected Documents:** OCETS, Plant Registry Specification ### Context The ownership hierarchy cannot represent electrical flow, connectivity, measurement, containment, control responsibility, and operational power dependencies over time. ### Decision OCETS models stable typed Relationships inside immutable, versioned physical, electrical, or telemetry Topologies. Graph endpoints are existing registered objects. ### Consequences Topology remains historically interpretable and independent of diagrams. Validation must enforce endpoint type, tenant boundary, validity, symmetry, and containment-cycle rules. ### Alternatives Considered Embedding anonymous graph nodes and deriving topology from names were rejected because neither provides stable identity or governed history. ## ADR-019: Organization as Tenant Boundary **Status:** Accepted **Date:** July 2026 **Affected Documents:** OCETS, Plant Registry Specification ### Context Portfolios and Plants need ownership, authorization, residency, and governance boundaries at platform scale. ### Decision Organization is the tenant boundary. Portfolios group Plants within one Organization; globally unique Plant identity remains unchanged. ### Consequences Cross-tenant Registry relationships are invalid. Consumers can group Plants flexibly without coupling series identity to a portfolio name. ### Alternatives Considered Using Portfolio as ownership and embedding tenant names in Plant IDs were rejected because portfolios change and a Plant may belong to several groupings. ## ADR-020: Read-Only Registry API Profile **Status:** Accepted **Date:** July 2026 **Affected Documents:** OCETS, Plant Registry Specification ### Context File-only Registry access does not scale to many clients, large registries, caching, incremental synchronization, or tenant-scoped discovery. ### Decision OCETS defines an authenticated HTTP/JSON read profile with immutable revisions, snapshots, changes, cursor pagination, filtering, ETags, and stable errors. Mutation workflows remain implementation-specific. ### Consequences Clients can interoperate without making a particular database or approval system normative. ### Alternatives Considered A mandatory GraphQL service and a complete write API were rejected because they constrain implementation and governance unnecessarily. ## ADR-021: Normative Security Baseline **Status:** Accepted **Date:** July 2026 **Affected Documents:** All OCETS documents ### Context Stable identities and multi-tenant APIs are unsafe without authentication, authorization, secret handling, encryption, rotation, and audit requirements. ### Decision OCETS makes security controls normative while remaining independent of a specific identity provider, certificate authority, VPN, or secret store. ### Consequences Conformance requires default-deny tenant isolation, protected transport, distinct workload and human identities, rotation, least privilege, and auditable sensitive actions. ### Alternatives Considered Treating network location as trust and leaving security entirely to deployments were rejected because they prevent meaningful interoperable conformance. ## ADR-022: Immutable Versioned Metric Definitions **Status:** Accepted **Date:** July 2026 **Affected Documents:** OCETS, Canonical Metric Catalogue, Registry API ### Context Lifecycle status alone does not reveal when a Metric entered, changed status, or received a replacement, which makes historical interpretation and client migration unreliable. ### Decision Metric definitions are immutable and carry definition, introduction, deprecation, removal, and replacement version metadata. Incompatible meaning changes still require a new name or OCETS major version. ### Consequences Catalogue releases remain reproducible and API clients can plan migrations explicitly. ### Alternatives Considered Editing published definitions in place was rejected because historical telemetry would silently change meaning. --- # SOURCE: docs/02_Reference_Implementation_Guide_v1.1.md --- title: "OCETS Reference Implementation Guide" version: "1.1" status: "Architecture Review Candidate" release: "July 2026" identifier: "OCETS-GUIDE-1.1" --- # OCETS Reference Implementation Guide **Document:** 2 of 5 **Type:** Informative Implementation Guide **Version:** 1.1 **Status:** Architecture Review Candidate **Compatibility:** OCETS 1.1 ## 1. Purpose This guide describes one practical implementation of the Open Canonical Energy Telemetry Standard using common open infrastructure components. The normative standard defines the model. This guide shows how a deployment can implement that model using concrete tools. It may change more frequently than the standard as tools, devices, and operational practices evolve. ## 2. Scope This guide covers: - Telegraf; - MQTT; - VictoriaMetrics; - Grafana; - Modbus; - Huawei devices; - Janitza devices; - templates; - deployment; - transformation scripts; - operational validation. Current or legacy implementation names are examples only. They are not OCETS compatibility exceptions and do not create alternative canonical names. ## 3. Reference Architecture The reference implementation uses Registry-generated configuration and keeps Observations and Events logically distinct: ```text Organization / Portfolio / Plant Registry -> Generator | Field Device -> Modbus / Vendor Protocol -> Edge Telegraf -> MQTT -> Collector Telegraf -> VictoriaMetrics -> Grafana / API Consumers | | +-> Event channel +-> Quality and provenance metadata ``` The implementation must preserve the canonical semantics defined by OCETS. Tool-specific names, register addresses, field aliases, hostnames, and transport topics are implementation details. ## 4. Canonical Storage Shape In time-series storage, the measurement or series name should be the canonical metric name, for example `active_power`, `voltage`, or `state_of_charge`. Recommended canonical labels: - `plant`; - `asset`; - `device`; - `measurement_point`; - `role`; - `energy_form`; - `phase`, when applicable; - `direction`, when applicable; - `string`, when applicable; - `mppt`, when applicable; - `status`, for state telemetry where applicable. Do not add a redundant label that repeats the metric name. Vendor, model, collector, source address, and protocol metadata may be retained as implementation labels, but canonical dashboards and alerts should not depend on them for semantic meaning. Every stored value must also be resolvable to acquisition time, quality, provenance, and the Metric Catalogue version. Implementations may use fields, a companion metadata series, or an observation store; high-cardinality calculation, actor, model, or source references should not become TSDB labels. Events should use a separate durable event stream or event store keyed by `event_id`. Re-delivery should upsert lifecycle state idempotently while preserving acknowledgement and transition history. Example logical Observation: ```json { "metric": "active_power", "catalogue_version": "1.1", "value": 42.5, "plant": "plant-example", "measurement_point": "mp-grid", "acquired_at": "2026-07-13T10:00:00Z", "quality": "GOOD", "provenance": {"origin": "device", "source_id": "meter-01"} } ``` Example correlated Event after acknowledgement: ```json { "event_id": "evt-01JZ8M8K7P", "event_type": "grid_failure", "severity": "critical", "source": {"kind": "measurement_point", "id": "mp-grid"}, "begin_at": "2026-07-13T10:01:00Z", "state": "acknowledged", "correlation_id": "incident-4711", "quality": "GOOD", "provenance": {"origin": "device", "source_id": "meter-01"}, "acknowledgement": {"actor": "operator-17", "at": "2026-07-13T10:02:00Z"} } ``` ## 5. Telegraf Layout The recommended Telegraf layout separates stable infrastructure from generated device inputs. ### 5.1 Edge Layout ```text /etc/telegraf/ telegraf.conf telegraf.d/ 10-meter-grid.conf 20-inverters.conf 30-battery.conf ``` The main `telegraf.conf` should contain agent settings and outputs. Device inputs should be placed in generated or templated files under `telegraf.d/`. ### 5.2 Collector Layout ```text /etc/telegraf/ telegraf.conf telegraf.d/ 10-mqtt-telemetry.conf 20-mqtt-health.conf ``` Unrelated consumers should remain in separate files with narrow topic subscriptions and clear parsing rules. ## 6. MQTT Transport MQTT is used as the reference transport between edge collectors and central collectors. Recommended topic pattern: ```text telemetry/{plant}/{device}/{canonical_metric} ``` Payloads may use Influx line protocol when Telegraf is used on both sides. The MQTT topic is not canonical identity. Canonical identity is carried by the metric name and registry-derived labels. ## 7. VictoriaMetrics Storage VictoriaMetrics is the reference time-series storage backend. The storage backend should receive values after: - unit conversion; - canonical metric naming; - sign normalization; - label normalization; - enum normalization; - validation. The storage backend should not be used to repair unit inconsistencies or canonical naming errors. Those belong in ingestion and mapping. ## 8. Grafana Dashboards Grafana dashboards should be generated or parameterized from registry data. Dashboards should query canonical metric names rather than vendor-specific field names. Recommended dashboard variables: - plant; - asset; - device; - measurement point; - role; - energy form; - phase; - direction. ## 9. Mapping Vendor Fields to Canonical Metrics Vendor mappings should be explicit, reviewed, and tested with captured source data. Each mapping should define: - source field or register; - source unit and scale factor; - canonical metric name; - canonical unit; - target labels; - role and Measurement Point; - sign conversion rule; - value type; - enum mapping, if applicable. Example mapping table: | Source Field | Source Unit | Canonical Metric | Canonical Unit | Labels | Mapping Notes | |---|---:|---|---:|---|---| | `grid_p` | W | `active_power` | kW | `role=grid`, `measurement_point=grid_connection` | Divide by 1000; positive import, negative export. | | `load_p` | W | `active_power` | kW | `role=load`, `measurement_point=site_load` | Divide by 1000; positive consumption. | | `pv1_u` | V | `voltage` | V | `role=pv`, `measurement_point=pv_string_1`, `string=1` | Preserve value. | | `pv1_i` | A | `current` | A | `role=pv`, `measurement_point=pv_string_1`, `string=1` | Preserve value. | | `battery_soc` | % | `state_of_charge` | percent | `role=battery`, `measurement_point=battery_dc_bus` | Normalize percent range to 0..100. | | `battery_p` | W | `active_power` | kW | `role=battery`, `measurement_point=battery_dc_bus` | Divide by 1000; positive charging, negative discharging. | Avoid creating domain-specific electrical metric names when `active_power`, `voltage`, `current`, or another generic metric plus labels describes the measurement correctly. ## 10. Modbus Integration Modbus register maps are implementation-specific and vendor-specific. The reference implementation should map registers to canonical metrics during ingestion. Slave IDs and gateway addresses should not become canonical identity. ## 11. Huawei Integration Huawei register maps belong in this guide or implementation-specific appendices. Huawei source fields should be mapped into canonical metric names and canonical units before storage. PV string and MPPT values should use `string` and `mppt` labels for subcomponents instead of multiplying metric names where possible. ## 12. Janitza Integration Janitza meter values should be mapped into canonical electrical metrics for grid, load, or other Measurement Points. Three-phase values should use the controlled `phase` values `l1`, `l2`, `l3`, and `total`. ## 13. Templates Configuration should be generated from the Plant Registry. Templates should produce: - Telegraf input files; - MQTT output configuration; - collector subscriptions; - VictoriaMetrics label rules; - Grafana dashboard variables; - alert labels; - deployment inventory. Humans should edit registry source data and templates, not repeated generated output. ## 14. Example Configuration Skeleton ```toml [agent] omit_hostname = true [[outputs.mqtt]] servers = ["tcp://broker.example:1883"] topic = 'telemetry/{{ .Tag "plant" }}/{{ .Tag "device" }}/{{ .Name }}' data_format = "influx" ``` This skeleton is illustrative. Production configuration must include credentials, TLS, buffering, retry behavior, and operational monitoring. ## 15. Transformation Processing Transformation processors may be used to convert vendor-specific or flat field structures into canonical metric and label structures. Example use cases: - pivoting repeated fields into `string` or `mppt` labels; - normalizing enum values; - applying role-based power signs; - splitting mixed measurements; - adding registry-derived labels; - dropping fields that cannot be mapped safely. Transformation logic should be tested with captured input before deployment. ## 16. Deployment The reference deployment should define: - edge host provisioning; - collector provisioning; - secrets management; - service units; - configuration generation; - validation commands; - rollback procedures; - monitoring checks. ## 17. Validation Ritual After each configuration change: ```bash telegraf --config /etc/telegraf/telegraf.conf \ --config-directory /etc/telegraf/telegraf.d --test grep -rnE '^\[\[(inputs|outputs)\.' \ /etc/telegraf/telegraf.conf /etc/telegraf/telegraf.d/ systemctl reload telegraf || systemctl restart telegraf systemctl is-active telegraf ``` The test command must include the configuration directory. ## 18. Best Practices - Keep `host` out of canonical identity. - Keep credentials out of generated files where possible. - Use stable logical device IDs. - Keep labels low-cardinality and controlled. - Generate repeated configuration from templates. - Monitor freshness and communication status. - Treat missing data differently from measured zero. - Validate generated configuration before reload. - Document legacy-to-canonical migration separately from OCETS conformance. ## 19. Edge Collector Observability Profile ### 19.1 Collection Boundary Use one stable registry Device for the logical edge collector. Emit profile metrics with `plant`, `device`, and `role=collector`. Keep hostname, IP address, network interface, filesystem path, Linux device name, and hardware serial number as implementation labels outside canonical identity. Application-native instrumentation should provide collector, pipeline, freshness, buffer, mapping, validation, transport, and restart metrics. Operating-system collectors cannot reliably infer these application states. ### 19.2 Ubuntu and Raspberry Pi CM5 On Ubuntu, Telegraf inputs may collect CPU, memory, filesystem, disk I/O, network, processes, and selected systemd unit states. Limit collection to filesystems, interfaces, and services that affect telemetry acquisition or forwarding. CM5-specific collectors may read: - SoC and component temperatures from available Linux thermal zones; - throttling or undervoltage flags exposed by the installed firmware and kernel tooling; - fan speed where the carrier provides tachometer data; - eMMC, NVMe, or SD health using tooling appropriate to the installed storage; - RTC, external-power, and backup-power state where the carrier or UPS exposes them. Linux thermal readings are operational indicators, not calibrated environmental measurements. Hardware-specific values should derive canonical `host_temperature`, `storage_status`, or power metrics only when their meaning is known. Raw sensor and kernel values may remain in the infrastructure-monitoring namespace. Use the active Ubuntu time service as the source for `time_sync_status` and `timestamp_skew`. Current Ubuntu releases may use Chrony, while older or upgraded installations may use `systemd-timesyncd`. Detect the active service and do not run competing synchronization daemons. ### 19.3 Continuity Monitoring Infrastructure monitoring should additionally alert on: - out-of-memory events, sustained swapping, and unexpected reboots; - read-only filesystems, I/O errors, inode exhaustion, and storage wear indicators; - carrier loss, packet errors, upstream reachability, and persistent delivery retries; - failed telemetry-related systemd units and unexpected collector restarts; - certificate or credential expiry, authentication failures, and unexpected configuration changes. These signals may explain canonical health state but are not themselves required OCETS series unless listed in the Canonical Metric Catalogue. ### 19.4 Initial Alert Policy Deployments should tune alerts from observed baselines. The following are starting values: | Condition | Warning | Critical | |---|---:|---:| | Data freshness | greater than 2 times expected sample interval | greater than 3 times expected sample interval | | Buffer utilization | 70 percent | 90 percent | | Storage utilization | 75 percent | 90 percent | | Timestamp skew | 1 s | 5 s | | CPU utilization | 80 percent for 15 min | 95 percent for 15 min | | Available memory | less than 15 percent | less than 5 percent | | CM5 host temperature | 75 degC | 82 degC | Any known `failed`, `disconnected`, or `unsynchronized` state should alert immediately. Sustained increases in mapping, validation, transport, authentication, disk, or network errors should alert even when utilization remains below a threshold. Buffer age should alert when it exceeds the deployment's recovery or delivery objective. ## 20. Topology and Registry API Generate topology views from versioned Registry Relationships. Do not maintain independent dashboard-only connection maps. Cache Registry API resources by `ETag` and persist the source `registry_revision` with generated configuration so an operator can reproduce the deployed state. Large clients should consume `/snapshot` for bootstrap and `/changes` for incremental refresh. They should complete cursor pagination against one revision and restart traversal if that revision is no longer retained. ## 21. Security Baseline Use separate credentials for field Devices, edge collectors, central collectors, Registry API clients, and human operators. Prefer short-lived service credentials or rotatable certificates, encrypted transport, tenant-scoped authorization, and a managed secret store. Registry YAML and generated configuration should reference secret identifiers rather than contain secret values. Record Registry revisions, manual corrections, Event acknowledgements, access-policy changes, and credential rotations in an audit system. A network VPN may reduce exposure but does not replace authentication or authorization. --- # SOURCE: implementation/registry/schema/plant-registry-v1.1.schema.json { "$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://ocets.5ya.de/schema/plant-registry-v1.1.json", "title": "OCETS Plant Registry", "type": "object", "required": [ "version", "registry_id", "revision", "organizations", "portfolios", "plants", "assets", "devices", "measurement_points", "topologies", "relationships" ], "additionalProperties": false, "properties": { "version": { "const": "1.1" }, "registry_id": { "$ref": "#/$defs/id" }, "revision": { "type": "string", "format": "date-time" }, "organizations": { "type": "array", "items": { "$ref": "#/$defs/organization" } }, "portfolios": { "type": "array", "items": { "$ref": "#/$defs/portfolio" } }, "plants": { "type": "array", "items": { "$ref": "#/$defs/plant" } }, "assets": { "type": "array", "items": { "$ref": "#/$defs/asset" } }, "devices": { "type": "array", "items": { "$ref": "#/$defs/device" } }, "measurement_points": { "type": "array", "items": { "$ref": "#/$defs/measurement_point" } }, "topologies": { "type": "array", "items": { "$ref": "#/$defs/topology" } }, "relationships": { "type": "array", "items": { "$ref": "#/$defs/relationship" } } }, "$defs": { "id": { "type": "string", "minLength": 1, "pattern": "^[a-z0-9][a-z0-9._-]*$" }, "status": { "enum": ["planned", "active", "maintenance", "disabled", "retired"] }, "role": { "enum": ["grid", "load", "pv", "battery", "inverter", "meter", "transformer", "busbar", "collector", "environment"] }, "energy_form": { "enum": ["electricity_ac", "electricity_dc", "thermal", "environmental", "operational"] }, "phase": { "enum": ["l1", "l2", "l3", "n", "total"] }, "direction": { "enum": ["import", "export", "charge", "discharge", "generation", "consumption", "bidirectional"] }, "organization": { "type": "object", "required": ["id", "name", "status"], "additionalProperties": false, "properties": { "id": { "$ref": "#/$defs/id" }, "name": { "type": "string", "minLength": 1 }, "status": { "$ref": "#/$defs/status" }, "data_residency_region": { "type": "string", "minLength": 1 }, "tags": { "type": "array", "items": { "type": "string", "minLength": 1 }, "uniqueItems": true } } }, "portfolio": { "type": "object", "required": ["id", "organization_id", "name", "status"], "additionalProperties": false, "properties": { "id": { "$ref": "#/$defs/id" }, "organization_id": { "$ref": "#/$defs/id" }, "name": { "type": "string", "minLength": 1 }, "status": { "$ref": "#/$defs/status" }, "tags": { "type": "array", "items": { "type": "string", "minLength": 1 }, "uniqueItems": true } } }, "plant": { "type": "object", "required": ["id", "organization_id", "name", "timezone", "status"], "additionalProperties": false, "properties": { "id": { "$ref": "#/$defs/id" }, "organization_id": { "$ref": "#/$defs/id" }, "portfolio_ids": { "type": "array", "items": { "$ref": "#/$defs/id" }, "uniqueItems": true }, "name": { "type": "string", "minLength": 1 }, "timezone": { "type": "string", "minLength": 1 }, "status": { "$ref": "#/$defs/status" }, "country": { "type": "string", "pattern": "^[A-Z]{2}$" }, "operator": { "type": "string", "minLength": 1 }, "commissioned_at": { "type": "string", "format": "date-time" }, "data_residency_region": { "type": "string", "minLength": 1 }, "tags": { "type": "array", "items": { "type": "string", "minLength": 1 }, "uniqueItems": true } } }, "asset": { "type": "object", "required": ["id", "plant_id", "type", "name", "status"], "additionalProperties": false, "properties": { "id": { "$ref": "#/$defs/id" }, "plant_id": { "$ref": "#/$defs/id" }, "type": { "type": "string", "minLength": 1 }, "name": { "type": "string", "minLength": 1 }, "status": { "$ref": "#/$defs/status" }, "vendor": { "type": "string" }, "model": { "type": "string" }, "serial_number": { "type": "string" }, "location": { "type": "string" }, "commissioned_at": { "type": "string", "format": "date-time" } } }, "device": { "type": "object", "required": ["id", "plant_id", "asset_id", "role", "energy_form", "status"], "additionalProperties": false, "properties": { "id": { "$ref": "#/$defs/id" }, "plant_id": { "$ref": "#/$defs/id" }, "asset_id": { "$ref": "#/$defs/id" }, "role": { "$ref": "#/$defs/role" }, "energy_form": { "$ref": "#/$defs/energy_form" }, "status": { "$ref": "#/$defs/status" }, "vendor": { "type": "string" }, "model": { "type": "string" }, "protocols": { "type": "array", "items": { "type": "string", "minLength": 1 }, "uniqueItems": true }, "communication": { "type": "object" }, "capabilities": { "type": "array", "items": { "type": "string", "minLength": 1 }, "uniqueItems": true }, "profiles": { "type": "array", "items": { "enum": ["edge_collector_observability"] }, "uniqueItems": true } } }, "measurement_point": { "type": "object", "required": ["id", "plant_id", "device_id", "type", "name"], "additionalProperties": false, "properties": { "id": { "$ref": "#/$defs/id" }, "plant_id": { "$ref": "#/$defs/id" }, "device_id": { "$ref": "#/$defs/id" }, "type": { "type": "string", "minLength": 1 }, "name": { "type": "string", "minLength": 1 }, "role": { "$ref": "#/$defs/role" }, "energy_form": { "$ref": "#/$defs/energy_form" }, "phase": { "$ref": "#/$defs/phase" }, "direction": { "$ref": "#/$defs/direction" }, "string": { "type": "string" }, "mppt": { "type": "string" }, "nominal_voltage": { "type": "number" }, "parent_measurement_point_id": { "$ref": "#/$defs/id" } } }, "topology": { "type": "object", "required": ["id", "plant_id", "kind", "version", "name", "status", "valid_from"], "additionalProperties": false, "properties": { "id": { "$ref": "#/$defs/id" }, "plant_id": { "$ref": "#/$defs/id" }, "kind": { "enum": ["electrical", "physical", "telemetry"] }, "version": { "type": "integer", "minimum": 1 }, "name": { "type": "string", "minLength": 1 }, "status": { "$ref": "#/$defs/status" }, "valid_from": { "type": "string", "format": "date-time" }, "valid_to": { "type": "string", "format": "date-time" } } }, "endpoint": { "type": "object", "required": ["kind", "id"], "additionalProperties": false, "properties": { "kind": { "enum": ["plant", "asset", "device", "measurement_point"] }, "id": { "$ref": "#/$defs/id" } } }, "relationship": { "type": "object", "required": ["id", "plant_id", "topology_id", "topology_version", "type", "from", "to", "status", "valid_from"], "additionalProperties": false, "properties": { "id": { "$ref": "#/$defs/id" }, "plant_id": { "$ref": "#/$defs/id" }, "topology_id": { "$ref": "#/$defs/id" }, "topology_version": { "type": "integer", "minimum": 1 }, "type": { "enum": ["contains", "feeds", "connected_to", "measures", "controls", "powered_by"] }, "from": { "$ref": "#/$defs/endpoint" }, "to": { "$ref": "#/$defs/endpoint" }, "status": { "$ref": "#/$defs/status" }, "valid_from": { "type": "string", "format": "date-time" }, "valid_to": { "type": "string", "format": "date-time" } } } } } --- # SOURCE: dist/ocets-v1.1/examples/solar-plant-example.yaml # OCETS v1.1 Plant Registry — plant "solar-example" # Authoritative source of truth (OCETS-REGISTRY-1.1). # Edge-acquisition topology: Raspberry Pi edge collector, no field devices yet. # Validate with: scripts/validate_registry.py version: "1.1" registry_id: "example-registry" revision: "2026-07-13T10:00:00Z" organizations: - id: "example-energy" name: "Example Energy" status: "active" data_residency_region: "DE" portfolios: - id: "germany" organization_id: "example-energy" name: "German Plants" status: "active" plants: - id: "solar-example" organization_id: "example-energy" portfolio_ids: - "germany" name: "Example Solar Plant" timezone: "Europe/Berlin" status: "active" country: "DE" operator: "Example Energy" assets: - id: "plant-operations" plant_id: "solar-example" type: "telemetry_infrastructure" name: "Plant Telemetry Infrastructure" status: "active" location: "Example site cabinet" devices: # Logical edge collector. ID is stable and NOT derived from hostname, # IP, or hardware serial (OCETS-REGISTRY-1.1 §9). The physical Pi can be # replaced without changing this identity. - id: "edge-collector-01" plant_id: "solar-example" asset_id: "plant-operations" role: "collector" energy_form: "operational" status: "active" profiles: - "edge_collector_observability" capabilities: # Required by the Edge Collector Observability Profile (OCETS-CORE-1.1 §15.1) - "device_available" - "collector_status" - "pipeline_status" - "communication_status" - "data_freshness" - "time_sync_status" - "timestamp_skew" - "buffer_utilization" - "buffer_oldest_age" - "storage_utilization" - "storage_status" - "transport_error_count" - "collector_restart_count" - "mapping_error_count" - "validation_error_count" # Optional host metrics this deployment can supply - "cpu_utilization" - "memory_utilization" - "host_temperature" measurement_points: # Storage required by the telemetry pipeline (SD card root filesystem). # The mount path stays an implementation detail; this ID is the identity. - id: "mp-collector-storage" plant_id: "solar-example" device_id: "edge-collector-01" type: "collector_storage" name: "Edge Collector Pipeline Storage" role: "collector" energy_form: "operational" # SoC thermal zone of the edge host. Operational indicator, not an # environmental measurement (OCETS-GUIDE-1.1 §19.2). - id: "mp-collector-soc" plant_id: "solar-example" device_id: "edge-collector-01" type: "collector_host_thermal" name: "Edge Collector SoC Temperature" role: "collector" energy_form: "operational" topologies: - id: "telemetry-infrastructure" plant_id: "solar-example" kind: "telemetry" version: 1 name: "Plant Telemetry Infrastructure" status: "active" valid_from: "2026-07-13T10:00:00Z" relationships: - id: "rel-plant-collector" plant_id: "solar-example" topology_id: "telemetry-infrastructure" topology_version: 1 type: "contains" from: {kind: "plant", id: "solar-example"} to: {kind: "device", id: "edge-collector-01"} status: "active" valid_from: "2026-07-13T10:00:00Z" - id: "rel-collector-storage" plant_id: "solar-example" topology_id: "telemetry-infrastructure" topology_version: 1 type: "contains" from: {kind: "device", id: "edge-collector-01"} to: {kind: "measurement_point", id: "mp-collector-storage"} status: "active" valid_from: "2026-07-13T10:00:00Z" - id: "rel-collector-soc" plant_id: "solar-example" topology_id: "telemetry-infrastructure" topology_version: 1 type: "contains" from: {kind: "device", id: "edge-collector-01"} to: {kind: "measurement_point", id: "mp-collector-soc"} status: "active" valid_from: "2026-07-13T10:00:00Z"