registry: SceneController events, DoorbellEventSource, SimpleEventSource, TimeHoldController, InventoryLevelSensor, WakeOnLANController

Six descriptors written from their pages replace the last stubs of tiers 1 and 2. A scene answers Activate and
Deactivate through ctx.respond() with ActivationStarted and DeactivationStarted, the time and the cause filled
in. device.raise(descriptor, name, payload) publishes DoorbellPress and the Event of a button on <root>/event
with the endpoint and a new messageId; it throws a MessageError for an interface or instance the device did
not declare, an event that answers a directive, a payload that does not fit and a message over 16000 bytes.
TurnOn of a device with WakeOnLANController is deferred without the warning.

On the wire: a doorbell has no properties object and proactivelyReported on the capability; SimpleEventSource
is version 1.0, InventoryLevelSensor and WakeOnLANController version 3 (1.5.2: 1). A scene declared without
options is announced as before. Alex2MQTT has no topic yet for the WakeUp event.
24 examples of the six pages are saved as fixtures. 267 tests pass, 241 before.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
David 2026-09-28 21:01:53 +00:00
parent d7dfc5b122
commit 3a07c861b1
116 changed files with 3136 additions and 166 deletions

View file

@ -21,6 +21,12 @@ export declare const DISPLAY_CATEGORIES: readonly ["ACTIVITY_TRIGGER", "AIR_COND
export type DisplayCategoryName = (typeof DISPLAY_CATEGORIES)[number];
/** Not to be used as a friendly name (resources-and-assets.html, "Reserved words"). */
export declare const RESERVED_WORDS: readonly ["alarm", "alarms", "all alarms", "away mode", "bass", "camera", "date", "date today", "day", "do not disturb", "drop in", "music", "night light", "notification", "playing", "sleep sounds", "time", "timer", "today in music", "treble", "volume", "way f. m."];
/**
* Why a property changed or an event was raised (message-guide.html, "Cause object"). RULE_TRIGGER is not in that
* table; the ChangeReport examples of alexa-securitypanelcontroller.html and alexa-thermostatcontroller.html use it.
*/
export declare const CAUSES: readonly ["APP_INTERACTION", "PERIODIC_POLL", "PHYSICAL_INTERACTION", "RULE_TRIGGER", "VOICE_INTERACTION"];
export type Cause = (typeof CAUSES)[number];
/**
* What a discovery answer may hold (alexa-discovery.html, "Interface limits"; alexa-discovery-objects.html,
* "Endpoint object details" and "AdditionalAttributes object details"; alexa-scenecontroller.html, "Discovery").

13
dist/types/registry/events.d.ts vendored Normal file
View file

@ -0,0 +1,13 @@
import type { Cause } from "./catalog.js";
/** The time of an event: now, unless the payload says when. */
export declare const timestamp: import("./schema.js").Schema<string>;
/**
* The payload of an event that happened at a time and for a reason: ActivationStarted, DoorbellPress. Both are
* required by Alexa. The cause is the usual one of the event unless the payload names another.
*/
export declare const happened: (usually: Cause) => import("./schema.js").Schema<import("./schema.js").InferShape<{
cause: import("./schema.js").Schema<{
type: "APP_INTERACTION" | "PERIODIC_POLL" | "PHYSICAL_INTERACTION" | "RULE_TRIGGER" | "VOICE_INTERACTION";
}>;
timestamp: import("./schema.js").Schema<string>;
}>>;

View file

@ -4,10 +4,12 @@ import { ChannelController } from "./interfaces/ChannelController.js";
import { ColorController } from "./interfaces/ColorController.js";
import { ColorTemperatureController } from "./interfaces/ColorTemperatureController.js";
import { ContactSensor } from "./interfaces/ContactSensor.js";
import { DoorbellEventSource } from "./interfaces/DoorbellEventSource.js";
import { EndpointHealth } from "./interfaces/EndpointHealth.js";
import { EqualizerController } from "./interfaces/EqualizerController.js";
import { HumiditySensor } from "./interfaces/HumiditySensor.js";
import { InputController } from "./interfaces/InputController.js";
import { InventoryLevelSensor } from "./interfaces/InventoryLevelSensor.js";
import { LockController } from "./interfaces/LockController.js";
import { ModeController } from "./interfaces/ModeController.js";
import { MotionSensor } from "./interfaces/MotionSensor.js";
@ -17,13 +19,17 @@ import { PlaybackStateReporter } from "./interfaces/PlaybackStateReporter.js";
import { PowerController } from "./interfaces/PowerController.js";
import { PowerLevelController } from "./interfaces/PowerLevelController.js";
import { RangeController } from "./interfaces/RangeController.js";
import { SceneController } from "./interfaces/SceneController.js";
import { SecurityPanelController } from "./interfaces/SecurityPanelController.js";
import { SimpleEventSource } from "./interfaces/SimpleEventSource.js";
import { Speaker } from "./interfaces/Speaker.js";
import { StepSpeaker } from "./interfaces/StepSpeaker.js";
import { TemperatureSensor } from "./interfaces/TemperatureSensor.js";
import { ThermostatController } from "./interfaces/ThermostatController.js";
import { ThermostatControllerSchedule } from "./interfaces/ThermostatControllerSchedule.js";
import { TimeHoldController } from "./interfaces/TimeHoldController.js";
import { ToggleController } from "./interfaces/ToggleController.js";
import { WakeOnLANController } from "./interfaces/WakeOnLANController.js";
import type { AnyDescriptor } from "./types.js";
export declare const registry: {
/** Whether an interface of this name is known. */
@ -33,9 +39,10 @@ export declare const registry: {
/** Every descriptor, ordered by namespace. */
list(): AnyDescriptor[];
};
export { Alexa, BrightnessController, ChannelController, ColorController, ColorTemperatureController, ContactSensor, EndpointHealth, EqualizerController, HumiditySensor, InputController, LockController, ModeController, MotionSensor, PercentageController, PlaybackController, PlaybackStateReporter, PowerController, PowerLevelController, RangeController, SecurityPanelController, Speaker, StepSpeaker, TemperatureSensor, ThermostatController, ThermostatControllerSchedule, ToggleController, };
export { Alexa, BrightnessController, ChannelController, ColorController, ColorTemperatureController, ContactSensor, DoorbellEventSource, EndpointHealth, EqualizerController, HumiditySensor, InputController, InventoryLevelSensor, LockController, ModeController, MotionSensor, PercentageController, PlaybackController, PlaybackStateReporter, PowerController, PowerLevelController, RangeController, SceneController, SecurityPanelController, SimpleEventSource, Speaker, StepSpeaker, TemperatureSensor, ThermostatController, ThermostatControllerSchedule, TimeHoldController, ToggleController, WakeOnLANController, };
export { INPUTS } from "./interfaces/InputController.js";
export type { InputName } from "./interfaces/InputController.js";
export type { InventoryLevel } from "./interfaces/InventoryLevelSensor.js";
export type { Mode } from "./interfaces/ModeController.js";
export { THERMOSTAT_MODES } from "./interfaces/ThermostatController.js";
export type { ThermostatModeName } from "./interfaces/ThermostatController.js";

View file

@ -0,0 +1,6 @@
/**
* A doorbell. It takes no directive and reports nothing; device.raise(DoorbellEventSource, "DoorbellPress") says
* that somebody rang. Alexa wants 30 seconds between two presses of one doorbell, and announces a press when the
* user switched the announcements on for the doorbell in the Alexa app.
*/
export declare const DoorbellEventSource: import("../types.js").InterfaceDescriptor<{}, {}, {}, false>;

View file

@ -0,0 +1,34 @@
import type { Infer, Schema } from "../schema.js";
declare const level: Schema<import("../schema.js").InferShape<{
"@type": import("../schema.js").EnumSchema<"Count" | "Percentage" | "Volume" | "Weight">;
value: Schema<number>;
unit: import("../schema.js").OptionalSchema<string>;
}>>;
export type InventoryLevel = Infer<typeof level>;
/**
* How much is left of something a device uses up: ink, paper, detergent. Each instance is one sensor, and Amazon
* orders a refill by its Dash replenishment id. The level is reported, there is nothing to ask for by voice.
*/
export declare const InventoryLevelSensor: import("../types.js").InterfaceDescriptor<{
level: {
name: string;
value: Schema<import("../schema.js").InferShape<{
"@type": import("../schema.js").EnumSchema<"Count" | "Percentage" | "Volume" | "Weight">;
value: Schema<number>;
unit: import("../schema.js").OptionalSchema<string>;
}>>;
note: string;
};
}, {}, import("../schema.js").InferShape<{
/** How the level is measured: { "@type": "Volume", unit: "MILLILITER" }, { "@type": "Count" }. */
measurement: Schema<import("../schema.js").InferShape<{
"@type": import("../schema.js").EnumSchema<"Count" | "Percentage" | "Volume" | "Weight">;
unit: import("../schema.js").OptionalSchema<string>;
}>>;
/** The id the Dash console gave for the product. */
replenishment: Schema<import("../schema.js").InferShape<{
"@type": import("../schema.js").EnumSchema<"DashReplenishmentId">;
value: Schema<string>;
}>>;
}>, true>;
export {};

View file

@ -0,0 +1,21 @@
/**
* A scene: an endpoint that is not a device, but several devices set to a state each. Activate is answered with
* ActivationStarted and Deactivate with DeactivationStarted; ctx.respond() sends them, with the time and
* VOICE_INTERACTION as the cause. A scene reports nothing and has no Alexa.EndpointHealth.
*
* Alexa takes no scene with a lock, a garage door, a camera, a cooking appliance or a security device in it.
*/
export declare const SceneController: import("../types.js").InterfaceDescriptor<{}, {
Activate: {
name: string;
payload: import("../schema.js").Schema<import("../schema.js").InferShape<{}>>;
};
Deactivate: {
name: string;
payload: import("../schema.js").Schema<import("../schema.js").InferShape<{}>>;
when: ({ options }: import("../types.js").Declared<any>) => boolean;
};
}, import("../schema.js").InferShape<{
/** The scene can be switched off again. */
supportsDeactivation: import("../schema.js").OptionalSchema<boolean>;
}>, false>;

View file

@ -0,0 +1,15 @@
/**
* A button of a remote, or anything else that routines start on. Each instance is one button with the events it
* has, a single and a double push; device.raise(SimpleEventSource, "Event", { id }, { instance }) says that one
* happened. Alexa wants the instance to be unique among all endpoints, "preferably a version 4 UUID".
*
* The page folds its discovery example away. The capability is announced with the fields of its table and without a
* properties object, as the interface has no property.
*/
export declare const SimpleEventSource: import("../types.js").InterfaceDescriptor<{}, {}, import("../schema.js").InferShape<{
/** For a REMOTE the names are assets of the catalog: Alexa.Button.SinglePush, Alexa.Gesture.Tap. */
supportedEvents: import("../schema.js").Schema<import("../schema.js").InferShape<{
id: import("../schema.js").Schema<string>;
friendlyNames: import("../schema.js").Schema<import("../types.js").Label[]>;
}>[]>;
}>, true>;

View file

@ -0,0 +1,27 @@
/**
* Pausing what a device does, a microwave that heats, and going on with it. Amazon pairs the interface with
* Alexa.Cooking. Alexa sends Resume to a device declared with allowRemoteResume only; for another one it asks the
* user to press start on the device.
*/
export declare const TimeHoldController: import("../types.js").InterfaceDescriptor<{
holdStartTime: {
name: string;
value: import("../schema.js").Schema<string>;
};
holdEndTime: {
name: string;
value: import("../schema.js").Schema<string>;
};
}, {
Hold: {
name: string;
payload: import("../schema.js").Schema<import("../schema.js").InferShape<{}>>;
};
Resume: {
name: string;
payload: import("../schema.js").Schema<import("../schema.js").InferShape<{}>>;
when: ({ options }: import("../types.js").Declared<any>) => boolean;
};
}, import("../schema.js").InferShape<{
allowRemoteResume: import("../schema.js").Schema<boolean>;
}>, false>;

View file

@ -0,0 +1,10 @@
/**
* A device that is switched on by a Wake-on-LAN message, which an Echo of the user sends to the MAC addresses of
* the capability. The interface has no directive and no property: the device gets TurnOn of Alexa.PowerController,
* answers with a DeferredResponse, sends the WakeUp event and, when it is up, the Response.
*
* Alex2MQTT has no topic yet that takes the WakeUp event to Alexa.
*/
export declare const WakeOnLANController: import("../types.js").InterfaceDescriptor<{}, {}, import("../schema.js").InferShape<{
macAddresses: import("../schema.js").Schema<string[]>;
}>, false>;

View file

@ -62,6 +62,8 @@ declare function enumeration<V extends readonly string[]>(...values: V): EnumSch
declare function oneOf<V extends string>(values: readonly V[], expects: string): EnumSchema<V>;
declare function unknown(): Schema<unknown>;
declare function optional<T>(inner: Schema<T>): OptionalSchema<T>;
/** A value that is made when none is given: the time of an event, which is now unless the caller says when. */
declare function defaulted<T>(inner: Schema<T>, make: () => T): Schema<T>;
declare function nullable<T>(inner: Schema<T>): Schema<T | null>;
declare function array<T>(item: Schema<T>, rules?: {
min?: number;
@ -87,6 +89,7 @@ export declare const s: {
oneOf: typeof oneOf;
unknown: typeof unknown;
optional: typeof optional;
defaulted: typeof defaulted;
nullable: typeof nullable;
array: typeof array;
object: typeof object;

View file

@ -138,6 +138,14 @@ export interface InterfaceDescriptor<P extends Properties = Properties, D extend
errorTypes?: readonly string[];
/** Amazon documents a DeferredResponse for the interface. */
deferrable?: boolean;
/**
* The directives of other interfaces that Amazon documents a DeferredResponse for on an endpoint with this one:
* TurnOn of Alexa.PowerController, for a device that is woken over the LAN.
*/
defers?: ReadonlyArray<{
namespace: string;
name: string;
}>;
/** Rules a schema cannot state, for options that passed the schema. Throws DeclarationError. */
validate?: (capability: Declared<O>, endpoint: EndpointView) => void;
}