import type { IClientOptions } from "mqtt"; import Device from "./device/Device.js"; import type { EndpointDefinition } from "./device/Device.js"; import { EventEmitter } from "events"; import { DisplayCategory } from "./compat/enums.js"; import type { Timers } from "./dispatcher.js"; import type { Publisher } from "./transport.js"; /** Optional settings for the bridge (1.5.1). Everything has the 1.4.0 behaviour as its default. */ export interface Alex2MQTTOptions { /** The broker URL. Default: the public Alex2MQTT broker, mqtt://Alex2MQTT.stormysdream.club:1883. */ host?: string; /** Extra mqtt.js client options (reconnectPeriod, connectTimeout, clientId, ...). Merged over the defaults. */ mqtt?: IClientOptions; /** Where log lines go. Default: console (only when debugLogging is on). */ log?: (message: string, detail?: unknown) => void; /** * false: discovery does not list the Alexa interface on the endpoints. Default: every endpoint ends with * { type: "AlexaInterface", interface: "Alexa", version: "3" }, which Amazon requires and 1.x left out. */ alexaInterface?: boolean; /** * How long a directive may wait for its answer, in milliseconds. After that the bridge answers INTERNAL_ERROR and * emits "unanswered". Default: 6500, before Alex2MQTT gives up at 7000. 0: the bridge never answers for a handler. */ answerWithinMs?: number; /** * true: a directive for an endpoint the bridge does not have is answered with NO_SUCH_ENDPOINT. Default: it is * left alone, because the endpoint may belong to another bridge on the same root topic. */ answerUnknownEndpoints?: boolean; /** Publish here and not to the broker: a MemoryPublisher and receive() run a bridge that never connects. */ publisher?: Publisher; /** The timer of answerWithinMs, for a test that does not wait. Default: setTimeout, unref'd. */ timers?: Timers; } export declare const DEFAULT_HOST = "mqtt://Alex2MQTT.stormysdream.club:1883"; /** * The Alexa-to-MQTT bridge: one broker connection for a user's root topic, a set of registered devices, discovery and * directive dispatch. * * Events (all optional to listen to - since 1.5.1 a broker outage never throws out of the library): * "connect" connected (or reconnected) and subscribed to /discover and /+/alexaDirective * "offline" the connection dropped; mqtt.js reconnects on its own (reconnectPeriod, default 1 s) * "reconnect" a reconnect attempt starts * "close" the connection closed * "error" (err) a connection or publish error. Emitted ONLY when a listener is attached (1.4.0 emitted it * unconditionally, and Node kills a process that has an unhandled "error" event) * "discover" (n) a discovery request was answered with n devices * "directive" (info) a directive was dispatched to a device: { endpointId, namespace, name } * "unknownEndpoint" (info) a directive came for an endpoint that is not registered: { endpointId, namespace, name } * "unanswered" (info) nothing answered a directive in time and the bridge answered INTERNAL_ERROR: * { endpointId, namespace, name, correlationToken } */ declare class Alex2MQTT extends EventEmitter { private username; private password; private rootTopic; private debugLogging; private client; private readonly publisher; private readonly dispatcher; private devices; private MqttHost; private options; private logged; /** true while the broker connection is up. */ connected: boolean; /** ISO time of the last discovery request answered, null before the first. */ lastDiscoveryAt: string | null; constructor(username: string, password: string, rootTopic: string, debugLogging?: boolean, options?: Alex2MQTTOptions); private log; /** Emit "error" only when somebody listens: an unhandled "error" event would crash the host process. */ private fail; connect(): void; /** * What the bridge does with a message of the broker: it answers a discovery request, and it hands a directive to * the handlers of its device. Resolves when they are done and never rejects. With the publisher option a test * calls it in place of the broker: * * await bridge.receive("root/lamp-1/alexaDirective", JSON.stringify(directive)); */ receive(topic: string, payload: Buffer | string): Promise; private answerDiscovery; private describeDevices; /** Close the broker connection (resolves once closed). The devices stay registered; connect() again reuses them. */ disconnect(): Promise; /** * Declare a device: * * const blinds = bridge.addDevice({ endpointId: "bedroom-blinds", name: "Bedroom Blinds", * categories: ["INTERIOR_BLIND"], manufacturerName: "Acme", description: "Roller blind by Acme" }); * * Throws a DeclarationError when Alexa would reject the endpoint (an endpointId with a slash, a name with * punctuation) or when the endpointId is registered already. Discovery lists Alexa.EndpointHealth for the device * unless endpointHealth is false. A device can be declared before connect(): what it sends before the bridge has * a connection is not published, and the "error" event says so. */ addDevice(definition: EndpointDefinition): Device; registerDevice(name: string, endpointId: string, displayCategory?: DisplayCategory | DisplayCategory[] | null): Device; private register; /** Forget a device (its listeners with it). Returns false when there was none. */ unregisterDevice(endpointId: string): boolean; /** Forget every device. */ clearDevices(): void; private release; getDevices(): Device[]; getDevice(endpointId: string): Device | undefined; getRootTopic(): string; getHost(): string; } export default Alex2MQTT;