Alex2Node/dist/esm/device/Device.d.ts
David 6789a1a077 bridge: publish through a Publisher; devices no longer hold the broker client
src/transport.ts has the Publisher interface, MqttPublisher (the client the bridge has at the time) and
MemoryPublisher (tests without a broker); src/topics.ts names the four topics the library publishes to.
Device, AlexaStatusMessage, AlexaErrorResponse and sendSceneResponse shared three copies of the
publish-and-report code: they now call one send() that resolves the topic or "" and never rejects.
registerDevice() and addDevice() work before connect(); a send() without a connection resolves "" and the
"error" event says to call connect(). unregisterDevice() and clearDevices() take the publisher from the device.
Device.setMqttClient() is gone, the first constructor argument of Device is ignored, and the message classes
take a Publisher where they took the client. Tests: 108 -> 113.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-28 19:34:39 +00:00

140 lines
7.2 KiB
TypeScript

import { EventEmitter } from "events";
import { AlexaErrorResponse } from "../compat/AlexaErrorResponse.js";
import { AlexaInterface } from "../compat/AlexaInterface.js";
import { AlexaStatusMessage } from "../compat/AlexaStatusMessage.js";
import { DisplayCategory } from "../compat/enums.js";
import type { AlexaInterfaceType } from "../compat/enums.js";
import type { ChangeCause } from "../messages/types.js";
import type { DisplayCategoryName } from "../registry/catalog.js";
import type { Directives, InterfaceDescriptor, Properties } from "../registry/types.js";
import type { Publisher } from "../transport.js";
import { Capability } from "./Capability.js";
import type { AnyCapability, CapabilityJson, Declaration } from "./Capability.js";
import type { EndpointFields } from "./validate.js";
/** An endpoint as bridge.addDevice() takes it. */
export interface EndpointDefinition {
/** Up to 256 letters, digits, spaces and _ - = # ; : ? @ &. The same id at every discovery. */
endpointId: string;
/** What the user calls the device: letters, digits and spaces. */
name: string;
/** The first one is the category the Alexa app shows the device under. */
categories: Array<DisplayCategoryName | DisplayCategory>;
/** Shown in the Alexa app, up to 128 characters. Default: "Alexa to Node.js bridge". */
description?: string;
/** Up to 128 characters. Default: "Alex2Node". */
manufacturerName?: string;
manufacturer?: string;
model?: string;
serialNumber?: string;
firmwareVersion?: string;
softwareVersion?: string;
customIdentifier?: string;
/** Returned with every directive to the endpoint. Up to 5000 bytes; not a place for state. */
cookie?: Record<string, string>;
/** false: the device gets no Alexa.EndpointHealth unless it declares one. */
endpointHealth?: boolean;
}
/** An endpoint object of a discovery answer (alexa-discovery-objects.html, "Endpoint object"). */
export interface EndpointJson extends EndpointFields {
capabilities: CapabilityJson[];
}
type DeclarationArguments<O, I extends boolean> = {} extends Declaration<O, I> ? [options?: Declaration<O, I>] : [options: Declaration<O, I>];
declare class Device extends EventEmitter {
private rootTopic;
name: string;
endpointId: string;
displayCategory: Array<DisplayCategory> | null;
description: string;
manufacturerName: string;
manufacturer: string;
model: string;
softwareVersion: string;
serialNumber: string;
firmwareVersion: string;
customIdentifier: string;
cookie?: Record<string, string>;
/**
* Discovery lists the Alexa interface on the endpoint (alexa-interface.html: "You must explicitly identify your
* support for the Alexa interface"). The bridge sets it from its alexaInterface option.
*/
alexaInterface: boolean;
/**
* Discovery lists Alexa.EndpointHealth when the device did not declare it and is not a scene. On for a device of
* bridge.addDevice(), off for one of registerDevice(), which is announced as 1.x announced it.
*/
endpointHealth: boolean;
private capabilities;
/** Where a failed publish from this device or a message it built is reported; Alex2MQTT sets it (1.5.2). */
onPublishError?: (err: Error) => void;
/**
* What the device and the messages it builds publish through. The bridge sets it when the device is registered
* and clears it when the device is unregistered; a MemoryPublisher here tests a device without a broker. While it
* is null every send() resolves "" and reports why.
*/
publisher: Publisher | null;
/** client is ignored: in 1.x it was the broker client, and a device could only be built after connect(). */
constructor(client: unknown, rootTopic: string, name: string, endpointId: string, displayCategory: Array<DisplayCategory> | null, description?: string, manufacturerName?: string, manufacturer?: string, model?: string);
getName(): string;
setName(name: string): void;
getEndpointId(): string;
setDisplayCategory(category: DisplayCategory | DisplayCategory[]): void;
getDisplayCategory(): Array<DisplayCategory>;
setDescription(description: string): void;
getDescription(): string;
getErrorMessage(correlationToken: string): AlexaErrorResponse;
getStatusMessage(correlationToken: string, isResponse?: boolean, isDeferred?: boolean): AlexaStatusMessage;
/**
* A proactive Alexa.ChangeReport (1.5.1): add the changed properties (the default target), optionally
* .unchanged() then the others, and .send() - it goes to <root>/changeReport, which Alex2MQTT forwards to the Alexa
* event gateway with the user's token. Alexa only accepts it for capabilities registered with proactivelyReported.
* Without a changed property send() publishes nothing and resolves with "": Alex2MQTT would drop the report.
*/
getChangeReport(cause?: ChangeCause): AlexaStatusMessage;
/**
* Alexa.SceneController: answer an Activate / Deactivate directive with ActivationStarted / DeactivationStarted
* (1.5.1). Resolves with the topic published to, or "" when the publish failed (never rejects, 1.5.2).
*/
sendSceneResponse(correlationToken: string, activated: boolean, cause?: ChangeCause, sendAsync?: boolean): Promise<string>;
/** The capabilities the device declared, in the order it declared them. */
getCapabilities(): AnyCapability[];
setManufacturerName(name: string): void;
getManufacturerName(): string;
setManufacturer(manufacturer: string): void;
getManufacturer(): string;
setModel(model: string): void;
getModel(): string;
getSoftwareVersion(): string;
/**
* Declare an interface of the device:
*
* lamp.add(PowerController, { proactivelyReported: true });
* blinds.add(RangeController, { instance: "Blind.Lift", friendlyNames: [asset("Alexa.Setting.Opening")],
* range: { min: 0, max: 100, precision: 1 } });
*
* Throws a DeclarationError that names the endpoint, the interface and the instance when Alexa would reject the
* capability; the device is then as it was before the call.
*/
add<P extends Properties, D extends Directives, O, I extends boolean>(descriptor: InterfaceDescriptor<P, D, O, I>, ...[options]: DeclarationArguments<O, I>): Capability<P, D, O>;
/**
* Declare an interface the 1.x way, by its name: options.retrievable / proactivelyReported / instance, then the
* add and set methods of the capability that is returned. Throws for a name that is not an interface. Anything
* else Alexa would reject is not refused here: check() lists it.
*/
addCapability(type: AlexaInterfaceType | string, options?: {
retrievable?: boolean;
proactivelyReported?: boolean;
instance?: string;
}): AlexaInterface;
/**
* What Alexa would reject in the device as it is declared now, one line for each: a name with punctuation, an
* interface declared twice. Also what a capability noted about its declaration. Empty when there is nothing.
* The bridge logs the lines when it answers a discovery.
*/
check(): string[];
/** The endpoint object for discovery. */
getJSON(): EndpointJson;
private fields;
private view;
private announced;
}
export default Device;