diff --git a/README.md b/README.md index 1165d82..a6a996c 100644 --- a/README.md +++ b/README.md @@ -41,8 +41,9 @@ Generally speaking, the following types of devices will work: * Door/window sensors * Light sensors (needs work) * Motion sensors -* :tada: :new: Door Locks (e.g. Danalock) -* :tada: :new: Relative Humidity sensors (e.g. Aeon Labs Multisensor 6...needs testing!) +* Door Locks (e.g. Danalock) +* Relative Humidity sensors (e.g. Aeon Labs Multisensor 6...needs testing!) +* :tada: :new: Window Coverings Additional devices in progress: @@ -154,6 +155,10 @@ There is not really a direct analogue to a `Door/Window` sensor in HomeKit--the b. You don't get any iOS notifications for state changes, so pick this if you find those annoying. But, you won't be able to ask Siri about the state of the "Door", and app support for this characteristic has been historically lacking (Eve works great now). Also note that you can invert the value with `Homebridge.ContactSensorState.Invert`, which may result in a more intuitive value being shown. +##### Dimmer or other `switchMultilevel` as `WindowCovering` + +If you have a shutter/drapery control that uses a percentage value for open/closed, but is not automatically recognized as such (for instance it is instead shown as a light dimmer), you can specify `Homebridge.Service.Type:WindowCovering` to force it to be recognized correctly. This should not be necessary in most cases. + ##### More There will be additional devices and use cases where this will be used. If you think you have a good use case for this that is not supported by the current code, please submit an issue with the guidelines above. diff --git a/index.js b/index.js index 6533696..5474639 100644 --- a/index.js +++ b/index.js @@ -201,6 +201,7 @@ ZWayServerPlatform.prototype = { var primaryDeviceClasses = [ "doorlock", "thermostat", + "switchMultilevel.blind", "switchMultilevel", "switchBinary", "sensorBinary.Door/Window", @@ -458,10 +459,15 @@ if(!vdev) debug("ERROR: vdev passed to getVDevServices is undefined!"); case "switchMultilevel": if(this.platform.getTagValue(vdev, "Service.Type") === "Switch"){ services.push(new Service.Switch(vdev.metrics.title, vdev.id)); + } else if(this.platform.getTagValue(vdev, "Service.Type") === "WindowCovering"){ + services.push(new Service.WindowCovering(vdev.metrics.title, vdev.id)); } else { services.push(new Service.Lightbulb(vdev.metrics.title, vdev.id)); } break; + case "switchMultilevel.blind": + services.push(new Service.WindowCovering(vdev.metrics.title, vdev.id)); + break; case "sensorBinary.Door/Window": var stype = this.platform.getTagValue(vdev, "Service.Type"); if(stype === "ContactSensor"){ @@ -540,9 +546,9 @@ if(!vdev) debug("ERROR: vdev passed to getVDevServices is undefined!"); map[(new Characteristic.CurrentDoorState).UUID] = ["sensorBinary.Door/Window","sensorBinary"]; map[(new Characteristic.TargetDoorState).UUID] = ["sensorBinary.Door/Window","sensorBinary"]; //TODO: Always a fixed result map[(new Characteristic.ContactSensorState).UUID] = ["sensorBinary","sensorBinary.Door/Window"]; - map[(new Characteristic.CurrentPosition).UUID] = ["sensorBinary.Door/Window","sensorBinary"]; - map[(new Characteristic.TargetPosition).UUID] = ["sensorBinary.Door/Window","sensorBinary"]; - map[(new Characteristic.PositionState).UUID] = ["sensorBinary.Door/Window","sensorBinary"]; + map[(new Characteristic.CurrentPosition).UUID] = ["sensorBinary.Door/Window","switchMultilevel.blind","sensorBinary","switchMultilevel"]; + map[(new Characteristic.TargetPosition).UUID] = ["sensorBinary.Door/Window","switchMultilevel.blind","sensorBinary","switchMultilevel"]; + map[(new Characteristic.PositionState).UUID] = ["sensorBinary.Door/Window","switchMultilevel.blind","sensorBinary","switchMultilevel"]; map[(new Characteristic.ObstructionDetected).UUID] = ["sensorBinary.Door/Window","sensorBinary"]; //TODO: Always a fixed result map[(new Characteristic.BatteryLevel).UUID] = ["battery.Battery"]; map[(new Characteristic.StatusLowBattery).UUID] = ["battery.Battery"]; @@ -1027,6 +1033,11 @@ if(!vdev) debug("ERROR: vdev passed to getVDevServices is undefined!"); if(cx instanceof Characteristic.CurrentPosition){ cx.zway_getValueFromVDev = function(vdev){ + if(service instanceof Service.WindowCovering){ + var level = vdev.metrics.level; + return level == 99 ? 100 : level; + } + // Door sensor/sensorBinary return vdev.metrics.level === "off" ? 0 : 100 ; }; cx.value = cx.zway_getValueFromVDev(vdev); @@ -1044,8 +1055,12 @@ if(!vdev) debug("ERROR: vdev passed to getVDevServices is undefined!"); } if(cx instanceof Characteristic.TargetPosition){ - //TODO: Currently only Door sensors, so always return 0. cx.zway_getValueFromVDev = function(vdev){ + if(service instanceof Service.WindowCovering){ + var level = vdev.metrics.level; + return level == 99 ? 100 : level; + } + // Door sensor, so fixed value... return 0; }; cx.value = cx.zway_getValueFromVDev(vdev); @@ -1053,10 +1068,20 @@ if(!vdev) debug("ERROR: vdev passed to getVDevServices is undefined!"); debug("Getting value for " + vdev.metrics.title + ", characteristic \"" + cx.displayName + "\"..."); callback(false, cx.zway_getValueFromVDev(vdev)); }); + cx.on('set', function(level, callback){ + this.command(vdev, "exact", {level: parseInt(level, 10)}).then(function(result){ + //debug("Got value: " + result.data.metrics.level + ", for " + vdev.metrics.title + "."); + callback(false, cx.zway_getValueFromVDev(result.data)); + }); + }.bind(this)); + cx.setProps({ + minValue: vdev.metrics && vdev.metrics.min !== undefined ? vdev.metrics.min : 0, + maxValue: vdev.metrics && (vdev.metrics.max !== undefined || vdev.metrics.max != 99) ? vdev.metrics.max : 100 + }); } if(cx instanceof Characteristic.PositionState){ - //TODO: Currently only Door sensors, so always return STOPPED. + // Always return STOPPED, we don't really get status updates from Z-Way... cx.zway_getValueFromVDev = function(vdev){ return Characteristic.PositionState.STOPPED; }; diff --git a/package.json b/package.json index 40849bc..e301c67 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "homebridge-zway", - "version": "0.4.0", + "version": "0.5.0-alpha0", "description": "homebridge-plugin for ZWay Server and RaZBerry", "main": "index.js", "scripts": {