Overview

Plugins

Widgets

Reference

Publishing

MQTT Reference

All plugin services communicate with the Hiclaro API over MQTT using a standardised topic and payload contract.

Connection

Plugin services run as subprocesses of the Hiclaro service host. The service host injects MQTT_HOST and MQTT_PORT into every plugin subprocess environment — read them instead of hardcoding localhost so your plugin works across deployment topologies:

import os

mqtt_host = os.getenv("MQTT_HOST", "localhost")
mqtt_port = int(os.getenv("MQTT_PORT", "1883"))

client.connect(mqtt_host, mqtt_port)

On the standard Raspberry Pi deployment both values default to localhost:1883. No authentication is required.

eims/telemetry

Publish live device values to this topic. Entries are batched in a single message — publish one entry or many in the same payload. Each entry must include a value field; entries without one are silently dropped.

FieldTypeRequiredDescription
deviceAddress

string

No

MAC address or IP of the originating device. Marks the device online and serves as the default address for all entries that omit their own. Omit for global datasources not scoped to a specific device.

entries

array

Yes

Array of telemetry entries (see below).

entries[]

FieldTypeRequiredDescription
datasourceKey

string

Yes

Dotted-path key of the datasource (e.g. tapo.plug.current_power). The datasource must be registered before publishing.

value

number | string

Yes

The reading. Use a number for number datasources; use a string for string and boolean datasources (e.g. "true", "charging").

deviceAddress

string

No

Per-entry device address override. Takes precedence over the message-level deviceAddress for this entry only.

recordedAt

string

No

ISO-8601 timestamp. Defaults to the time the message is received. Use for backdating historical data.

// Numeric batch — two readings for the same device
{
  "deviceAddress": "192.168.1.42",
  "entries": [
    { "datasourceKey": "my-plugin.device.temperature", "value": 23.4 },
    { "datasourceKey": "my-plugin.device.battery_soc", "value": 87 }
  ]
}

// String/boolean datasource — value is always a string
{
  "deviceAddress": "192.168.1.42",
  "entries": [
    { "datasourceKey": "my-plugin.device.status", "value": "charging" }
  ]
}

// Global datasource — not scoped to a device
{
  "entries": [
    { "datasourceKey": "my-plugin.system.total_power", "value": 1420 }
  ]
}

// Backdated entry
{
  "entries": [
    {
      "datasourceKey": "my-plugin.device.temperature",
      "value": 21.1,
      "recordedAt": "2025-06-01T12:00:00Z"
    }
  ]
}

eims/registry/datasource/register

Register datasources before publishing telemetry to them. The API upserts each entry by key — safe to call on every plugin startup or reconnect. Entries that already exist are updated in place; their UUID and any associated historical data are preserved.

FieldTypeRequiredDescription
pluginKey

string

Yes

The key from your plugin.json. Used to associate datasources with your plugin so they are cleaned up on uninstall.

datasources

array

Yes

Array of datasource descriptors. Each entry: key (string), label (string), unit? (string), type (number | string | boolean), meta? (object).

{
  "pluginKey": "my-plugin",
  "datasources": [
    {
      "key": "my-plugin.device.temperature",
      "label": "Device: Temperature",
      "unit": "°C",
      "type": "number"
    },
    {
      "key": "my-plugin.device.status",
      "label": "Device: Status",
      "type": "string"
    },
    {
      "key": "my-plugin.device.battery_soc",
      "label": "Device: Battery SOC",
      "unit": "%",
      "type": "number",
      "meta": { "min": 0, "max": 100 }
    }
  ]
}

asset/updates

Register, update, or remove assets. The port field is the unique address — MAC address, IP address, or serial path — used to identify the asset across messages. Hiclaro upserts on assetAdded: if an asset with that address already exists it is updated; otherwise a new one is created.

FieldTypeRequiredDescription
data.event

string

Yes

One of: assetAdded, assetUpdated, assetRemoved.

data.data.port

string

Yes

Unique address identifying the asset (MAC, IP, or serial path).

data.data.device_info

object

assetAdded only

{ name, manufacturer, device_type } — human-readable metadata for the asset.

data.data.online

boolean

Yes

Whether the asset is currently reachable.

data.data.pluginKey

string

No

Your plugin key. Associates the asset with your plugin so it is removed on uninstall.

// Register a new asset
{
  "data": {
    "event": "assetAdded",
    "data": {
      "port": "AA:BB:CC:DD:EE:FF",
      "device_info": {
        "name": "Living Room Plug",
        "manufacturer": "Acme Corp.",
        "device_type": "Plug"
      },
      "online": true,
      "pluginKey": "my-plugin"
    }
  }
}

// Mark an asset offline
{
  "data": {
    "event": "assetUpdated",
    "data": {
      "port": "AA:BB:CC:DD:EE:FF",
      "online": false
    }
  }
}

// Remove an asset
{
  "data": {
    "event": "assetRemoved",
    "data": {
      "port": "AA:BB:CC:DD:EE:FF"
    }
  }
}

asset/location

Publish a GPS fix for an asset. The platform updates the asset's coordinates and re-evaluates zone containment automatically. No datasource registration is needed for this topic.

FieldTypeRequiredDescription
address

string

Yes

The asset's port address — same value used in asset/updates.

lat

number

Yes

Latitude in WGS-84 decimal degrees.

lng

number

Yes

Longitude in WGS-84 decimal degrees.

altitude

number

No

Altitude in metres above sea level. Used for vertical zone disambiguation on multi-floor buildings.

accuracy

number

No

Horizontal accuracy radius in metres.

{
  "address": "AA:BB:CC:DD:EE:FF",
  "lat": 47.5182,
  "lng": 19.0390,
  "altitude": 120,
  "accuracy": 5
}

© 2026 Hiclaro. All rights reserved.