src/messages builds Response, StateReport, DeferredResponse, ErrorResponse, ChangeReport and the scene, doorbell and simple events from plain values; messageId and times are parameters, so a test compares whole objects. StateBuilder collects properties checked by the descriptors, AlexaError and AlexaErrors carry the payload fields of an error type. AlexaStatusMessage and AlexaErrorResponse move to src/compat and are written on the builders. On the wire, against 1.5.2: a DeferredResponse has no context key, a ChangeReport has no correlationToken, the namespace of an ErrorResponse follows its type, and a ChangeReport without a changed property is not published: send() resolves "" and the bridge reports an error that names the endpoint. 143 tests pass (108 before). Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
54 lines
2.7 KiB
JavaScript
54 lines
2.7 KiB
JavaScript
"use strict";
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
exports.AlexaErrorResponse = void 0;
|
|
const crypto_1 = require("crypto");
|
|
const build_js_1 = require("../messages/build.js");
|
|
const errors_js_1 = require("../messages/errors.js");
|
|
/** An ErrorResponse as 1.x builds it: device.getErrorMessage(token), setErrorMessage(), send(). */
|
|
class AlexaErrorResponse {
|
|
constructor(correlationToken, rootTopic, endpointId, mqttClient) {
|
|
this.correlationToken = correlationToken;
|
|
this.rootTopic = rootTopic;
|
|
this.endpointId = endpointId;
|
|
this.mqttClient = mqttClient;
|
|
// Sent when setErrorMessage() was not called: 1.x published an empty payload, which is no ErrorResponse to Alexa
|
|
this.error = errors_js_1.AlexaErrors.of("INTERNAL_ERROR", "the device answered with an error and did not say which");
|
|
// One id for the message, however often toJSON() is called
|
|
this.messageId = (0, crypto_1.randomUUID)();
|
|
}
|
|
/**
|
|
* The error to answer with. otherParams are the fields the type adds to the payload (validRange). The header
|
|
* carries the namespace the type is documented under, Alexa.ThermostatController for THERMOSTAT_IS_OFF;
|
|
* options.namespace names another.
|
|
*/
|
|
setErrorMessage(type, message, otherParams = {}, options = {}) {
|
|
this.error = errors_js_1.AlexaErrors.of(type, message, otherParams);
|
|
this.namespace = options.namespace;
|
|
}
|
|
toJSON() {
|
|
const { type, alexaMessage, extra } = this.error;
|
|
return (0, build_js_1.errorResponse)({
|
|
endpointId: this.endpointId,
|
|
messageId: this.messageId,
|
|
correlationToken: this.correlationToken,
|
|
type,
|
|
message: alexaMessage,
|
|
extra,
|
|
namespace: this.namespace ?? this.error.namespace,
|
|
});
|
|
}
|
|
/** Resolves with the topic published to, or "" when the publish failed. Never rejects. */
|
|
send(sendAsync = false) {
|
|
const topic = `${this.rootTopic}/${this.endpointId}/${sendAsync ? "deferredResponse" : "alexaResponce"}`; // "alexaResponce" is how Alex2MQTT and Alex2ESP spell the topic
|
|
return new Promise((resolve) => {
|
|
this.mqttClient.publish(topic, JSON.stringify(this.toJSON()), (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
|
|
});
|
|
});
|
|
}
|
|
}
|
|
exports.AlexaErrorResponse = AlexaErrorResponse;
|