Entities
Publishing entities, state and attribute conventions per platform, and handling service calls.
Adding entities
await ctx.entities.add([{
uniqueId: `${host}:temp`, // stable within your integration; never changes for the same thing
platform: 'sensor',
name: 'Temperature',
deviceClass: 'temperature',
state: 21.5,
attributes: { unitOfMeasurement: '°C', stateClass: 'measurement' },
device: { uniqueId: host, manufacturer: 'Acme', model: 'Thing', swVersion: '1.2' },
}]);Entities sharing a device.uniqueId group under one device in the app. entityCategory: 'config' | 'diagnostic' moves housekeeping entities out of the main view. available: false
marks an entity offline (its state shows as unavailable).
Updating
ctx.entities.update(`${host}:temp`, { state: 22.1 });
ctx.entities.update(`${host}:power`, { state: 'on', attributes: { brightnessPercent: 60 } });
ctx.entities.update(`${host}:power`, { available: false });Updates are cheap and synchronous; the hub diffs and emits entity-change events for smart apps and
Flows. ctx.entities.remove(id) deletes; ctx.entities.list() returns the ids you own.
Conventions per platform
| platform | state | recognised attributes |
|---|---|---|
sensor | number or string | unitOfMeasurement, stateClass, batteryLevel, isLow |
binary_sensor | 'on' / 'off' / boolean | batteryLevel, isLow |
switch | 'on' / 'off' / boolean | — |
light | 'on' / 'off' / boolean | brightnessPercent, colorMode, kelvin, rgbColor, supportedColorModes, minColorTempKelvin, maxColorTempKelvin |
cover | open / closed / opening / closing | currentPosition, currentTiltPosition (+ supportedFeatures bitmask) |
lock | locked / unlocked / boolean | batteryLevel, isLow |
select | current option | options: string[] |
Other primitive attributes pass through unchanged. Device classes follow the platform's list (see each domain on the capability reference, e.g. binary sensor).
Handling service calls
Service names are the platform's: turnOn, turnOff, toggle, openCover, setCoverPosition,
lock, unlock, selectOption, …. Handle them per entity or centrally:
// per entity
{ uniqueId: id, platform: 'light', name: 'Lamp',
async onService(service, data) {
if (service === 'turnOn') await setLamp(true, data.brightnessPercent);
if (service === 'turnOff') await setLamp(false);
ctx.entities.update(id, { state: service === 'turnOn' ? 'on' : 'off' });
} }
// or one dispatcher for everything without onService
handleService(call, ctx) {
// call.uniqueId, call.platform, call.service, call.data
}Report the resulting state yourself with entities.update; the hub does not assume a command
succeeded. For cover, set supportedFeatures to advertise SET_POSITION and friends (bits on the
cover capability).