Overview

Plugins

Widgets

Reference

Publishing

WidgetApi

The interface provided to every widget for accessing telemetry, datasource metadata, and device state. The same API is available on both desktop and mobile.

Methods

MethodDescription
subscribeTelemetry(options)

Subscribe to telemetry data. Returns an unsubscribe function. Call it during cleanup (disconnectedCallback on desktop, useEffect cleanup on mobile) to avoid memory leaks.

getDatasourceById(id)

Returns the Datasource object (id, key, label, unit, type) for the given ID, or undefined.

getDatasourceByKey(key)

Returns the Datasource object for the given dotted-path key (e.g. tapo.plug.current_power), or undefined. Useful when the key is known statically and the ID is not.

getAssetById(id)

Returns the Asset object for the given ID, or undefined.

getAllAssets()

Returns the full list of all assets known to the host. Does not make a network call — reads from the host's in-memory asset registry. Use this to discover assets belonging to your plugin without REST calls from widget code.

getAllZones()

Returns the full list of all zones defined in the system. Does not make a network call — reads from host state cached at dashboard load. Use alongside getAllAssets() to group assets by zone.

getActionRegistrations()

Returns the list of all available action registrations.

getActionRegistrationByKey(key)

Returns the ActionRegistration for the given key, or undefined. Useful when the action key is known statically and you need the full registration object (e.g. to check hasValue or perDevice before triggering).

triggerAction(id, options?)

Dispatch an action by its registration ID. Returns a Promise that resolves when the action has been sent. Only plugin actions can be triggered — system actions (pluginId: null) are rejected by the server.

triggerActionByKey(key, options?)

Dispatch an action by its key instead of its ID. Resolves the key to a registration at call time and delegates to triggerAction. Rejects if no registration is found for the key.

subscribeTelemetry options

FieldTypeRequiredDescription
datasourceIds

string[]

Yes

One or more datasource IDs to subscribe to.

deviceIds

string[]

No

Restrict results to these asset IDs (database UUIDs). Omit to receive data for all assets.

mode

string

Yes

latest — callback receives the most recent data point per datasource/device. history — callback receives an array of data points per datasource/device.

hours

number

No

Number of hours of history to fetch. Only used when mode is history. Defaults to 24.

callback

function

Yes

Called with a data object on each update. Shape depends on mode — see below.

Callback data shapes

The data object passed to callback is keyed by datasource ID, then by asset ID. Both are database UUID strings — the same values stored in instanceConfig for datasource and asset input fields. In latest mode each leaf is a single data point; in history mode it is an array ordered oldest to newest.

// mode: 'latest' — callback data shape
{
  "datasource-id": {
    "device-id-1": { "recordedAt": 1715000000, "value": 83 },
    "device-id-2": { "recordedAt": 1715000000, "value": 61 }
  }
}
// mode: 'history' — callback data shape
{
  "datasource-id": {
    "device-id": [
      { "recordedAt": 1714900000, "value": 72 },
      { "recordedAt": 1714950000, "value": 78 },
      { "recordedAt": 1715000000, "value": 83 }
    ]
  }
}

triggerAction / triggerActionByKey options

Both methods accept the same optional second argument. The difference is in the first argument: triggerAction takes the registration UUID (as stored in instanceConfig for action input fields), while triggerActionByKey takes the stable string key defined in the plugin manifest. Omit value for actions where hasValue is false, and omit assetId for actions where perDevice is false.

FieldTypeRequiredDescription
id

string

Yes

The action registration ID to trigger. Obtain it from getActionRegistrations() or from an action input field in instanceConfig.

options.value

string

No

Value to pass to the action. Only used when the registration's hasValue is true.

options.assetId

string

No

Target asset UUID. Only used when the registration's perDevice is true.

ActionRegistration shape

Each object returned by getActionRegistrations() has the following fields. The action input type in a widget manifest stores the selected registration ID in instanceConfig, which you can pass directly to triggerAction.

FieldTypeRequiredDescription
id

string

Yes

UUID that uniquely identifies this registration. Pass it to triggerAction.

key

string

Yes

Action key defined in the plugin manifest (e.g. turn_on). Stable across reinstalls.

label

string

Yes

Human-readable name shown to users.

hasValue

boolean

Yes

True if the action accepts a value payload.

valueType

'number' | 'string' | 'boolean' | null

Yes

Expected type of the value when hasValue is true.

acceptedValues

string[] | { value: string; label: string }[] | null

No

Fixed set of allowed values declared by the plugin. When non-null and non-empty, the automation builder renders a Select instead of a free-text input. Inspect this field in widget code when building a custom action trigger UI — use it to populate a picker rather than letting the user type a raw string.

perDevice

boolean

Yes

True if the action targets a specific asset. Pass assetId in triggerAction options when this is true.

pluginId

string | null

Yes

ID of the plugin that registered this action. null for built-in system actions, which cannot be triggered via triggerAction.

Asset shape

Each object returned by getAllAssets() has the following fields. Neither getAllAssets() nor getAllZones() makes a network call — both read from the host's in-memory state and are safe to call on every render.

FieldTypeRequiredDescription
id

string

Yes

UUID that uniquely identifies this asset.

name

string

Yes

Human-readable display name set by the user.

assetType

string | null

No

Device category string defined by the plugin (e.g. 'Sensor', 'Plug'). Use this to distinguish device types within a single plugin.

pluginId

string | null

No

ID of the plugin that registered this asset. Use this to filter assets belonging to your plugin.

assignedZone

{ id: string; name: string } | null

No

Zone the user has assigned this asset to, or null if unassigned.

online

boolean | null

No

Last known connectivity state reported by the plugin service.

Zone shape

Each object returned by getAllZones() has the following fields. Zones form a tree via parentId. Top-level zones have parentId: null.

FieldTypeRequiredDescription
id

string

Yes

UUID that uniquely identifies this zone.

name

string

Yes

Human-readable display name set by the user.

zoneType

string | null

No

One of 'building', 'floor', or 'room'. Use this to determine zone hierarchy level.

parentId

string | null

No

ID of the parent zone, or null for top-level zones.

sortOrder

number

Yes

Display order within the same parent zone. Sort by this field when rendering zone lists.

Asset discovery pattern

Widgets that need to enumerate all devices of a given type — such as an "all sensors overview" widget — should use getAllAssets() filtered by pluginId and assetType. The pluginId value is injected by the host as a DOM property alongside widgetApi and instanceConfig. Expose a set pluginId accessor in your custom element and pass the value down to your React component.

This avoids hardcoding the plugin ID (which is a UUID assigned at install time) and allows the same widget code to work regardless of which EIMS instance it runs on.

// index.tsx — host injects pluginId as a DOM property alongside widgetApi
set pluginId(value: string) {
  this._pluginId = value;
  this._render();
}

// Widget component — filter assets by pluginId and assetType
const sensors = api.getAllAssets().filter(
  (asset) => asset.pluginId === pluginId && asset.assetType === 'Sensor'
);

// Build a zone lookup map for grouping
const zones = api.getAllZones();
const zoneMap = new Map(zones.map((zone) => [zone.id, zone]));

// Subscribe to telemetry for all discovered assets in one call
const unsubscribe = api.subscribeTelemetry({
  datasourceIds: [datasourceId],
  assetIds: sensors.map((sensor) => sensor.id),
  mode: 'latest',
  callback: (data) => { /* … */ },
});

© 2026 Hiclaro. All rights reserved.