messages: pure builders for every event the bridge sends
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>
This commit is contained in:
parent
2558e21787
commit
46fa06728c
68 changed files with 3410 additions and 1208 deletions
54
dist/cjs/compat/AlexaErrorResponse.js
vendored
Normal file
54
dist/cjs/compat/AlexaErrorResponse.js
vendored
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
"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;
|
||||
Loading…
Add table
Add a link
Reference in a new issue