1.5.2: send() never rejects (status, error, scene, change report: resolves the topic or "" and reports the failure through the bridge's error event when listened to - 1.5.1 rejected, and an un-caught .send() killed the host on any broker hiccup); types ship (declaration: true, dist/*.d.ts tracked; addSupportedModes takes {value, modeResources}, ActionMapping payload optional, addHealthProp accepts EndpointHealth or the string); disconnect()/connect() re-binds devices to the new client; registerDevice returns the existing device on a duplicate endpointId (warning via the log hook, console.warn without one); ThermostatController discovery lists targetSetpoint and drops adaptiveRecoveryStatus; the UNSUPORTED INTERFACE TYPE stderr spam goes through the log hook. Examples: require("alex2node"), an error listener in each, EndpointHealth.OK, neutral endpoint ids, BlindControl reads correlationToken from the header, the thermostat reports Fahrenheit as Fahrenheit, ExamplePowerController is power-only again + new ExamplePowerControllerWithBrightness. readme (install from Forgejo, 1.5.2 changelog, table syntax), LICENSE (MIT); tests for the non-rejecting send, reconnect, duplicate, thermostat discovery and the shipped declaration signatures (8/8 on an in-process broker).
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
parent
717af632de
commit
275f00f8a7
35 changed files with 1011 additions and 176 deletions
|
|
@ -9,6 +9,8 @@ import { AlexaErrorResponse } from "./AlexaErrorResponse";
|
|||
class Device extends EventEmitter {
|
||||
protected softwareVersion: string = "1.0.0";
|
||||
private capabilities: AlexaInterface[] = [];
|
||||
/** Where a failed publish from this device or a message it built is reported; Alex2MQTT sets it (1.5.2). */
|
||||
public onPublishError?: (err: Error) => void;
|
||||
|
||||
constructor(
|
||||
private mqttClient: MqttClient,
|
||||
|
|
@ -24,6 +26,11 @@ class Device extends EventEmitter {
|
|||
super();
|
||||
}
|
||||
|
||||
/** Internal (1.5.2): Alex2MQTT.connect() re-binds every registered device to its new broker client after a disconnect(). */
|
||||
setMqttClient(client: MqttClient): void {
|
||||
this.mqttClient = client;
|
||||
}
|
||||
|
||||
getName(): string {
|
||||
return this.name;
|
||||
}
|
||||
|
|
@ -52,19 +59,21 @@ class Device extends EventEmitter {
|
|||
return this.description;
|
||||
}
|
||||
getErrorMessage(correlationToken: string): AlexaErrorResponse {
|
||||
return new AlexaErrorResponse(
|
||||
const msg = new AlexaErrorResponse(
|
||||
correlationToken,
|
||||
this.rootTopic,
|
||||
this.endpointId,
|
||||
this.mqttClient
|
||||
);
|
||||
msg.onPublishError = this.onPublishError;
|
||||
return msg;
|
||||
}
|
||||
getStatusMessage(
|
||||
correlationToken: string,
|
||||
isResponse = false,
|
||||
isDeferred = false
|
||||
): AlexaStatusMessage {
|
||||
return new AlexaStatusMessage(
|
||||
const msg = new AlexaStatusMessage(
|
||||
correlationToken,
|
||||
this.rootTopic,
|
||||
this.endpointId,
|
||||
|
|
@ -72,6 +81,8 @@ class Device extends EventEmitter {
|
|||
isResponse,
|
||||
isDeferred
|
||||
);
|
||||
msg.onPublishError = this.onPublishError;
|
||||
return msg;
|
||||
}
|
||||
/**
|
||||
* A proactive Alexa.ChangeReport (1.5.1): add the changed properties (the default target), optionally
|
||||
|
|
@ -79,11 +90,13 @@ class Device extends EventEmitter {
|
|||
* event gateway with the user's token. Alexa only accepts it for capabilities registered with proactivelyReported.
|
||||
*/
|
||||
getChangeReport(cause: ChangeCause = "PHYSICAL_INTERACTION"): AlexaStatusMessage {
|
||||
return new AlexaStatusMessage("", this.rootTopic, this.endpointId, this.mqttClient, false, false, cause);
|
||||
const msg = new AlexaStatusMessage("", this.rootTopic, this.endpointId, this.mqttClient, false, false, cause);
|
||||
msg.onPublishError = this.onPublishError;
|
||||
return msg;
|
||||
}
|
||||
/**
|
||||
* Alexa.SceneController: answer an Activate / Deactivate directive with ActivationStarted / DeactivationStarted
|
||||
* (1.5.1). Resolves with the topic published to.
|
||||
* (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 = "VOICE_INTERACTION", sendAsync = false): Promise<string> {
|
||||
const payload = {
|
||||
|
|
@ -95,8 +108,12 @@ class Device extends EventEmitter {
|
|||
},
|
||||
};
|
||||
const topic = `${this.rootTopic}/${this.endpointId}/${sendAsync ? "deferredResponse" : "alexaResponce"}`;
|
||||
return new Promise((resolve, reject) => {
|
||||
this.mqttClient.publish(topic, JSON.stringify(payload), (err) => (err ? reject(err) : resolve(topic)));
|
||||
return new Promise((resolve) => {
|
||||
this.mqttClient.publish(topic, JSON.stringify(payload), (err) => {
|
||||
if (!err) return resolve(topic);
|
||||
if (this.onPublishError) this.onPublishError(err); // -> the bridge's "error" event (when somebody listens)
|
||||
resolve(""); // 1.5.1 rejected here, and an un-caught send() then killed the host on any broker hiccup
|
||||
});
|
||||
});
|
||||
}
|
||||
getCapabilities(): AlexaInterface[] {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue