UNPKG

homebridge-hatch-baby-rest

Version:
117 lines (116 loc) 4.49 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.IotDevice = exports.MAX_IOT_VALUE = void 0; exports.convertFromPercentage = convertFromPercentage; exports.convertToPercentage = convertToPercentage; const rxjs_1 = require("rxjs"); const operators_1 = require("rxjs/operators"); const util_1 = require("../shared/util"); function assignState(previousState, changes) { const state = Object.assign({}, previousState); for (const key in changes) { if (typeof changes[key] === 'object') { state[key] = assignState(previousState[key] || {}, changes[key]); } else { state[key] = changes[key]; } } return state; } exports.MAX_IOT_VALUE = 65535; function convertFromPercentage(percentage) { return Math.ceil((percentage / 100) * exports.MAX_IOT_VALUE); } function convertToPercentage(value) { return Math.floor((value * 100) / exports.MAX_IOT_VALUE); } class IotDevice { get mqttClient() { return this.onIotClient.getValue(); } get id() { return this.info.id; } get name() { return this.info.name; } get macAddress() { return this.info.macAddress; } constructor(info, onIotClient) { this.info = info; this.onIotClient = onIotClient; this.onCurrentState = new rxjs_1.BehaviorSubject(null); this.onStatusToken = new rxjs_1.Subject(); this.previousUpdatePromise = Promise.resolve(); this.onState = this.onCurrentState.pipe((0, operators_1.filter)((state) => state !== null)); onIotClient .pipe((0, rxjs_1.skip)(1)) .subscribe((client) => this.registerMqttClient(client)); this.registerMqttClient(onIotClient.getValue()); } registerMqttClient(mqttClient) { const { thingName } = this.info; let getClientToken; mqttClient.on('status', (topic, message, clientToken, status) => { if (topic !== thingName) { // status for a different thing return; } this.onStatusToken.next(clientToken); if (clientToken === getClientToken) { const { state } = status; this.onCurrentState.next(assignState(state.reported, state.desired)); } }); mqttClient.on('foreignStateChange', (topic, message, s) => { const currentState = this.onCurrentState.getValue(); if (!currentState || topic !== thingName) { return; } this.onCurrentState.next(assignState(assignState(currentState, s.state.reported), s.state.desired)); }); this.previousUpdatePromise = this.previousUpdatePromise .catch((_) => { // ignore errors, they shouldn't be possible void _; }) .then(() => new Promise((resolve) => { mqttClient.on('connect', () => { mqttClient.register(thingName, {}, () => { getClientToken = mqttClient.get(thingName); resolve((0, rxjs_1.firstValueFrom)(this.onStatusToken.pipe((0, operators_1.filter)((token) => token === getClientToken)))); }); }); })); } getCurrentState() { return (0, rxjs_1.firstValueFrom)(this.onState); } update(update) { this.previousUpdatePromise = this.previousUpdatePromise .catch((_) => { // ignore errors, they shouldn't be possible void _; }) .then(() => { if (!this.mqttClient) { (0, util_1.logError)(`Unable to Update ${this.name} - No MQTT Client Registered`); return; } const updateToken = this.mqttClient.update(this.info.thingName, { state: { desired: update, }, }); if (!updateToken) { (0, util_1.logError)(`Failed to apply update to ${this.name} because another update was in progress: ${JSON.stringify(update)}`); } const requestComplete = (0, rxjs_1.firstValueFrom)(this.onStatusToken.pipe((0, operators_1.filter)((token) => token === updateToken))); // wait a max of 30 seconds to finish request return Promise.race([requestComplete, (0, util_1.delay)(30000)]); }); } } exports.IotDevice = IotDevice;