Datasources
A datasource is a named measurement point. Every piece of telemetry your plugin publishes is recorded against a datasource, and every widget or automation condition that reads live or historical data references one.
How datasources work
Datasources live in a central registry keyed by a unique dotted-path string (e.g. tapo.plug.current_power). The registry is the single source of truth for what data the system knows about — widgets, automations, and the telemetry storage layer all reference datasources by this key or by the UUID assigned at registration.
When a datasource is deleted — for example when its plugin is uninstalled — all associated telemetry, rollup data, and event records are automatically removed via cascade. Datasources are preserved across plugin updates because the plugin row is updated in place, keeping its ID and all downstream references intact.
Datasource types
The type field controls how Hiclaro stores and routes the data.number datasources write to the telemetry table (float, with hourly rollups).string and boolean datasources write to the event telemetry table (varchar, deduplicated, no rollup).
| Type | Description |
|---|---|
number | A numeric value. Hiclaro stores every sample and computes hourly rollups (avg / min / max) for efficient long-range queries. Use this for anything you want to chart historically — temperature, power draw, state of charge, remaining capacity. |
string | A text value representing a mode or status — for example a mode selector (eco / comfort / boost) or a status string (charging / idle). Consecutive identical values are deduplicated; only transitions are stored. |
boolean | A true/false toggle — on/off, active/inactive, is_charging. Stored as the strings "true" or "false". Like string, consecutive duplicates are deduplicated. |
Key naming conventions
Datasource keys use a dotted-path format: plugin_key.category.metric. The plugin key prefix namespaces your datasources and prevents collisions with other plugins.
Keep keys stable across plugin versions. Changing a key in an update orphans any widgets or automations that referenced the old key, and leaves stale datasource rows behind.
Choosing a registration approach
There are two ways to register datasources — the plugin.json manifest and the runtime MQTT topic. They serve different use cases and are not meant to be combined. Pick one approach per datasource; using both for the same key is redundant and can cause unexpected double-upserts on startup.
| Approach | When to use | Example |
|---|---|---|
plugin.json manifest | Datasource keys are fixed and known at build time — the plugin always exposes the same set of measurements regardless of what devices are connected. | A Tapo plug plugin that always exposes |
| Runtime MQTT | Datasource keys are only known after the service starts and discovers entities — the set varies per installation. | A Home Assistant bridge that registers one datasource per HA entity as they are discovered over the WebSocket API. |
If your plugin targets a fixed set of devices with a predictable schema, use the manifest — it is simpler and the datasources are registered at install time before your service even starts. Use runtime MQTT only when the datasource set is genuinely dynamic.
Registration: manifest (static)
The simplest way to register datasources is to declare them in plugin.json. Hiclaro upserts them by key at install time and on every reinstall. Use this approach when the full set of datasources your plugin will ever publish is known at build time.
See the Plugin Manifest reference for the full field list.
Registration: runtime MQTT (dynamic)
Some plugins integrate platforms — like Home Assistant or Zigbee — where the set of entities is not known until the service connects and discovers them at runtime. For these cases, publish to eims/registry/datasource/register to register datasources on demand.
The API upserts each entry by key, so re-publishing the same registration on reconnect is safe and has no side effects. The registration message also links each datasource to the publishing plugin, so they are cleaned up automatically if the plugin is uninstalled.
Batching and throttling
When a plugin first connects it may discover many entities in a short burst. Rather than sending one MQTT message per entity, buffer new registrations and flush them in batches every few seconds — or immediately when the buffer reaches a fixed size. This keeps MQTT traffic low during startup and avoids hammering the API.
Maintain an in-memory set of already-registered keys so you skip the registration step for subsequent telemetry events from the same entity. Clear the set on reconnect so datasources are re-registered after a restart.
Publishing telemetry
Once a datasource is registered, publish measurements to eims/telemetry. Always use the value field — pass a number for number datasources, or a string for string and boolean datasources.
Omit deviceAddress for global datasources that are not scoped to a specific device — for example aggregated battery totals or cloud-fetched readings. Telemetry published before a datasource is registered is silently dropped, so always register first.
The meta field
The optional meta object carries supplementary information that widgets can use for rendering. Currently recognised keys:
| Key | Type | Description |
|---|---|---|
min | number | Minimum expected value. Used by gauge and radial bar widgets to set the scale floor. |
max | number | Maximum expected value. Used by gauge and radial bar widgets to set the scale ceiling. |