From af79ea4fbf5b172cdf0f076307da91e0b37fdd55 Mon Sep 17 00:00:00 2001 From: S'pht'Kr Date: Wed, 7 Oct 2015 05:38:24 +0200 Subject: [PATCH 1/2] Beginning tag support enhancements Generalized tag recognition, tags are now `Homebridge.*` instead of `Homebridge:*`, initial attempt at `IsPrimary` but probably not working right yet. --- platforms/ZWayServer.js | 49 +++++++++++++++++++++++++++++++++++------ 1 file changed, 42 insertions(+), 7 deletions(-) diff --git a/platforms/ZWayServer.js b/platforms/ZWayServer.js index 730eb9b..f21f39b 100644 --- a/platforms/ZWayServer.js +++ b/platforms/ZWayServer.js @@ -83,7 +83,20 @@ ZWayServerPlatform.prototype = { return deferred.promise; } , - + getTagValue: function(vdev, tagStem){ + if(!(vdev.tags && vdev.tags.length > 0)) return false; + var tagStem = "Homebridge." + tagStem; + if(vdev.tags.indexOf(tagStem) >= 0) return true; + var tags = vdev.tags, l = tags.length, tag; + for(var i = 0; i < l; i++){ + tag = tags[i]; + if(tag.indexOf(tagStem + ":") === 0){ + return tag.substr(tagStem.length + 1); + } + } + return false; + } + , accessories: function(callback) { debug("Fetching Z-Way devices..."); @@ -110,12 +123,24 @@ ZWayServerPlatform.prototype = { var groupedDevices = {}; for(var i = 0; i < devices.length; i++){ var vdev = devices[i]; - if(vdev.tags.indexOf("Homebridge:Skip") >= 0) { debug("Tag says skip!"); continue; } - if(this.opt_in && vdev.tags.indexOf("Homebridge:Include") < 0) continue; + if(this.getTagValue("Skip")) { debug("Tag says skip!"); continue; } + if(this.opt_in && !this.getTagValue(vdev, "Include")) continue; var gdid = vdev.id.replace(/^(.*?)_zway_(\d+-\d+)-\d.*/, '$1_$2'); var gd = groupedDevices[gdid] || (groupedDevices[gdid] = {devices: [], types: {}, extras: {}, primary: undefined}); gd.devices.push(vdev); var tk = ZWayServerPlatform.getVDevTypeKey(vdev); + + // If this is explicitly set as primary, set it now... + if(this.getTagValue("IsPrimary")){ + gd.primary = gd.devices.length - 1; + if(gd.types[tk] !== undefined){ + // everybody out of the way! + gd.extras[tk] = gd.extras[tk] || []; + gd.extras[tk].push(gd.types[tk]); + } + gd.types[tk] = gd.primary; + } + if(gd.types[tk] === undefined){ gd.types[tk] = gd.devices.length - 1; } else { @@ -136,12 +161,17 @@ ZWayServerPlatform.prototype = { } var accessory = null; - for(var ti = 0; ti < primaryDeviceClasses.length; ti++){ + if(gd.primary !== undefined){ + var pd = gd.devices[gd.primary]; + var name = pd.metrics && pd.metrics.title ? pd.metrics.title : pd.id; + accessory = new ZWayServerAccessory(name, gd, that); + } + else for(var ti = 0; ti < primaryDeviceClasses.length; ti++){ if(gd.types[primaryDeviceClasses[ti]] !== undefined){ gd.primary = gd.types[primaryDeviceClasses[ti]]; var pd = gd.devices[gd.primary]; var name = pd.metrics && pd.metrics.title ? pd.metrics.title : pd.id; - debug("Using primary device with type " + primaryDeviceClasses[ti] + ", " + name + " (" + pd.id + ") as primary."); + //debug("Using primary device with type " + primaryDeviceClasses[ti] + ", " + name + " (" + pd.id + ") as primary."); accessory = new ZWayServerAccessory(name, gd, that); break; } @@ -303,7 +333,11 @@ ZWayServerAccessory.prototype = { services.push(new Service.Switch(vdev.metrics.title, vdev.id)); break; case "switchMultilevel": - services.push(new Service.Lightbulb(vdev.metrics.title, vdev.id)); + if(this.platform.getTagValue(vdev, "ServiceType") === "Switch"){ + services.push(new Service.Switch(vdev.metrics.title, vdev.id)); + } else { + services.push(new Service.Lightbulb(vdev.metrics.title, vdev.id)); + } break; case "sensorBinary.Door/Window": services.push(new Service.GarageDoorOpener(vdev.metrics.title, vdev.id)); @@ -778,7 +812,8 @@ ZWayServerAccessory.prototype = { // Any extra switchMultilevels? Could be a RGBW+W bulb, add them as additional services... if(this.devDesc.extras["switchMultilevel"]) for(var i = 0; i < this.devDesc.extras["switchMultilevel"].length; i++){ var xvdev = this.devDesc.devices[this.devDesc.extras["switchMultilevel"][i]]; - services = services.concat(this.getVDevServices(xvdev)); + var xservice = this.getVDevServices(xvdev); + services = services.concat(xservice); } if(this.platform.splitServices){ From 25299a7863455ed83b653e3a95419e609f48314a Mon Sep 17 00:00:00 2001 From: S'pht'Kr Date: Sat, 10 Oct 2015 15:45:27 +0200 Subject: [PATCH 2/2] =?UTF-8?q?Last=20bits=E2=80=A6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- platforms/ZWayServer.js | 38 ++++++++++++++++++++++++++++---------- 1 file changed, 28 insertions(+), 10 deletions(-) diff --git a/platforms/ZWayServer.js b/platforms/ZWayServer.js index f21f39b..0b81e88 100644 --- a/platforms/ZWayServer.js +++ b/platforms/ZWayServer.js @@ -125,20 +125,26 @@ ZWayServerPlatform.prototype = { var vdev = devices[i]; if(this.getTagValue("Skip")) { debug("Tag says skip!"); continue; } if(this.opt_in && !this.getTagValue(vdev, "Include")) continue; - var gdid = vdev.id.replace(/^(.*?)_zway_(\d+-\d+)-\d.*/, '$1_$2'); + + var gdid = this.getTagValue(vdev, "Accessory.Id"); + if(!gdid){ + gdid = vdev.id.replace(/^(.*?)_zway_(\d+-\d+)-\d.*/, '$1_$2'); + } + var gd = groupedDevices[gdid] || (groupedDevices[gdid] = {devices: [], types: {}, extras: {}, primary: undefined}); gd.devices.push(vdev); var tk = ZWayServerPlatform.getVDevTypeKey(vdev); // If this is explicitly set as primary, set it now... - if(this.getTagValue("IsPrimary")){ - gd.primary = gd.devices.length - 1; + if(this.getTagValue(vdev, "IsPrimary")){ + // everybody out of the way! Can't be in "extras" if you're the primary... if(gd.types[tk] !== undefined){ - // everybody out of the way! gd.extras[tk] = gd.extras[tk] || []; gd.extras[tk].push(gd.types[tk]); + delete gd.types[tk]; // clear the way for this one to be set here below... } - gd.types[tk] = gd.primary; + gd.primary = gd.devices.length - 1; + //gd.types[tk] = gd.primary; } if(gd.types[tk] === undefined){ @@ -149,7 +155,7 @@ ZWayServerPlatform.prototype = { } if(tk !== vdev.deviceType) gd.types[vdev.deviceType] = gd.devices.length - 1; // also include the deviceType only as a possibility } - //TODO: Make a second pass, re-splitting any devices that don't make sense together + for(var gdid in groupedDevices) { if(!groupedDevices.hasOwnProperty(gdid)) continue; @@ -183,7 +189,6 @@ ZWayServerPlatform.prototype = { foundAccessories.push(accessory); } -//foundAccessories = foundAccessories.slice(0, 10); // Limit to a few devices for testing... callback(foundAccessories); // Start the polling process... @@ -332,8 +337,9 @@ ZWayServerAccessory.prototype = { case "switchBinary": services.push(new Service.Switch(vdev.metrics.title, vdev.id)); break; + case "switchRGBW": case "switchMultilevel": - if(this.platform.getTagValue(vdev, "ServiceType") === "Switch"){ + if(this.platform.getTagValue(vdev, "Service.Type") === "Switch"){ services.push(new Service.Switch(vdev.metrics.title, vdev.id)); } else { services.push(new Service.Lightbulb(vdev.metrics.title, vdev.id)); @@ -436,6 +442,12 @@ ZWayServerAccessory.prototype = { return cx; } + // We don't want to override "Name"'s name...so we just move this below that block. + var descOverride = this.platform.getTagValue(vdev, "Characteristic.Description"); + if(descOverride){ + cx.displayName = descOverride; + } + if(cx instanceof Characteristic.On){ cx.zway_getValueFromVDev = function(vdev){ var val = false; @@ -797,17 +809,23 @@ ZWayServerAccessory.prototype = { getServices: function() { var that = this; + var vdevPrimary = this.devDesc.devices[this.devDesc.primary]; + var accId = this.platform.getTagValue(vdevPrimary, "Accessory.Id"); + if(!accId){ + accId = "VDev-" + vdevPrimary.h; //FIXME: Is this valid? + } + var informationService = new Service.AccessoryInformation(); informationService .setCharacteristic(Characteristic.Name, this.name) .setCharacteristic(Characteristic.Manufacturer, "Z-Wave.me") .setCharacteristic(Characteristic.Model, "Virtual Device (VDev version 1)") - .setCharacteristic(Characteristic.SerialNumber, "VDev-" + this.devDesc.devices[this.devDesc.primary].h) //FIXME: Is this valid?); + .setCharacteristic(Characteristic.SerialNumber, accId); var services = [informationService]; - services = services.concat(this.getVDevServices(this.devDesc.devices[this.devDesc.primary])); + services = services.concat(this.getVDevServices(vdevPrimary)); // Any extra switchMultilevels? Could be a RGBW+W bulb, add them as additional services... if(this.devDesc.extras["switchMultilevel"]) for(var i = 0; i < this.devDesc.extras["switchMultilevel"].length; i++){