KNX support for Garage Door Opener

The garage door opener device MUST adhere to HomeKit numeric
conventions, see KNX.md documentation
This commit is contained in:
Snowdd1
2015-09-19 15:19:11 +02:00
parent 91f6ccb2d4
commit 387e7ec9ce
2 changed files with 134 additions and 27 deletions

View File

@@ -322,6 +322,21 @@ KNXDevice.prototype = {
this.knxwrite(callback, gaddress,'DPT5',numericValue); this.knxwrite(callback, gaddress,'DPT5',numericValue);
} }
}, },
setInt: function(value, callback, context, gaddress) {
if (context === 'fromKNXBus') {
this.log("event ping pong, exit!");
if (callback) {
callback();
}
} else {
var numericValue = 0;
if (value && value>=0 && value<=255) {
numericValue = value; // assure 1..255 for KNX bus
}
this.log("Setting "+gaddress+" int to %s (%s)", value, numericValue);
this.knxwrite(callback, gaddress,'DPT5',numericValue);
}
},
setFloat: function(value, callback, context, gaddress) { setFloat: function(value, callback, context, gaddress) {
if (context === 'fromKNXBus') { if (context === 'fromKNXBus') {
this.log(gaddress + " event ping pong, exit!"); this.log(gaddress + " event ping pong, exit!");
@@ -406,6 +421,11 @@ KNXDevice.prototype = {
this.setFloat(value, callback, context, config.Set); this.setFloat(value, callback, context, config.Set);
}.bind(this)); }.bind(this));
break; break;
case "Int":
myCharacteristic.on('set', function(value, callback, context) {
this.setInt(value, callback, context, config.Set);
}.bind(this));
break;
case "HVAC": case "HVAC":
myCharacteristic.on('set', function(value, callback, context) { myCharacteristic.on('set', function(value, callback, context) {
this.setHVACState(value, callback, context, config.Set); this.setHVACState(value, callback, context, config.Set);
@@ -432,6 +452,10 @@ KNXDevice.prototype = {
case "Float": case "Float":
this.knxregister_float([config.Set].concat(config.Listen || []), myCharacteristic); this.knxregister_float([config.Set].concat(config.Listen || []), myCharacteristic);
break; break;
case "Int":
// use float as return type for ints, for we don't care
this.knxregister_float([config.Set].concat(config.Listen || []), myCharacteristic);
break;
case "HVAC": case "HVAC":
this.knxregister_HVAC([config.Set].concat(config.Listen || []), myCharacteristic); this.knxregister_HVAC([config.Set].concat(config.Listen || []), myCharacteristic);
break; break;
@@ -498,6 +522,62 @@ KNXDevice.prototype = {
} }
return myService; return myService;
}, },
getGarageDoorOpenerService: function(config) {
// // Required Characteristics
// this.addCharacteristic(Characteristic.CurrentDoorState);
// this.addCharacteristic(Characteristic.TargetDoorState);
// this.addCharacteristic(Characteristic.ObstructionDetected);
// Characteristic.CurrentDoorState.OPEN = 0;
// Characteristic.CurrentDoorState.CLOSED = 1;
// Characteristic.CurrentDoorState.OPENING = 2;
// Characteristic.CurrentDoorState.CLOSING = 3;
// Characteristic.CurrentDoorState.STOPPED = 4;
// //
// // Optional Characteristics
// this.addOptionalCharacteristic(Characteristic.LockCurrentState);
// this.addOptionalCharacteristic(Characteristic.LockTargetState);
// The value property of LockCurrentState must be one of the following:
// Characteristic.LockCurrentState.UNSECURED = 0;
// Characteristic.LockCurrentState.SECURED = 1;
// Characteristic.LockCurrentState.JAMMED = 2;
// Characteristic.LockCurrentState.UNKNOWN = 3;
// some sanity checks
if (config.type !== "GarageDoorOpener") {
this.log("[ERROR] GarageDoorOpener Service for non 'GarageDoorOpener' service called");
return undefined;
}
if (!config.name) {
this.log("[ERROR] GarageDoorOpener Service without 'name' property called");
return undefined;
}
var myService = new Service.GarageDoorOpener(config.name,config.name);
if (config.CurrentDoorState) {
this.log("GarageDoorOpener CurrentDoorState characteristic enabled");
this.bindCharacteristic(myService, Characteristic.CurrentDoorState, "Int", config.CurrentDoorState);
}
if (config.TargetDoorState) {
this.log("GarageDoorOpener TargetDoorState characteristic enabled");
this.bindCharacteristic(myService, Characteristic.TargetDoorState, "Int", config.TargetDoorState);
}
if (config.ObstructionDetected) {
this.log("GarageDoorOpener ObstructionDetected characteristic enabled");
this.bindCharacteristic(myService, Characteristic.ObstructionDetected, "Bool", config.ObstructionDetected);
}
//optionals
if (config.LockCurrentState) {
this.log("GarageDoorOpener LockCurrentState characteristic enabled");
myService.addCharacteristic(Characteristic.LockCurrentState);
this.bindCharacteristic(myService, Characteristic.LockCurrentState, "Int", config.LockCurrentState);
}
if (config.LockTargetState) {
this.log("GarageDoorOpener LockTargetState characteristic enabled");
myService.addCharacteristic(Characteristic.LockTargetState);
this.bindCharacteristic(myService, Characteristic.LockTargetState, "Bool", config.LockTargetState);
}
return myService;
},
getLightbulbService: function(config) { getLightbulbService: function(config) {
// some sanity checks // some sanity checks
//this.config = config; //this.config = config;
@@ -657,11 +737,6 @@ KNXDevice.prototype = {
// TargetTemperature if available // TargetTemperature if available
if (config.TargetTemperature) { if (config.TargetTemperature) {
this.log("Thermostat TargetTemperature characteristic enabled"); this.log("Thermostat TargetTemperature characteristic enabled");
// DEBUG
console.log("default value: " + myService.getCharacteristic(Characteristic.TargetTemperature).value);
// DEBUG
// default boundary too narrow for thermostats // default boundary too narrow for thermostats
myService.getCharacteristic(Characteristic.TargetTemperature).minimumValue=0; // °C myService.getCharacteristic(Characteristic.TargetTemperature).minimumValue=0; // °C
myService.getCharacteristic(Characteristic.TargetTemperature).maximumValue=40; // °C myService.getCharacteristic(Characteristic.TargetTemperature).maximumValue=40; // °C
@@ -790,7 +865,7 @@ KNXDevice.prototype = {
informationService informationService
.setCharacteristic(Characteristic.Manufacturer, "Opensource Community") .setCharacteristic(Characteristic.Manufacturer, "Opensource Community")
.setCharacteristic(Characteristic.Model, "KNX Universal Device") .setCharacteristic(Characteristic.Model, "KNX Universal Device")
.setCharacteristic(Characteristic.SerialNumber, "Version 1.1"); .setCharacteristic(Characteristic.SerialNumber, "Version 1.1.2");
accessoryServices.push(informationService); accessoryServices.push(informationService);
@@ -814,6 +889,9 @@ KNXDevice.prototype = {
case "ContactSensor": case "ContactSensor":
accessoryServices.push(this.getContactSenserService(configService)); accessoryServices.push(this.getContactSenserService(configService));
break; break;
case "GarageDoorOpener":
accessoryServices.push(this.getGarageDoorOpenerService(configService));
break;
case "Lightbulb": case "Lightbulb":
accessoryServices.push(this.getLightbulbService(configService)); accessoryServices.push(this.getLightbulbService(configService));
break; break;

View File

@@ -71,47 +71,76 @@ Two kinds of addresses are supported: `"Set":"1/2/3"` is a writable group addres
# Supported Services and their characteristics # Supported Services and their characteristics
## ContactSensor ## ContactSensor
- ContactSensorState: DPT 1, 0 as contact **OR** - ContactSensorState: DPT 1.002, 0 as contact **OR**
- ContactSensorStateContact1: DPT 1, 1 as contact - ContactSensorStateContact1: DPT 1.002, 1 as contact
- StatusActive: DPT 1.011, 1 as true
- StatusFault: DPT 1.011, 1 as true
- StatusTampered: DPT 1.011, 1 as true
- StatusLowBattery: DPT 1.011, 1 as true
## GarageDoorOpener
- CurrentDoorState: DPT5 integer value in range 0..4
// Characteristic.CurrentDoorState.OPEN = 0;
// Characteristic.CurrentDoorState.CLOSED = 1;
// Characteristic.CurrentDoorState.OPENING = 2;
// Characteristic.CurrentDoorState.CLOSING = 3;
// Characteristic.CurrentDoorState.STOPPED = 4;
- TargetDoorState: DPT5 integer value in range 0..1
// Characteristic.TargetDoorState.OPEN = 0;
// Characteristic.TargetDoorState.CLOSED = 1;
- ObstructionDetected: DPT1, 1 as true
- LockCurrentState: DPT5 integer value in range 0..3
// Characteristic.LockCurrentState.UNSECURED = 0;
// Characteristic.LockCurrentState.SECURED = 1;
// Characteristic.LockCurrentState.JAMMED = 2;
// Characteristic.LockCurrentState.UNKNOWN = 3;
- LockTargetState: DPT5 integer value in range 0..1
// Characteristic.LockTargetState.UNSECURED = 0;
// Characteristic.LockTargetState.SECURED = 1;
- StatusActive: DPT 1, 1 as true
- StatusFault: DPT 1, 1 as true
- StatusTampered: DPT 1, 1 as true
- StatusLowBattery: DPT 1, 1 as true
## Lightbulb ## Lightbulb
- On: DPT 1, 1 as on, 0 as off - On: DPT 1.001, 1 as on, 0 as off
- Brightness: DPT5 percentage, 100% (=255) the brightest - Brightness: DPT5.001 percentage, 100% (=255) the brightest
## LightSensor ## LightSensor
- CurrentAmbientLightLevel: DPT 9, 0 to 100000 Lux - CurrentAmbientLightLevel: DPT 9.004, 0 to 100000 Lux
## LockMechanism ## LockMechanism (This is poorly mapped!)
- LockCurrentState: DPT 1, 1 as secured **OR (but not both:)** - LockCurrentState: DPT 1, 1 as secured **OR (but not both:)**
- LockCurrentStateSecured0: DPT 1, 0 as secured - LockCurrentStateSecured0: DPT 1, 0 as secured
- LockTargetState: DPT 1, 1 as secured **OR** - LockTargetState: DPT 1, 1 as secured **OR**
- LockTargetStateSecured0: DPT 1, 0 as secured - LockTargetStateSecured0: DPT 1, 0 as secured
*ToDo here: correction of mappings, HomeKit reqires lock states UNSECURED=0, SECURED=1, JAMMED = 2, UNKNOWN=3*
## Outlet ## Outlet
- On: DPT 1, 1 as on, 0 as off - On: DPT 1.001, 1 as on, 0 as off
- OutletInUse: DPT 1, 1 as on, 0 as off - OutletInUse: DPT 1.011, 1 as on, 0 as off
## Switch ## Switch
- On: DPT 1, 1 as on, 0 as off - On: DPT 1.001, 1 as on, 0 as off
## TemperatureSensor ## TemperatureSensor
- CurrentTemperature: DPT9 in °C [listen only] - CurrentTemperature: DPT9.001 in °C [listen only]
## Thermostat ## Thermostat
- CurrentTemperature: DPT9 in °C [listen only] - CurrentTemperature: DPT9.001 in °C [listen only]
- TargetTemperature: DPT9, values 0..40°C only, all others are ignored - TargetTemperature: DPT9.001, values 0..40°C only, all others are ignored
- CurrentHeatingCoolingState: DPT5 HVAC, because of the incompatible mapping only off and heating (=auto) are shown, [listen only] - CurrentHeatingCoolingState: DPT20.102 HVAC, because of the incompatible mapping only off and heating (=auto) are shown, [listen only]
- TargetHeatingCoolingState: as above - TargetHeatingCoolingState: DPT20.102 HVAC, as above
## Window ## Window
- CurrentPosition: DPT5 percentage - CurrentPosition: DPT5.001 percentage
- TargetPosition: DPT5 percentage - TargetPosition: DPT5.001 percentage
- PositionState: DPT5 value [listen only] - PositionState: DPT5.005 value [listen only: 0 Increasing, 1 Decreasing, 2 Stopped]
## WindowCovering ## WindowCovering
- CurrentPosition: DPT5 percentage - CurrentPosition: DPT5 percentage