diff --git a/README.md b/README.md index f7a7801..4e65772 100755 --- a/README.md +++ b/README.md @@ -26,6 +26,7 @@ This is a plugin for [Homebridge](https://github.com/nfarina/homebridge) and [Ho - Lock Mechanisms (inverted) - Temperature sensors (only temperature characteristic in case of T+H / T+H+B) - Thermostat SetPoints +- TV ## Provides: @@ -123,12 +124,6 @@ The dimFix variable relates to an early issue between HomeKit and Domoticz regar
Advanced Configuration -### Dim Offset -The dimFix variable relates to an early issue between HomeKit and Domoticz regarding scaling of dimmer values. If you find that you can never set your dimmers to 100%, then set this variable to 1. If you find that, when you set your dimmers, this starts a never ending loop of brightness increasing by 1%, then you MUST omit this variable or set it to 0. - -### Use legacy blind support -If you use blinds, set this option to 1 if you use an older version of domoticz (until 2022-beta.14535). If using a more recent version, set to 0. When set to 0, the new reverse state and position will be used - ### MQTT By default, the plugin will grab hardware information regarding MQTT from Domoticz if `mqtt` is 1 or true in the configuration file. Advanced users can override their MQTT configuration as follows: diff --git a/config.schema.json b/config.schema.json index e36e17a..7163b49 100644 --- a/config.schema.json +++ b/config.schema.json @@ -26,6 +26,12 @@ "default": "8080", "required": true }, + "webroot": { + "title": "Webroot", + "type": "string", + "default": "", + "required": false + }, "roomid": { "title": "Room ID", "type": "integer", @@ -74,6 +80,7 @@ "items": [ "server", "port", + "webroot", "roomid" ] }, { diff --git a/index.js b/index.js index 9d2032d..0c88f80 100755 --- a/index.js +++ b/index.js @@ -9,31 +9,6 @@ // [http://twitter.com/marcisshadow] // [http://domoticz.com/forum/memberlist.php?mode=viewprofile&u=10884] // -// ** Remember to add platform to config.json ** -// -// Example ~/.homebridge/config.json content: -// -// { -// "bridge": { -// "name": "Homebridge", -// "username": "CC:21:3E:E4:DE:33", // << Randomize this... -// "port": 51826, -// "pin": "031-45-154", -// }, -// -// "platforms": [{ -// "platform": "eDomoticz", -// "name": "eDomoticz", -// "server": "127.0.0.1", // or "user:pass@ip" -// "port": "8080", -// "roomid": 0 , // 0 = all sensors, otherwise, room idx as shown at http://server:port/#/Roomplan -// "ssl": 0, -// "mqtt": true -// }], -// -// "accessories":[] -// } -// var Domoticz = require('./lib/domoticz.js').Domoticz; var Mqtt = require('./lib/mqtt.js').Mqtt; var eDomoticzAccessory = require('./lib/domoticz_accessory.js'); @@ -45,43 +20,44 @@ 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; - Helper.fixInheritance(eDomoticzServices.TotalConsumption, Characteristic); - Helper.fixInheritance(eDomoticzServices.CurrentConsumption, Characteristic); - Helper.fixInheritance(eDomoticzServices.GasConsumption, Characteristic); - Helper.fixInheritance(eDomoticzServices.TempOverride, Characteristic); - Helper.fixInheritance(eDomoticzServices.MeterDeviceService, Service); - Helper.fixInheritance(eDomoticzServices.GasDeviceService, Service); - Helper.fixInheritance(eDomoticzServices.Ampere, Characteristic); - Helper.fixInheritance(eDomoticzServices.AMPDeviceService, Service); - Helper.fixInheritance(eDomoticzServices.Volt, Characteristic); - Helper.fixInheritance(eDomoticzServices.VOLTDeviceService, Service); - Helper.fixInheritance(eDomoticzServices.CurrentUsage, Characteristic); - Helper.fixInheritance(eDomoticzServices.UsageDeviceService, Service); - Helper.fixInheritance(eDomoticzServices.TodayConsumption, Characteristic); - Helper.fixInheritance(eDomoticzServices.Barometer, Characteristic); - Helper.fixInheritance(eDomoticzServices.WaterFlow, Characteristic); - Helper.fixInheritance(eDomoticzServices.TotalWaterFlow, Characteristic); - Helper.fixInheritance(eDomoticzServices.WaterDeviceService, Service); - Helper.fixInheritance(eDomoticzServices.WeatherService, Service); - Helper.fixInheritance(eDomoticzServices.WindSpeed, Characteristic); - Helper.fixInheritance(eDomoticzServices.WindChill, Characteristic); - Helper.fixInheritance(eDomoticzServices.WindDirection, Characteristic); - Helper.fixInheritance(eDomoticzServices.WindDeviceService, Service); - Helper.fixInheritance(eDomoticzServices.Rainfall, Characteristic); - Helper.fixInheritance(eDomoticzServices.RainDeviceService, Service); - Helper.fixInheritance(eDomoticzServices.Visibility, Characteristic); - Helper.fixInheritance(eDomoticzServices.VisibilityDeviceService, Service); - Helper.fixInheritance(eDomoticzServices.SolRad, Characteristic); - Helper.fixInheritance(eDomoticzServices.SolRadDeviceService, Service); - Helper.fixInheritance(eDomoticzServices.LocationService, Service); - Helper.fixInheritance(eDomoticzServices.Location, Characteristic); - Helper.fixInheritance(eDomoticzServices.InfotextDeviceService, Service); - Helper.fixInheritance(eDomoticzServices.Infotext, Characteristic); - Helper.fixInheritance(eDomoticzServices.UVDeviceService, Service); - Helper.fixInheritance(eDomoticzServices.UVIndex, Characteristic); + 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); @@ -109,9 +85,10 @@ function eDomoticzPlatform(log, config, api) { 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 + "/json.htm?"; + 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); @@ -149,20 +126,19 @@ eDomoticzPlatform.prototype = { var excludedDevices = (typeof this.config.excludedDevices !== 'undefined') ? this.config.excludedDevices : []; Domoticz.devices(this.apiBaseURL, this.room, function(devices) { - var removedAccessories = []; + 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.forceLog(device.Name + ' (idx:' + device.idx + ') excluded via config array'); - //continue; + this.log(device.Name + ' (idx:' + device.idx + ') excluded via config array'); } if (device.Image == undefined) { device.Image = 'Switch'; - //this.forceLog(device.Name); } var existingAccessory = this.accessories.find(function(existingAccessory) { @@ -191,20 +167,35 @@ eDomoticzPlatform.prototype = { // 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); + 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 { - this.api.registerPlatformAccessories("homebridge-edomoticz", "eDomoticz", [accessory.platformAccessory]); + 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); } - accessory.platformAccessory.context = { - device: device, - uuid: uuid, - eve: this.eve - }; + + } + } + // 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 + ")"); } } @@ -231,7 +222,6 @@ eDomoticzPlatform.prototype = { var index = this.accessories.indexOf(removedAccessory); this.accessories.splice(index, 1); } - this.isSynchronizingAccessories = false; }.bind(this), function(response, err) { Helper.LogConnectionError(this, response, err); @@ -254,7 +244,7 @@ eDomoticzPlatform.prototype = { 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); + 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); } }; diff --git a/lib/constants.js b/lib/constants.js index e3307d1..c20ac83 100755 --- a/lib/constants.js +++ b/lib/constants.js @@ -1,5 +1,6 @@ global.Service; global.Characteristic; +global.Categories; global.Types; global.UUID; @@ -18,7 +19,7 @@ module.exports = { DeviceTypeBlindsVenetianUS: 14, DeviceTypeBlindsVenetianEU: 15, DeviceTypeBlindsPercentageInverted: 16, - DeviceTypeMedia: 17, // Only supported as on/off switch at the moment. + DeviceTypeMedia: 17, DeviceTypeSelector: 18, DeviceTypeDoorLock: 19, DeviceTypeDoorLockInverted: 20, diff --git a/lib/domoticz.js b/lib/domoticz.js index 5d4e729..cb18c2b 100755 --- a/lib/domoticz.js +++ b/lib/domoticz.js @@ -48,6 +48,7 @@ Domoticz.settings = function(accessory, completion, error) { Helper.LogConnectionError(this.platform, response, err); if (typeof error !== 'undefined' && error !== false) { error(); + callback(); } } }.bind(accessory)); @@ -207,6 +208,7 @@ Domoticz.updateWithURL = function(accessory, url, completion) { } else { Helper.LogConnectionError(this.platform, response, err); + callback(); } if (typeof completion !== 'undefined' && completion !== false) { diff --git a/lib/domoticz_accessory.js b/lib/domoticz_accessory.js index 42954d2..50fd69a 100755 --- a/lib/domoticz_accessory.js +++ b/lib/domoticz_accessory.js @@ -9,7 +9,7 @@ module.exports = eDomoticzAccessory; var tvAccessories = {}; var tvInputAccessories = {}; -function eDomoticzAccessory(platform, platformAccessory, IsScene, status, idx, name, uuid, haveDimmer, maxDimLevel, subType, Type, batteryRef, swType, swTypeVal, hwId, hwType, image, eve, hwtimeout) { +function eDomoticzAccessory(platform, platformAccessory, IsScene, status, idx, name, uuid, haveDimmer, maxDimLevel, subType, Type, batteryRef, swType, swTypeVal, hwId, hwType, image, eve, hwtimeout, descript) { if ((haveDimmer) || (swType == "Dimmer")) { if ((hwType !== 51) && (swType !== "On/Off")) { @@ -53,6 +53,7 @@ function eDomoticzAccessory(platform, platformAccessory, IsScene, status, idx, n this.cachedValues = {}; this.hwId = hwId; this.hwType = hwType; + this.descript = descript; this.powerOnBySetLevelTime = 0; // Initialize default values, e.g. to get the "factor" @@ -84,6 +85,9 @@ function eDomoticzAccessory(platform, platformAccessory, IsScene, status, idx, n this.platformAccessory = new platform.api.platformAccessory(this.name, uuid); } this.platformAccessory.reachable = true; + if (this.swTypeVal == Constants.DeviceTypeMedia) { + this.platformAccessory.category = Categories.TELEVISION; + } this.publishServices(); } @@ -154,7 +158,7 @@ eDomoticzAccessory.prototype = { return service.addCharacteristic(new characteristicType()); }, - setPowerState: function (powerOn, callback, context) { + setPowerState: function (powerOn, callback, context) { if (context && context == "eDomoticz-MQTT" || (this.cachedValues[Characteristic.On.UUID] == powerOn && powerOn) // Prevents message loop while dimming lights. || (this.powerOnBySetLevelTime > 0 && (performance.now() - this.powerOnBySetLevelTime) < 500 && powerOn) // Ignore a power ON right after a setlevel to allow turning ON a light using a dimmer. @@ -172,7 +176,7 @@ eDomoticzAccessory.prototype = { callback(); }.bind(this)); }, - getPowerState: function (callback) { + getPowerState: function (callback) { var cachedValue = this.cachedValues[Characteristic.On.UUID]; if (typeof cachedValue !== 'undefined') { callback(null, cachedValue); @@ -188,7 +192,7 @@ eDomoticzAccessory.prototype = { value = (s.Status == "Off") ? false : true; } }.bind(this)); - + if (typeof cachedValue === 'undefined') { callback(null, value); } @@ -221,7 +225,7 @@ eDomoticzAccessory.prototype = { sArray.map(function (s) { value = (s.Status == "Off") ? false : true; }.bind(this)); - + if (typeof cachedValue === 'undefined') { callback(null, value); } @@ -451,7 +455,7 @@ eDomoticzAccessory.prototype = { value = (value == 0) ? 0.0001 : value; } else if (this.subType == "Waterflow" || (this.name.indexOf("Gas") > -1 && this.Type == "General" && this.subType == "kWh")) { value = Helper.cleanFloat(s.Data); -} else if (this.subType == "RFXMeter counter" || this.subType == "Percentage" || this.subType == "kWh" || this.subType == "Energy" || this.subType == "Solar Radiation" || this.subType == "UVN800" || this.subType == "UVN128,UV138" || this.subType == "Visibility") { + } else if (this.subType == "RFXMeter counter" || this.subType == "Percentage" || this.subType == "kWh" || this.subType == "Energy" || this.subType == "Solar Radiation" || this.subType == "UVN800" || this.subType == "UVN128,UV138" || this.subType == "Visibility") { value = (s.Counter !== undefined) ? Helper.cleanFloat(s.Counter) : Helper.cleanFloat(s.Data); } else if (this.subType == "Text") { value = s.Data.toString(); @@ -735,11 +739,8 @@ eDomoticzAccessory.prototype = { }); return; } - if (this.platform.config.legacyBlinds == 1) { - var command = (shouldOpen ? "On" : "Off"); - } else { - var command = (shouldOpen ? "Close" : "Open"); - } + + var command = (shouldOpen ? "On" : "Off"); Domoticz.updateDeviceStatus(this, "switchlight", { "switchcmd": command }, function (success) { @@ -986,9 +987,9 @@ eDomoticzAccessory.prototype = { callback(); return; } - - if (this.hwId.toString() in tvInputAccessories) { - Domoticz.updateDeviceStatus(tvInputAccessories[this.hwId.toString()], "switchlight", { + + if (this.descript in tvInputAccessories) { + Domoticz.updateDeviceStatus(tvInputAccessories[this.descript], "switchlight", { "switchcmd": "Set Level", "level": identifier * 10 }, function (success) { @@ -1003,8 +1004,8 @@ eDomoticzAccessory.prototype = { callback(null, cachedValue); } - if (this.hwId.toString() in tvInputAccessories) { - Domoticz.deviceStatus(tvInputAccessories[this.hwId.toString()], function (json) { + if (this.descript in tvInputAccessories) { + Domoticz.deviceStatus(tvInputAccessories[this.descript], function (json) { var value = 0; var sArray = Helper.sortByKey(json.result, "Name"); sArray.map(function (s) { @@ -1020,7 +1021,7 @@ eDomoticzAccessory.prototype = { } else if (typeof cachedValue === 'undefined') { this.cachedValues[Characteristic.ActiveIdentifier.UUID] = 0; callback(null, 0); - } + } }, handleMQTTMessage: function (message, callback) { this.platform.log("MQTT Message received for %s.\nName:\t\t%s\nDevice:\t\t%s,%s\nIs Switch:\t%s\nSwitchTypeVal:\t%s\nMQTT Message:\n%s", this.name, this.name, this.Type, this.subType, this.isSwitch, this.swTypeVal, JSON.stringify(message, null, 4)); @@ -1034,7 +1035,7 @@ eDomoticzAccessory.prototype = { if (this.isSwitch) { switch (true) { case this.swTypeVal == Constants.DeviceTypeSwitch || this.swTypeVal == Constants.DeviceTypePushOn: - { + { var service = false; if (this.image !== undefined && this.swTypeVal !== Constants.DeviceTypePushOn) { if (this.image.indexOf("Fan") > -1) { @@ -1167,7 +1168,7 @@ eDomoticzAccessory.prototype = { callback(characteristic, Characteristic.ProgrammableSwitchEvent.SINGLE_PRESS); break; } - case this.swTypeVal == Constants.DeviceTypeSelector && this.image != "TV": + case this.swTypeVal == Constants.DeviceTypeSelector && this.image !== "TV": { var service = this.getService(Service.StatelessProgrammableSwitch); var characteristic = this.getCharacteristic(service, Characteristic.ProgrammableSwitchEvent); @@ -1188,16 +1189,21 @@ eDomoticzAccessory.prototype = { } case this.swTypeVal == Constants.DeviceTypeSelector && this.image == "TV": { - var tvAccessory = tvAccessories[this.hwId.toString()]; - var tvService = tvAccessory.getService(Service.Television); - var characteristic = tvAccessory.getCharacteristic(tvService, Characteristic.ActiveIdentifier); - var identifier = parseInt(message.svalue1) / 10; - var oldIdentifier = tvAccessory.cachedValues[Characteristic.ActiveIdentifier.UUID]; - - if (identifier != oldIdentifier) { - tvAccessory.cachedValues[Characteristic.ActiveIdentifier.UUID] = identifier; - callback(characteristic, identifier); + var tvAccessory = tvAccessories[this.descript]; + if (typeof tvAccessory !== undefined) { + var tvService = tvAccessory.getService(Service.Television); + var characteristic = tvAccessory.getCharacteristic(tvService, Characteristic.ActiveIdentifier); + var identifier = parseInt(message.svalue1) / 10; + var oldIdentifier = tvAccessory.cachedValues[Characteristic.ActiveIdentifier.UUID]; + + if (identifier != oldIdentifier) { + tvAccessory.cachedValues[Characteristic.ActiveIdentifier.UUID] = identifier; + callback(characteristic, identifier); + } + } else { + callback(); } + } break; case this.swTypeVal == Constants.DeviceTypeDoorLock: @@ -1318,6 +1324,7 @@ eDomoticzAccessory.prototype = { } } } + var lastActivity = false; if (this.cachedValues["lastActivity"]) { lastActivity = this.cachedValues["lastActivity"]; @@ -1354,29 +1361,36 @@ eDomoticzAccessory.prototype = { case this.swTypeVal == Constants.DeviceTypeSecuritySystem: { var systemState = Characteristic.SecuritySystemCurrentState.STAY_ARM; + var targetState = Characteristic.SecuritySystemTargetState.STAY_ARM; switch (message.nvalue) { case 0: //Disarm case 1: //Normal Delay case 13: //Disarm systemState = Characteristic.SecuritySystemCurrentState.DISARMED; + targetState = Characteristic.SecuritySystemTargetState.DISARM; break; case 9: //Arm Away case 10: //Arm Away Delayed systemState = Characteristic.SecuritySystemCurrentState.AWAY_ARM; + targetState = Characteristic.SecuritySystemTargetState.AWAY_ARM; break; case 11: //Arm Home case 12: //Arm Home Delayed systemState = Characteristic.SecuritySystemCurrentState.STAY_ARM; + targetState = Characteristic.SecuritySystemTargetState.STAY_ARM; break; case 6: systemState = Characteristic.SecuritySystemCurrentState.ALARM_TRIGGERED; + targetState = Characteristic.SecuritySystemTargetState.STAY_ARM; break; default: - case 2: //Alarm + case 2: + systemState = Characteristic.SecuritySystemCurrentState.ALARM_TRIGGERED; + targetState = Characteristic.SecuritySystemTargetState.STAY_ARM; + break; case 3: //Alarm Delayed case 4: //Motion case 5: //No Motion - case 6: //Panic case 7: //Panic End case 8: } @@ -1386,7 +1400,7 @@ eDomoticzAccessory.prototype = { var currentStateCharacteristic = this.getCharacteristic(service, Characteristic.SecuritySystemCurrentState); var targetStateCharacteristic = this.getCharacteristic(service, Characteristic.SecuritySystemTargetState); callback(currentStateCharacteristic, systemState); - callback(targetStateCharacteristic, systemState); + callback(targetStateCharacteristic, targetState); break; } @@ -1760,12 +1774,7 @@ eDomoticzAccessory.prototype = { this.gracefullyAddCharacteristic(service, Characteristic.Hue).on('set', this.setHueValue.bind(this, 'Hue')).on('get', this.getHueValue.bind(this, 'Hue')); this.gracefullyAddCharacteristic(service, Characteristic.Saturation).on('set', this.setHueValue.bind(this, 'Saturation')).on('get', this.getHueValue.bind(this, 'Saturation')); } else if (this.subType == 'WW') { - //var col = (this.Color == "" || typeof this.Color === undefined) ? !1 : !0; - //if (col == !0) { - this.gracefullyAddCharacteristic(service, Characteristic.ColorTemperature).on('set', this.setColorTempValue.bind(this, 'ColorTemperature')).on('get', this.getColorTempValue.bind(this, 'ColorTemperature')); - //} else { - // this.platform.forceLog(this.name +' claims to be a WW light but provides no Color object. Treating as plain old Dimmer.'); - //} + this.gracefullyAddCharacteristic(service, Characteristic.ColorTemperature).on('set', this.setColorTempValue.bind(this, 'ColorTemperature')).on('get', this.getColorTempValue.bind(this, 'ColorTemperature')); } } this.services.push(service); @@ -1807,8 +1816,8 @@ eDomoticzAccessory.prototype = { this.getCharacteristic(tvService, Characteristic.RemoteKey) .on('set', this.sendTelevisionRemoteKey.bind(this)); this.services.push(tvService); - tvAccessories[this.hwId.toString()] = this; - + tvAccessories[this.descript] = this; + // TV volume. var tvSpeakerService = this.getService(Service.TelevisionSpeaker); if (!tvSpeakerService) { @@ -1823,19 +1832,19 @@ eDomoticzAccessory.prototype = { .on('get', this.getTelevisionMuteState.bind(this)); tvService.addLinkedService(tvSpeakerService); this.services.push(tvSpeakerService); - - if (this.hwId.toString() in tvInputAccessories) { - this.createTvInputService(tvInputAccessories[this.hwId.toString()]); - } - + + if (this.descript in tvInputAccessories) { + this.createTvInputService(tvInputAccessories[this.descript]); + } + break; } case this.swTypeVal == Constants.DeviceTypeSelector && this.image == "TV": { - tvInputAccessories[this.hwId.toString()] = this; + tvInputAccessories[this.descript] = this; - if (this.hwId.toString() in tvAccessories) { - tvAccessories[this.hwId.toString()].createTvInputService(this); + if (this.descript in tvAccessories) { + tvAccessories[this.descript].createTvInputService(this); } break; @@ -2269,58 +2278,59 @@ eDomoticzAccessory.prototype = { }, createTvInputService: function (domoticzInputSourceAccessory) { var tvService = this.services[1]; - - Domoticz.deviceStatus(domoticzInputSourceAccessory, function (json) { - var sArray = Helper.sortByKey(json.result, "Name"); - sArray.map(function (s) { - var inputs = new Buffer(s.LevelNames, 'base64').toString("utf8").split("|"); - if(inputs.length > 0 && inputs[0] == "Off") { - inputs.shift(); - } - - inputs.forEach((input, index) => { - var inputType; - switch (true) { - case input.match(/^TV|Live$/i): - inputType = Characteristic.InputSourceType.TUNER; - break; - case input.match(/hdmi/i): - inputType = Characteristic.InputSourceType.HDMI; - break; - case input.match(/ypbpr/i): - inputType = Characteristic.InputSourceType.COMPONENT_VIDEO; - break; - default: - inputType = Characteristic.InputSourceType.APPLICATION; - break; + if (typeof tvService !== undefined) { + Domoticz.deviceStatus(domoticzInputSourceAccessory, function (json) { + var sArray = Helper.sortByKey(json.result, "Name"); + sArray.map(function (s) { + var inputs = new Buffer(s.LevelNames, 'base64').toString("utf8").split("|"); + if (inputs.length > 0 && inputs[0] == "Off") { + inputs.shift(); } - var inputService = this.getService(Service.InputSource, input); - if (!inputService) { - inputService = new Service.InputSource(input.replace(/\s/g, '').toLowerCase(), input); - } - inputService - .setCharacteristic(Characteristic.Identifier, index + 1) - .setCharacteristic(Characteristic.ConfiguredName, input) - .setCharacteristic(Characteristic.IsConfigured, Characteristic.IsConfigured.CONFIGURED) - .setCharacteristic(Characteristic.InputSourceType, inputType) - .setCharacteristic(Characteristic.CurrentVisibilityState, Characteristic.CurrentVisibilityState.SHOWN); - tvService.addLinkedService(inputService); - this.services.push(inputService); + inputs.forEach((input, index) => { + var inputType; + switch (true) { + case input.match(/^TV|Live$/i): + inputType = Characteristic.InputSourceType.TUNER; + break; + case input.match(/hdmi/i): + inputType = Characteristic.InputSourceType.HDMI; + break; + case input.match(/ypbpr/i): + inputType = Characteristic.InputSourceType.COMPONENT_VIDEO; + break; + default: + inputType = Characteristic.InputSourceType.APPLICATION; + break; + } - if(this.published) { - this.publishService(inputService); - } - }); + var inputService = this.getService(Service.InputSource, input); + if (!inputService) { + inputService = new Service.InputSource(input.replace(/\s/g, '').toLowerCase(), input); + } + inputService + .setCharacteristic(Characteristic.Identifier, index + 1) + .setCharacteristic(Characteristic.ConfiguredName, input) + .setCharacteristic(Characteristic.IsConfigured, Characteristic.IsConfigured.CONFIGURED) + .setCharacteristic(Characteristic.InputSourceType, inputType) + .setCharacteristic(Characteristic.CurrentVisibilityState, Characteristic.CurrentVisibilityState.SHOWN); + tvService.addLinkedService(inputService); + this.services.push(inputService); + + if(this.published) { + this.publishService(inputService); + } + }); + }.bind(this)); }.bind(this)); - }.bind(this)); + } }, removed: function() { // This accessory has been removed. - if (this.hwId.toString() in tvAccessories) { - delete tvAccessories[this.hwId.toString()]; + if (this.descript in tvAccessories) { + delete tvAccessories[this.descript]; } - if (this.hwId.toString() in tvInputAccessories) { - delete tvInputAccessories[this.hwId.toString()]; + if (this.descript in tvInputAccessories) { + delete tvInputAccessories[this.descript]; } } }; diff --git a/lib/services.js b/lib/services.js index c41c9a5..79ed035 100755 --- a/lib/services.js +++ b/lib/services.js @@ -20,6 +20,7 @@ eDomoticzServices.TotalConsumption = function() { unit: 'kWh' }); this.value = this.getDefaultValue(); + this.UUID = charUUID; }; eDomoticzServices.TodayConsumption = function() { var charUUID = UUID.generate('eDomoticz:customchar:TodayConsumption'); @@ -30,6 +31,7 @@ eDomoticzServices.TodayConsumption = function() { unit: 'kWh' }); this.value = this.getDefaultValue(); + this.UUID = charUUID; }; eDomoticzServices.CurrentConsumption = function() { var charUUID = 'E863F10D-079E-48FF-8F27-9C2605A29F52'; //UUID.generate('eDomoticz:customchar:CurrentConsumption'); @@ -40,6 +42,7 @@ eDomoticzServices.CurrentConsumption = function() { unit: 'W' }); this.value = this.getDefaultValue(); + this.UUID = charUUID; }; eDomoticzServices.Ampere = function() { var charUUID = 'E863F126-079E-48FF-8F27-9C2605A29F52'; //AMPERE @@ -50,6 +53,7 @@ eDomoticzServices.Ampere = function() { unit: 'A' }); this.value = this.getDefaultValue(); + this.UUID = charUUID; }; eDomoticzServices.Volt = function() { var charUUID = 'E863F10A-079E-48FF-8F27-9C2605A29F52'; //VOLT @@ -60,6 +64,7 @@ eDomoticzServices.Volt = function() { unit: 'V' }); this.value = this.getDefaultValue(); + this.UUID = charUUID; }; eDomoticzServices.GasConsumption = function() { var charUUID = UUID.generate('eDomoticz:customchar:CurrentConsumption'); @@ -69,6 +74,7 @@ eDomoticzServices.GasConsumption = function() { perms: [Characteristic.Perms.READ, Characteristic.Perms.NOTIFY] }); this.value = this.getDefaultValue(); + this.UUID = charUUID; }; eDomoticzServices.WaterFlow = function() { var charUUID = UUID.generate('eDomoticz:customchar:WaterFlow'); @@ -79,6 +85,7 @@ eDomoticzServices.WaterFlow = function() { unit: 'm3' }); this.value = this.getDefaultValue(); + this.UUID = charUUID; }; eDomoticzServices.TotalWaterFlow = function() { var charUUID = UUID.generate('eDomoticz:customchar:TotalWaterFlow'); @@ -89,6 +96,7 @@ eDomoticzServices.TotalWaterFlow = function() { unit: 'l' }); this.value = this.getDefaultValue(); + this.UUID = charUUID; }; // Custom SetPoint Minutes characteristic for TempOverride modes eDomoticzServices.TempOverride = function() { @@ -103,6 +111,7 @@ eDomoticzServices.TempOverride = function() { perms: [Characteristic.Perms.READ, Characteristic.Perms.WRITE, Characteristic.Perms.NOTIFY] }); this.value = this.getDefaultValue(); + this.UUID = charUUID; }; // Ampere Meter eDomoticzServices.AMPDeviceService = function(displayName, subtype) { @@ -152,6 +161,7 @@ eDomoticzServices.CurrentUsage = function() { minStep:0.1 }); this.value = this.getDefaultValue(); + this.UUID = charUUID; }; // The Usage Meter itself eDomoticzServices.UsageDeviceService = function(displayName, subtype) { @@ -168,6 +178,7 @@ eDomoticzServices.Location = function() { perms: [Characteristic.Perms.READ, Characteristic.Perms.NOTIFY] }); this.value = this.getDefaultValue(); + this.UUID = charUUID; }; eDomoticzServices.LocationService = function(displayName, subtype) { var serviceUUID = UUID.generate('eDomoticz:location:customservice'); @@ -187,6 +198,7 @@ eDomoticzServices.WindSpeed = function() { minStep:0.1 }); this.value = this.getDefaultValue(); + this.UUID = charUUID; }; // DarkSkies WindChill Characteristic eDomoticzServices.WindChill = function() { @@ -201,6 +213,7 @@ eDomoticzServices.WindChill = function() { minStep:0.1 }); this.value = this.getDefaultValue(); + this.UUID = charUUID; }; // DarkSkies WindDirection Characteristic eDomoticzServices.WindDirection = function() { @@ -215,6 +228,7 @@ eDomoticzServices.WindDirection = function() { minStep:1 }); this.value = this.getDefaultValue(); + this.UUID = charUUID; }; // DarkSkies Virtual Wind Sensor eDomoticzServices.WindDeviceService = function(displayName, subtype) { @@ -238,6 +252,7 @@ eDomoticzServices.Rainfall = function() { minStep:0.1 }); this.value = this.getDefaultValue(); + this.UUID = charUUID; }; // DarkSkies Rain Meter itself eDomoticzServices.RainDeviceService = function(displayName, subtype) { @@ -258,6 +273,7 @@ eDomoticzServices.Visibility = function() { minStep:0.1 }); this.value = this.getDefaultValue(); + this.UUID = charUUID; }; // DarkSkies Visibility Meter itself eDomoticzServices.VisibilityDeviceService = function(displayName, subtype) { @@ -278,6 +294,7 @@ eDomoticzServices.UVIndex = function() { minStep:0.1 }); this.value = this.getDefaultValue(); + this.UUID = charUUID; }; // DarkSkies UV Index Meter itself @@ -299,6 +316,7 @@ eDomoticzServices.SolRad = function() { minStep:0.1 }); this.value = this.getDefaultValue(); + this.UUID = charUUID; }; // DarkSkies Solar Radiation Meter itself eDomoticzServices.SolRadDeviceService = function(displayName, subtype) { @@ -319,6 +337,7 @@ eDomoticzServices.Barometer = function() { minStep: 0.1 }); this.value = this.getDefaultValue(); + this.UUID = charUUID; }; // Weather Service eDomoticzServices.WeatherService = function(displayName, subtype) { @@ -337,6 +356,7 @@ eDomoticzServices.Infotext = function() { perms: [Characteristic.Perms.READ, Characteristic.Perms.NOTIFY] }); this.value = this.getDefaultValue(); + this.UUID = charUUID; }; // DarkSkies Visibility Meter itself eDomoticzServices.InfotextDeviceService = function(displayName, subtype) { diff --git a/package.json b/package.json index 0c85b02..2aace34 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "homebridge-edomoticz", - "version": "2.1.39", + "version": "2.1.40", "description": "homebridge-plugin for Domoticz https://github.com/nfarina/homebridge", "main": "index.js", "scripts": {