OCETS Reference Implementation Guide

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:

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:

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:

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:

{
  "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:

{
  "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

/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

/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:

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:

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:

9. Mapping Vendor Fields to Canonical Metrics

Vendor mappings should be explicit, reviewed, and tested with captured source data.

Each mapping should define:

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:

Humans should edit registry source data and templates, not repeated generated output.

14. Example Configuration Skeleton

[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:

Transformation logic should be tested with captured input before deployment.

16. Deployment

The reference deployment should define:

17. Validation Ritual

After each configuration change:

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

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:

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:

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.