UNPKG

homebridge-ifttt

Version:

Homebridge plugin for IFTTT Maker Channel

242 lines 11.3 kB
'use strict'; Object.defineProperty(exports, "__esModule", { value: true }); const module_1 = require("module"); let Service, Characteristic, HomebridgeAPI; const superagent = require("superagent"); const storage = require("node-persist"); module.exports = function (homebridge) { Service = homebridge.hap.Service; Characteristic = homebridge.hap.Characteristic; HomebridgeAPI = homebridge; homebridge.registerPlatform('homebridge-ifttt', 'IFTTT', IFTTTPlatform); }; class IFTTTPlatform { constructor(log, config, api) { this.log = log; this.api = api; this.makerkey = config['makerkey']; this.IFTTTaccessories = config['accessories']; } accessories(callback) { this.log('Loading accessories...', ''); // eslint-disable-next-line @typescript-eslint/no-this-alias const that = this; const foundAccessories = []; if (!this.IFTTTaccessories || this.IFTTTaccessories.length === 0) { callback(foundAccessories); return; } this.cacheDirectory = HomebridgeAPI.user.persistPath(); storage.init({ dir: this.cacheDirectory, forgiveParseErrors: true }); const subtypes = []; function generateSubtype(button) { function valuesToString(values) { return JSON.stringify(values) ? JSON.stringify(values).replace(/\W/g, '') : null; } let result = (button.trigger || button.triggerOn + button.triggerOff) + (button.values ? '-v' + valuesToString(button.values) : '') + (button.valuesOn ? '-vOn' + valuesToString(button.valuesOn) : '') + (button.valuesOff ? '-vOff' + valuesToString(button.valuesOff) : ''); const duplicateSubtype = subtypes.find((subtype) => subtype.indexOf(result) === 0); if (duplicateSubtype) { let num = duplicateSubtype.replace(/^.*___(\d+)$/, '$1'); num = parseInt(num === result ? '1' : num); result += '___' + (num + 1); } subtypes.unshift(result); return result; } this.IFTTTaccessories.map((s) => { this.log('Found: ', s.name); let accessory = null; if (s.buttons.length !== 0) { const services = s.buttons.map((button) => { const service = { controlService: new Service.Switch(button.caption), characteristics: [Characteristic.On], }; service.controlService.subtype = generateSubtype(button); service.controlService.trigger = button.trigger; service.controlService.triggerOn = button.triggerOn; service.controlService.triggerOff = button.triggerOff; service.controlService.values = button.values; service.controlService.valuesOn = button.valuesOn; service.controlService.valuesOff = button.valuesOff; service.controlService.delayOn = button.delayOn; service.controlService.delayOff = button.delayOff; service.controlService.stateful = button.stateful; // Read saved state and set initial if (service.controlService.stateful) { const cachedState = storage.getItemSync(service.controlService.displayName); service.controlService.onoffstate = !(cachedState === undefined || cachedState === false); this.log('Loading service: ', service.controlService.displayName + ', subtype: ' + service.controlService.subtype + ', RestoredState: ' + service.controlService.onoffstate); } else { service.controlService.onoffstate = false; this.log('Loading service: ', service.controlService.displayName + ', subtype: ' + service.controlService.subtype); } return service; }); accessory = new IFTTTAccessory(services); } if (accessory) { accessory.getServices = function () { return that.getServices(accessory); }; accessory.platform = this; accessory.remoteAccessory = s; accessory.name = s.name; accessory.model = 'IFTTT'; accessory.manufacturer = 'IFTTT'; accessory.serialNumber = '<unknown>'; foundAccessories.push(accessory); } }); callback(foundAccessories); } async command(trigger, homebridgeAccessory) { const url = 'https://maker.ifttt.com/trigger/' + trigger.eventName + '/with/key/' + this.makerkey; try { await superagent .post(url) .send(trigger.values || {}) .set('Content-type', 'application/json'); homebridgeAccessory.platform.log(homebridgeAccessory.name + ' sent command ' + trigger.eventName); homebridgeAccessory.platform.log(url); if (trigger.values) { homebridgeAccessory.platform.log(trigger.values); } } catch (err) { homebridgeAccessory.platform.log('There was a problem sending command ' + trigger.eventName + ' to ' + homebridgeAccessory.name); } } getInformationService(homebridgeAccessory) { const informationService = new Service.AccessoryInformation(); informationService .setCharacteristic(Characteristic.Name, homebridgeAccessory.name) .setCharacteristic(Characteristic.Manufacturer, homebridgeAccessory.manufacturer) .setCharacteristic(Characteristic.Model, homebridgeAccessory.model) .setCharacteristic(Characteristic.SerialNumber, homebridgeAccessory.serialNumber); return informationService; } bindCharacteristicEvents(characteristic, service, homebridgeAccessory) { characteristic.on('set', (value, callback, context) => { if (context !== 'fromSetValue') { let eventName; let values; const trigger = { eventName, values }; if (service.controlService.trigger) { trigger.eventName = service.controlService.trigger; if (service.controlService.values) { trigger.values = service.controlService.values; } else if (value === 0) { trigger.values = service.controlService.valuesOff; } else if (value === 1) { trigger.values = service.controlService.valuesOn; } } else if (value === false) { trigger.eventName = service.controlService.triggerOff; service.controlService.onoffstate = false; if (service.controlService.valuesOff) { trigger.values = service.controlService.valuesOff; } else if (service.controlService.values) { trigger.values = service.controlService.values; } } else { trigger.eventName = service.controlService.triggerOn; service.controlService.onoffstate = true; if (service.controlService.valuesOn) { trigger.values = service.controlService.valuesOn; } else if (service.controlService.values) { trigger.values = service.controlService.values; } } const delayOn = service.controlService.delayOn; const delayOff = service.controlService.delayOff; if (shouldDelayCommand(value, delayOn, delayOff)) { homebridgeAccessory.platform.log(trigger.eventName + ' scheduled to run in ' + getDelay(value, delayOn, delayOff) / 1000 + ' seconds.'); setTimeout(() => { homebridgeAccessory.platform.command(trigger, homebridgeAccessory); }, getDelay(value, delayOn, delayOff)); } else { homebridgeAccessory.platform.command(trigger, homebridgeAccessory); } if (service.controlService.trigger && !service.controlService.valuesOn && !service.controlService.valuesOff) { // In order to behave like a push button reset the status to off setTimeout(() => { characteristic.setValue(false, undefined, 'fromSetValue'); }, 100); } // Save state if (service.controlService.stateful) { storage.setItemSync(service.controlService.displayName, value); } } callback(); }, module_1.bind(this)); characteristic.on('get', (callback) => { if (service.controlService.trigger) { // a push button is normally off callback(undefined, false); } else { callback(undefined, service.controlService.onoffstate); } }, module_1.bind(this)); } getServices(homebridgeAccessory) { const services = []; const informationService = homebridgeAccessory.platform.getInformationService(homebridgeAccessory); services.push(informationService); for (let s = 0; s < homebridgeAccessory.services.length; s++) { const service = homebridgeAccessory.services[s]; for (let i = 0; i < service.characteristics.length; i++) { let characteristic = service.controlService.getCharacteristic(service.characteristics[i]); if (!characteristic) { characteristic = service.controlService.addCharacteristic(service.characteristics[i]); } homebridgeAccessory.platform.bindCharacteristicEvents(characteristic, service, homebridgeAccessory); } services.push(service.controlService); } return services; } } class IFTTTAccessory { constructor(services) { this.services = services; } } function shouldDelayCommand(value, delayOn, delayOff) { if (value === 1 || value === true) { return delayOn; } else if (value === 0 || value === false) { return delayOff; } } function getDelay(value, delayOn, delayOff) { const multiplier = 1000; if (value === 1 && delayOn) { return delayOn * multiplier; } else if (value === 0 && delayOff) { return delayOff * multiplier; } return 0; } //# sourceMappingURL=index.js.map