Skip to content

Commit

Permalink
Merge pull request #17 from SphtKr/qubino-roller-shutter
Browse files Browse the repository at this point in the history
1st attempt at %-based WindowCovering control
  • Loading branch information
SphtKr committed Mar 15, 2016
2 parents 569b1b1 + f0c65d9 commit 49c2850
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 8 deletions.
9 changes: 7 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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:

Expand Down Expand Up @@ -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.
Expand Down
35 changes: 30 additions & 5 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,7 @@ ZWayServerPlatform.prototype = {
var primaryDeviceClasses = [
"doorlock",
"thermostat",
"switchMultilevel.blind",
"switchMultilevel",
"switchBinary",
"sensorBinary.Door/Window",
Expand Down Expand Up @@ -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"){
Expand Down Expand Up @@ -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"];
Expand Down Expand Up @@ -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);
Expand All @@ -1044,19 +1055,33 @@ 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);
cx.on('get', function(callback, context){
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;
};
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -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": {
Expand Down

0 comments on commit 49c2850

Please sign in to comment.