Subscriptions and events
subscribe, unsubscribe, matchesState, subscribeToLocationEvent, sendLocationEvent, getEntityIds
Global functions available to smart-app code. Call them by bare name; there is no object to import.
| Function | Summary |
|---|---|
subscribe | Subscribe to entity state changes. |
unsubscribe | Remove entity subscriptions: everything, everything for one handler, or those on a given target. |
matchesState | Does value name state for this entity? value is the raw token ('on') or the friendly label the app shows ('Open', 'Armed Away'), case- and separator-insensitive. |
subscribeToLocationEvent | Subscribe to a named location event (e.g. |
sendLocationEvent | Fire a named location event. |
getEntityIds | Normalise an entity input to a list of entity ids: one id for a single pick, every id for a multi-select proxy, [] for anything else. |
subscribe
Subscribe to entity state changes. The filter is validated strictly at subscribe() time (unknown keys throw, aborting installed()/updated()): {} matches any change (state OR attribute delta); from/to fire only on a real state transition; state is a legacy alias of to (never combine the two); attribute.value omitted = any change of that attribute. Mirrors smartAppSubscriptionFilterSchema in
Signature
function subscribe(target: unknown, filter: { from?: string; to?: string; state?: string; attribute?: { name: string; value?: unknown }; }, handler: unknown): voidParameters
| Name | Type | Required | Default | Description |
|---|---|---|---|---|
target | unknown | yes | — | An entity input (Entity), an array of them, or an entity id string. A multi-select input hydrates as an array-like proxy and subscribes every member. |
filter | { from?: string; to?: string; state?: string; attribute?: { name: string; value?: unknown }; } | yes | — | {} matches any change (state or attribute). from / to fire only on a real state transition and accept the raw token ('on') or the friendly label the app shows for that entity ('Open', 'Detected', 'Armed Away'), any case or separator. state is a legacy alias of to (never combine the two). attribute: { name, value? } watches one attribute; omit value for any change of it. Unknown keys throw. |
handler | unknown | yes | — | A top-level named function (or its name as a string). Handlers are dispatched by name, so arrow functions assigned to variables cannot be used. Receives an EntityChangeEvent. |
Returns
void — Throws when an argument is missing or the host rejects the filter, which aborts the installed() / updated() call that made it.
Notes
- Subscriptions are persisted and restored across hub reboots; you do not re-subscribe on
systemStart. - Call
unsubscribe()at the top ofupdated()before subscribing again, or a changed device picker leaves the old subscription dangling. - A label is resolved against the entity's domain and device class when the subscription is matched; the filter is stored as you wrote it.
{ to: 'on' }and{ to: 'Open' }on the same handler collapse to one subscription and fire once.
Examples
subscribe($g.motionSensor, { state: 'on' }, onMotionDetected);
subscribe($g.motionSensor, { state: 'off' }, onMotionCleared);subscribe($g.frontDoor, { to: 'Open' }, onDoorOpen); // binary_sensor/door: 'Open' → on
subscribe($g.panel, { to: 'Armed Away' }, onArmedAway); // intrusion panel
subscribe($g.garage, { from: 'Closed', to: 'Opening' }, onLeaving);subscribe($g.light, { attribute: { name: 'brightnessPercent' } }, onBrightness);
function onBrightness(evt) {
if (evt.newState.context?.actorType !== 'physical') return; // ignore app-driven changes
console.log('Dimmed by hand to', evt.newState.attributes?.brightnessPercent);
}See also
unsubscribe · EntityChangeEvent · subscription filter · subscriptions and events
unsubscribe
Remove entity subscriptions: everything, everything for one handler, or those on a given target.
Signature
function unsubscribe(target: unknown, filter?: unknown, handler?: unknown): voidParameters
| Name | Type | Required | Default | Description |
|---|---|---|---|---|
target | unknown | yes | — | Entity, array of entities, entity id, or undefined. With no target the call is a clear-all (optionally narrowed by handler). |
filter | unknown | no | undefined | Optional: remove only subscriptions registered with exactly this filter. |
handler | unknown | no | undefined | Optional: remove only subscriptions for this handler (function or name). |
Returns
void
Examples
$g.updated = function () {
unsubscribe(undefined); // drop every subscription
unschedule(undefined); // and every schedule / timer
initialize();
};See also
matchesState
Does value name state for this entity? value is the raw token ('on') or the friendly label the app shows ('Open', 'Armed Away'), case- and separator-insensitive. The handler-body twin of entity.is() — pass the event's snapshot, e.g. matchesState(evt.entityId, evt.newState.state, 'open'). Throws on an unknown entity.
Signature
function matchesState(entityId: string, state: string | null | undefined, value: string): booleanParameters
| Name | Type | Required | Default | Description |
|---|---|---|---|---|
entityId | string | yes | — | The entity to resolve the label against (its domain and device class pick the label table). |
state | string | null | undefined | yes | — | The state to test, normally evt.newState.state or evt.oldState.state so the event's snapshot is tested rather than the live row. null / undefined never match. |
value | string | yes | — | A raw token ('on') or the friendly label the app shows for this entity ('Open', 'Armed Away'), any case; spaces, hyphens and underscores are interchangeable. |
Returns
boolean — true when value names state. Throws when the entity is unknown.
Notes
- The handler-body twin of
entity.is(): use it on the event snapshot you were handed, because the live state may already have moved on. - Raw tokens always match themselves; labels are only an input alias. Numeric domains (
sensor,input_number,counter) never resolve a label.
Examples
function onDoor(evt) {
if (matchesState(evt.entityId, evt.newState.state, 'Open')) {
sendPushNotification('Front door opened');
}
}See also
is · subscribe · subscriptions and events
subscribeToLocationEvent
Subscribe to a named location event (e.g. systemStart, fired once per boot after the framework restores schedules + subscriptions). The subscription is persisted and restored across reboots.
Signature
function subscribeToLocationEvent(eventName: string, handler: unknown): voidParameters
| Name | Type | Required | Default | Description |
|---|---|---|---|---|
eventName | string | yes | — | Event name. The platform fires systemStart once per boot; any other name is a custom event sent by a smart app with sendLocationEvent. |
handler | unknown | yes | — | A top-level named function (or its name as a string). Handlers are dispatched by name, so arrow functions assigned to variables cannot be used. Receives the event payload ({ name, value, … }). |
Returns
void
Examples
subscribeToLocationEvent('systemStart', onSystemStart);
function onSystemStart() {
scheduleAtSunset(onSunset);
}See also
sendLocationEvent · subscriptions and events
sendLocationEvent
Available at runtime but not declared in ambient.d.ts; add your own declare line when authoring in TypeScript.
Fire a named location event. Every smart app subscribed to that name — including other apps — receives it, which makes it the inter-app back-channel.
Signature
function sendLocationEvent(eventName, data)Parameters
| Name | Type | Required | Default | Description |
|---|---|---|---|---|
eventName | unknown | yes | — | Any non-empty string. Pick a namespaced name (myorg.doorbell.pressed) to avoid collisions. |
data | unknown | yes | — | JSON-serialisable payload delivered to subscribers as the event value. |
Returns
void
Notes
- Not declared in
ambient.d.tsyet, so TypeScript authors needdeclare function sendLocationEvent(eventName: string, data?: unknown): void;.
Examples
sendLocationEvent('house.guestMode', { enabled: true });See also
getEntityIds
Available at runtime but not declared in ambient.d.ts; add your own declare line when authoring in TypeScript.
Normalise an entity input to a list of entity ids: one id for a single pick, every id for a multi-select proxy, [] for anything else.
Signature
function getEntityIds(entity)Parameters
| Name | Type | Required | Default | Description |
|---|---|---|---|---|
entity | unknown | yes | — | A single Entity, a multi-select proxy, or any other value. |
Returns
string[]
Notes
- Not declared in
ambient.d.ts; declare it yourself in TypeScript or useArray.isArray(input) ? input : [input]on the wrappers instead.
Examples
const ids = getEntityIds($g.lights); // ['light.kitchen', 'light.hall']