UNPKG

homebridge-edomoticz

Version:

homebridge-plugin for Domoticz https://github.com/nfarina/homebridge

301 lines (266 loc) 14.3 kB
// ____ _ _ // ___| _ \ ___ _ __ ___ ___ | |_(_) ___ ____ // / _ | | | |/ _ \| '_ ` _ \ / _ \| __| |/ __|_ / // | __| |_| | (_) | | | | | | (_) | |_| | (__ / / // \___|____/ \___/|_| |_| |_|\___/ \__|_|\___/___| // www.npmjs.com/package/homebridge-edomoticz // // A Platform Plugin for HomeBridge by Marci & TheRamon // [http://twitter.com/marcisshadow] // [http://domoticz.com/forum/memberlist.php?mode=viewprofile&u=10884] // var Domoticz = require('./lib/domoticz.js').Domoticz; var Mqtt = require('./lib/mqtt.js').Mqtt; var eDomoticzAccessory = require('./lib/domoticz_accessory.js'); var Constants = require('./lib/constants.js'); var Helper = require('./lib/helper.js').Helper; var eDomoticzServices = require('./lib/services.js').eDomoticzServices; const util = require('util'); module.exports = function(homebridge) { Service = homebridge.hap.Service; Characteristic = homebridge.hap.Characteristic; Categories = homebridge.hap.Accessory.Categories; Types = homebridge.hapLegacyTypes; UUID = homebridge.hap.uuid; util.inherits(eDomoticzServices.TotalConsumption, Characteristic); util.inherits(eDomoticzServices.CurrentConsumption, Characteristic); util.inherits(eDomoticzServices.GasConsumption, Characteristic); util.inherits(eDomoticzServices.TempOverride, Characteristic); util.inherits(eDomoticzServices.MeterDeviceService, Service); util.inherits(eDomoticzServices.GasDeviceService, Service); util.inherits(eDomoticzServices.Ampere, Characteristic); util.inherits(eDomoticzServices.AMPDeviceService, Service); util.inherits(eDomoticzServices.Volt, Characteristic); util.inherits(eDomoticzServices.VOLTDeviceService, Service); util.inherits(eDomoticzServices.CurrentUsage, Characteristic); util.inherits(eDomoticzServices.UsageDeviceService, Service); util.inherits(eDomoticzServices.TodayConsumption, Characteristic); util.inherits(eDomoticzServices.Barometer, Characteristic); util.inherits(eDomoticzServices.WaterFlow, Characteristic); util.inherits(eDomoticzServices.TotalWaterFlow, Characteristic); util.inherits(eDomoticzServices.WaterDeviceService, Service); util.inherits(eDomoticzServices.WeatherService, Service); util.inherits(eDomoticzServices.WindSpeed, Characteristic); util.inherits(eDomoticzServices.WindChill, Characteristic); util.inherits(eDomoticzServices.WindDirection, Characteristic); util.inherits(eDomoticzServices.WindDeviceService, Service); util.inherits(eDomoticzServices.Rainfall, Characteristic); util.inherits(eDomoticzServices.RainDeviceService, Service); util.inherits(eDomoticzServices.Visibility, Characteristic); util.inherits(eDomoticzServices.VisibilityDeviceService, Service); util.inherits(eDomoticzServices.SolRad, Characteristic); util.inherits(eDomoticzServices.SolRadDeviceService, Service); util.inherits(eDomoticzServices.LocationService, Service); util.inherits(eDomoticzServices.Location, Characteristic); util.inherits(eDomoticzServices.InfotextDeviceService, Service); util.inherits(eDomoticzServices.Infotext, Characteristic); util.inherits(eDomoticzServices.UVDeviceService, Service); util.inherits(eDomoticzServices.UVIndex, Characteristic); //homebridge.registerAccessory("homebridge-edomoticz", "eDomoticz", eDomoticzAccessory); homebridge.registerPlatform("homebridge-edomoticz", "eDomoticz", eDomoticzPlatform, true); }; function eDomoticzPlatform(log, config, api) { this.isSynchronizingAccessories = false; this.accessories = []; this.forceLog = log; this.log = function() { if (typeof process.env.DEBUG !== 'undefined') { log(util.format.apply(this, arguments)); } }; this.config = config; try { this.server = config.server; this.authorizationToken = false; if (this.server.indexOf(":") > -1 && this.server.indexOf("@") > -1) { var tmparr = this.server.split("@"); this.authorizationToken = Helper.Base64.encode(tmparr[0]); this.server = tmparr[1]; } this.ssl = (config.ssl == 1); this.port = config.port; this.webroot = config.webroot; this.room = config.roomid; this.api = api; this.apiBaseURL = "http" + (this.ssl ? "s" : "") + "://" + this.server + ":" + this.port + ((this.webroot === undefined) ? "" : "/" + this.webroot ) + "/json.htm?"; this.mqtt = false; } catch (e) { this.forceLog(e); return; } var requestHeaders = {}; if (this.authorizationToken) { requestHeaders['Authorization'] = 'Basic ' + this.authorizationToken; } Domoticz.initialize(this.ssl, requestHeaders); if (this.api) { this.api.once("didFinishLaunching", function() { var syncDevices = function() { this.synchronizeAccessories(); setTimeout(syncDevices.bind(this), 600000); // Sync devices every 10 minutes }.bind(this); syncDevices(); if (config.mqtt) { setupMqttConnection(this); } }.bind(this)); } } eDomoticzPlatform.prototype = { synchronizeAccessories: function() { if (this.isSynchronizingAccessories) { return; } this.isSynchronizingAccessories = true; this.forceLog('synchronizeAccessories in progress...'); var excludedDevices = (typeof this.config.excludedDevices !== 'undefined') ? this.config.excludedDevices : []; Domoticz.devices(this.apiBaseURL, this.room, function(devices) { var removedAccessories = [], externalAccessories = []; for (var i = 0; i < devices.length; i++) { var device = devices[i], exclude = !1; if (!(excludedDevices.indexOf(device.idx) <= -1)) { exclude = !0; this.log(device.Name + ' (idx:' + device.idx + ') excluded via config array'); } if (device.Image == undefined) { device.Image = 'Switch'; } var existingAccessory = this.accessories.find(function(existingAccessory) { return existingAccessory.idx == device.idx; }); if (existingAccessory) { if ((device.SwitchTypeVal > 0 && device.SwitchTypeVal !== existingAccessory.swTypeVal) || exclude == !0) { if (exclude == !1) { this.forceLog("Device " + existingAccessory.name + " has changed it's type. Recreating..."); } else { this.forceLog("Device " + existingAccessory.name + " has been excluded. Removing..."); } removedAccessories.push(existingAccessory); try { this.api.unregisterPlatformAccessories("homebridge-edomoticz", "eDomoticz", [existingAccessory.platformAccessory]); } catch (e) { this.forceLog("Could not unregister platform accessory! (" + existingAccessory.name + ")\n" + e); } } else { continue; } } if (exclude == !1) { // Generate a new accessory var uuid = UUID.generate(device.idx + "_" + device.Name); this.forceLog("Device: " + device.Name + " (" + device.idx + ")"); var accessory = new eDomoticzAccessory(this, false, false, device.Used, device.idx, device.Name, uuid, device.HaveDimmer, device.MaxDimLevel, device.SubType, device.Type, device.BatteryLevel, device.SwitchType, device.SwitchTypeVal, device.HardwareID, device.HardwareTypeVal, device.Image, this.eve, device.HaveTimeout, device.Description); this.accessories.push(accessory); // Register the accessories try { accessory.platformAccessory.context = { device: device, uuid: uuid, eve: this.eve }; if ((device.SwitchTypeVal == Constants.DeviceTypeMedia) || (device.SwitchTypeVal == Constants.DeviceTypeSelector && device.Image == "TV")) { externalAccessories.push(accessory); } else { this.api.registerPlatformAccessories("homebridge-edomoticz", "eDomoticz", [accessory.platformAccessory]); } } catch (e) { this.forceLog("Could not register platform accessory! (" + accessory.name + ")\n" + e); } } } // Publish external (ie: TV) accessories now that they're fully assembled for (var ei = 0; ei < externalAccessories.length; ei++) { var externalAccessory = externalAccessories[ei]; if (externalAccessory.subType !== 'Selector Switch') { this.api.publishExternalAccessories("homebridge-edomoticz", [externalAccessory.platformAccessory]); this.forceLog("External Device: " + externalAccessory.platformAccessory.context.device.Name + " (" + externalAccessory.platformAccessory.context.device.idx + ")"); } } // Remove the old accessories for (var i = 0; i < this.accessories.length; i++) { var removedAccessory = this.accessories[i]; var existingDevice = devices.find(function(existingDevice) { return existingDevice.idx == removedAccessory.idx; }); if (!existingDevice) { removedAccessories.push(removedAccessory); try { this.api.unregisterPlatformAccessories("homebridge-edomoticz", "eDomoticz", [removedAccessory.platformAccessory]); } catch (e) { this.forceLog("Could not unregister platform accessory! (" + removedAccessory.name + ")\n" + e); } } } for (var i = 0; i < removedAccessories.length; i++) { var removedAccessory = removedAccessories[i]; removedAccessory.removed(); var index = this.accessories.indexOf(removedAccessory); this.accessories.splice(index, 1); } this.isSynchronizingAccessories = false; }.bind(this), function(response, err) { Helper.LogConnectionError(this, response, err); this.isSynchronizingAccessories = false; }.bind(this)); }, configureAccessory: function(platformAccessory) { if (!platformAccessory.context || !platformAccessory.context.device) { // Remove this invalid device from the cache. try { this.api.unregisterPlatformAccessories("homebridge-edomoticz", "eDomoticz", [platformAccessory]); } catch (e) { this.forceLog("Could not unregister cached platform accessory!\n" + e); } return; } var device = platformAccessory.context.device; var uuid = platformAccessory.context.uuid; var eve = platformAccessory.context.eve; // Generate the already cached accessory again var accessory = new eDomoticzAccessory(this, platformAccessory, false, device.Used, device.idx, device.Name, uuid, device.HaveDimmer, device.MaxDimLevel, device.SubType, device.Type, device.BatteryLevel, device.SwitchType, device.SwitchTypeVal, device.HardwareID, device.HardwareTypeVal, device.Image, eve, device.HaveTimeout, device.Description); this.accessories.push(accessory); } }; function setupMqttConnection(platform) { var connectionInformation = { host: (typeof platform.config.mqtt.host !== 'undefined' ? platform.config.mqtt.host : '127.0.0.1'), port: (typeof platform.config.mqtt.port !== 'undefined' ? platform.config.mqtt.port : 1883), topic: (typeof platform.config.mqtt.topic !== 'undefined' ? platform.config.mqtt.topic : 'domoticz/out'), username: (typeof platform.config.mqtt.username !== 'undefined' ? platform.config.mqtt.username : ''), password: (typeof platform.config.mqtt.password !== 'undefined' ? platform.config.mqtt.password : ''), }; var mqttError = function() { platform.forceLog("There was an error while getting the MQTT Hardware Device from Domoticz.\nPlease verify that you have added the MQTT Hardware Device and that the hardware device is enabled."); }; Domoticz.hardware(platform.apiBaseURL, function(hardware) { var mqttHardware = false; for (var i = 0; i < hardware.length; i++) { if (hardware[i].Type == Constants.HardwareTypeMQTT) { mqttHardware = hardware[i]; break; } } if (mqttHardware === false || (mqttHardware.Enabled != "true")) { mqttError(); return; } if (typeof platform.config.mqtt.host === 'undefined') { connectionInformation.host = mqttHardware.Address; } if (typeof platform.config.mqtt.port === 'undefined') { connectionInformation.port = mqttHardware.Port; } if (typeof platform.config.mqtt.username === 'undefined') { connectionInformation.username = mqttHardware.Username; } if (typeof platform.config.mqtt.password === 'undefined') { connectionInformation.password = mqttHardware.Password; } platform.mqtt = new Mqtt(platform, connectionInformation.host, connectionInformation.port, connectionInformation.topic, { username: connectionInformation.username, password: connectionInformation.password }); }, mqttError); }