Document: 2 of 5
Type: Informative Implementation Guide
Version: 1.1
Status: Architecture Review Candidate
Compatibility: OCETS 1.1
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.
This guide covers:
Current or legacy implementation names are examples only. They are not OCETS compatibility exceptions and do not create alternative canonical names.
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.
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:
{
"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"}
}The recommended Telegraf layout separates stable infrastructure from generated device inputs.
/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/.
/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.
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.
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.
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:
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.
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.
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.
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.
Configuration should be generated from the Plant Registry.
Templates should produce:
Humans should edit registry source data and templates, not repeated generated output.
[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.
Transformation processors may be used to convert vendor-specific or flat field structures into canonical metric and label structures.
Example use cases:
string or
mppt labels;Transformation logic should be tested with captured input before deployment.
The reference deployment should define:
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 telegrafThe test command must include the configuration directory.
host out of canonical identity.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.
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.
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.
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.
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.
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.