"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.AlexaStatusMessage = exports.TemperatureSensorScale = exports.PowerController = exports.ThermostatMode = exports.EndpointHealth = void 0; const uuid_1 = require("uuid"); const AlexaInterface_1 = require("./AlexaInterface"); var EndpointHealth; (function (EndpointHealth) { EndpointHealth["OK"] = "OK"; EndpointHealth["UNREACHABLE"] = "UNREACHABLE"; })(EndpointHealth || (exports.EndpointHealth = EndpointHealth = {})); var ThermostatMode; (function (ThermostatMode) { ThermostatMode["OFF"] = "OFF"; ThermostatMode["HEAT"] = "HEAT"; ThermostatMode["COOL"] = "COOL"; ThermostatMode["AUTO"] = "AUTO"; ThermostatMode["ECO"] = "ECO"; ThermostatMode["CUSTOM"] = "CUSTOM"; })(ThermostatMode || (exports.ThermostatMode = ThermostatMode = {})); var PowerController; (function (PowerController) { PowerController["ON"] = "ON"; PowerController["OFF"] = "OFF"; })(PowerController || (exports.PowerController = PowerController = {})); var TemperatureSensorScale; (function (TemperatureSensorScale) { TemperatureSensorScale["CELSIUS"] = "CELSIUS"; TemperatureSensorScale["FAHRENHEIT"] = "FAHRENHEIT"; })(TemperatureSensorScale || (exports.TemperatureSensorScale = TemperatureSensorScale = {})); class AlexaStatusMessage { constructor(correlationToken, rootTopic, endpointId, mqttClient, isResponse = false, isDeferred = false, changeCause = null) { this.context = { properties: [] }; /** ChangeReport only: the properties that changed (payload.change.properties); the rest go to context. */ this.changeProps = []; this.changeCause = null; this.target = "context"; this.rootTopic = rootTopic; this.endpointId = endpointId; this.mqttClient = mqttClient; this.isDeferred = isDeferred; this.changeCause = changeCause; if (changeCause) this.target = "change"; this.event = { header: { namespace: "Alexa", name: changeCause ? "ChangeReport" : isDeferred ? "DeferredResponse" : isResponse ? "Response" : "StateReport", payloadVersion: "3", messageId: this.generateMessageId(), correlationToken, }, endpoint: { endpointId, }, payload: {}, }; } generateMessageId() { return (0, uuid_1.v4)(); } getTimestamp() { return new Date().toISOString(); } addProperty(namespace, name, value, uncertaintyInMilliseconds = 0, instance) { const prop = { namespace, name, value, timeOfSample: this.getTimestamp(), uncertaintyInMilliseconds, }; if (instance) prop.instance = instance; (this.target === "change" ? this.changeProps : this.context.properties).push(prop); return this; } /** ChangeReport: the add*Prop calls that follow describe what CHANGED (the default for a change report). */ changed() { this.target = "change"; return this; } /** ChangeReport: the add*Prop calls that follow describe the other, unchanged properties (context). */ unchanged() { this.target = "context"; return this; } /** True for a ChangeReport (Device.getChangeReport). */ isChangeReport() { return this.changeCause !== null; } /** The message as it will be published (for tests and logging). */ toJSON() { if (this.changeCause) { return { event: Object.assign(Object.assign({}, this.event), { payload: { change: { cause: { type: this.changeCause }, properties: this.changeProps } } }), context: this.context, }; } return { context: this.isDeferred ? null : this.context, event: this.event }; } addModeControllerProp(instance, value, uncertaintyInMs = 0) { return this.addProperty(AlexaInterface_1.AlexaInterfaceType.MODE_CONTROLLER, "mode", value, uncertaintyInMs, instance); } addThermostatModeProp(mode, uncertaintyInMs = 0) { return this.addProperty(AlexaInterface_1.AlexaInterfaceType.THERMOSTAT_CONTROLLER, "thermostatMode", mode, uncertaintyInMs); } addEstimatedDeferralTime(seconds) { if (this.isDeferred) { this.event.payload = { estimatedDeferralInSeconds: seconds, }; } else { console.warn("[AlexaStatusMessage.ts] Attempted to add estimated deferral time, but message is not marked as DeferredResponse."); } return this; } addThermostatControllerProp(name, scale, value, uncertaintyInMs = 0) { const tempValue = { value: scale === TemperatureSensorScale.FAHRENHEIT ? (value - 32) * (5 / 9) : value, scale: "CELSIUS", }; return this.addProperty(AlexaInterface_1.AlexaInterfaceType.THERMOSTAT_CONTROLLER, name, tempValue, uncertaintyInMs); } addHealthProp(health, uncertaintyInMs = 0) { return this.addProperty(AlexaInterface_1.AlexaInterfaceType.ENDPOINT_HEALTH, "connectivity", { value: health }, uncertaintyInMs); } addPowerControllerProp(power, uncertaintyInMs = 0) { return this.addProperty(AlexaInterface_1.AlexaInterfaceType.POWER_CONTROLLER, "powerState", power, uncertaintyInMs); } addTemperatureSensorProp(scale, value, uncertaintyInMs = 0) { const tempValue = { value: scale === TemperatureSensorScale.FAHRENHEIT ? (value - 32) * (5 / 9) : value, scale: "CELSIUS", }; return this.addProperty(AlexaInterface_1.AlexaInterfaceType.TEMPERATURE_SENSOR, "temperature", tempValue, uncertaintyInMs); } addBrightnessControllerProp(brightness, uncertaintyInMs = 0) { return this.addProperty(AlexaInterface_1.AlexaInterfaceType.BRIGHTNESS_CONTROLLER, "brightness", brightness, uncertaintyInMs); } addColorTemperatureControllerProp(colorTemp, uncertaintyInMs = 0) { return this.addProperty(AlexaInterface_1.AlexaInterfaceType.COLOR_TEMPERATURE_CONTROLLER, "colorTemperatureInKelvin", colorTemp, uncertaintyInMs); } addToggleControllerProp(state, instance, uncertaintyInMs = 0) { return this.addProperty(AlexaInterface_1.AlexaInterfaceType.TOGGLE_CONTROLLER, "toggleState", state, uncertaintyInMs, instance); } addContextProp(prop) { this.context.properties.push(prop); return this; } /** * Publish: a Response/StateReport to //alexaResponce (sendAsync: deferredResponse), a ChangeReport * to /changeReport (Alex2MQTT adds the user's token and posts it to the Alexa event gateway). Resolves with * the topic; rejects on a publish error (1.4.0 only logged). */ send(sendAsync = false) { const payloadStr = JSON.stringify(this.toJSON()); const topic = this.changeCause ? `${this.rootTopic}/changeReport` : `${this.rootTopic}/${this.endpointId}/${sendAsync ? "deferredResponse" : "alexaResponce"}`; //Yes this should be response but it is incorrect in both Alex2MQTT and Alex2ESP so for consistency is is wrong here too return new Promise((resolve, reject) => { this.mqttClient.publish(topic, payloadStr, (err) => (err ? reject(err) : resolve(topic))); }); } } exports.AlexaStatusMessage = AlexaStatusMessage;