homebridge-knx-easy
Version:
homebridge shim for KNX home automation.
1,183 lines (876 loc) • 53.8 kB
JavaScript
/*
* This is a module to handle a Garage Door Opener that is connected to a
* KNX actuator, staircaseFunc mode can be configured, time can be configured.
* The engine will switch from Up/Stop/Down in cycle if more than
* 1 command is received during movement.
*
* This addin can operate using one or two contact sensors to detect either KNXDoorClosed
* only or both KNXDoorClosed and KNXDoorOpened.
* In the former case, the KNXDoorOpened sensor can be simulated in two ways, either
* using the KNX-Bus in between (simulateDoorContactMode == "knx") or only simulating
* the state internally (simulateDoorContactMode == "internal"), in case you don't want to
* use the KNX-Bus in between (default).
*
* The contact sensors are expected to have a value of "sensorOn" when activated. Please use the
* "sensorOn"-keyword in knx_config.json (both need to operate the same way).
*
*/
/* jshint esversion: 6, strict: true, node: true */
'use strict';
/** * @type {HandlerPattern}
*/
var HandlerPattern = require('./handlerpattern.js');
var log = require('debug')('GarageDoorOpenerAdvanced');
/**
* @class A custom handler for a Garage Door Opener conected to a KNX actuator
* @extends HandlerPattern
*/
class GarageDoorOpenerAdvanced extends HandlerPattern {
constructor(knxAPI) {
super(knxAPI); // call the super constructor first. Always.
this.timer1 = undefined;
// sets the mode to simulate a Door-contact.
// Available modes:
// - off
// - knx
// - internal
this.simulateDoorContactMode = undefined;
// configures which contacts are really present in a setup.
// if simulateDoorContactMode is set to "knx" or "internal", the other contact will be
// simulated
//
// Available modes:
// - open - if the "open"-contact is present
// - closed - if the "closed"-contact is present
// - both - if both ontacts are present - no simulation in this case
this.doorContactPresent = undefined;
// Door run-time
this.doorRunTime = undefined;
// Define the length for a pulse. This needs to be set regardless staircase-function on or off
// In case the staircase-function is used, it needs to be set to the same value (or a little more)
this.pulseLength = undefined;
// Staircase function
this.staircaseFunc = undefined;
// Does the door use separate pulses for up and down?
this.separatePulseUpDown = undefined;
// get the sensor value for "On"
this.sensorOn = undefined;
// this is used to track the percentageOpen of the door
// 100% is open, 0% is closed
this.dateRunStart = undefined;
this.percentageOpen = undefined;
// debug-name
this.debugName = undefined;
}
/****
* onKNXValueChange is invoked if a Bus value for one of the bound addresses is received
*
*/
onKNXValueChange(field, oldValue, knxValue) {
var myCurrentDoorState = this.myAPI.getValue("CurrentDoorState");
// sets the mode to simulate the DoorOpen-contact.
// Available modes:
// - off
// - knx
// - internal
// TODO: A check for valid values would be nice here.
this.simulateDoorContactMode = this.myAPI.getLocalConstant("simulateDoorContactMode");
// configures which contacts are really present in a setup.
// if simulateDoorContactMode is set to "knx" or "internal", the other contact will be
// simulated
//
// Available modes:
// - open - if the "open"-contact is present
// - closed - if the "closed"-contact is present
// - both - if both ontacts are present - no simulation in this case
this.doorContactPresent = this.myAPI.getLocalConstant("doorContactPresent");
// Door run-time
this.doorRunTime = this.myAPI.getLocalConstant("doorRunTime"); // in mil.seconds
// Define the length for a pulse. This needs to be set regardless staircase-function on or off
// In case the staircase-function is used, it needs to be set to the same value (or a little more)
this.pulseLength = this.myAPI.getLocalConstant("pulseLength");
// Staircase function
this.staircaseFunc = this.myAPI.getLocalConstant("staircaseFunc");
// Does the door use separate pulses for up and down?
this.separatePulseUpDown = this.myAPI.getLocalConstant("separatePulseUpDown");
// get the sensor value for "On"
this.sensorOn = this.myAPI.getLocalConstant("sensorOn");
// set debugName
this.debugName = this.myAPI.getLocalConstant("debugName");
// The value property of CurrentDoorState must be one of the following:
// Characteristic.CurrentDoorState.OPEN = 0;
// Characteristic.CurrentDoorState.CLOSED = 1;
// Characteristic.CurrentDoorState.OPENING = 2;
// Characteristic.CurrentDoorState.CLOSING = 3;
// Characteristic.CurrentDoorState.STOPPED = 4;
// The value property of TargetDoorState must be one of the following:
// Characteristic.TargetDoorState.OPEN = 0;
// Characteristic.TargetDoorState.CLOSED = 1;
// The value property of OccupancyDetected must be one of the following:
// Characteristic.OccupancyDetected.OCCUPANCY_NOT_DETECTED = 0;
// Characteristic.OccupancyDetected.OCCUPANCY_DETECTED = 1;
console.log('INFO ' + this.debugName + ': on KNX Value Change(' + field + ", old="+ oldValue + ", new="+ knxValue+ ")");
console.log('INFO ' + this.debugName + ': myCurrentDoorState = ' + myCurrentDoorState);
if (field === "KNXPulseMove") {
if (knxValue === 1) {
var curDate = new Date();
var percentageRun;
if (oldValue !== 1){ // value changed?
console.log('INFO ' + this.debugName + ': KNXPulseMove detected');
if (this.timer1 !== undefined){
clearTimeout(this.timer1);
this.timer1 = undefined;
console.log('INFO ' + this.debugName + ': Timer für KNXDoorOpened reset');
}
if (myCurrentDoorState === 1){ // IF DOOR IS CLOSED
// also CurrentDoorState = 1
console.log('INFO ' + this.debugName + ': CurrentDoorState = 0 CLOSED detected');
console.log('INFO ' + this.debugName + ': TargetDoorState = 0 OPEN set');
// Handling the setting here,
// -> removed this in KNXDoorOpened and KNXDoorClosed-handling
this.myAPI.setValue("TargetDoorState", 0); // OPEN
console.log('INFO ' + this.debugName + ': CurrentDoorState = 2 OPENING set');
this.myAPI.setValue("CurrentDoorState", 2); // OPENING
this.dateRunStart = new Date();
this.lastMove = "goingUp";
console.log('INFO ' + this.debugName + ': lastMove = ' + this.lastMove+ ' set');
if (this.simulateDoorContactMode==="knx" && this.doorContactPresent==="open"){
console.log('INFO ' + this.debugName + ': this.simulateDoorContactMode: ' + this.simulateDoorContactMode);
console.log('INFO ' + this.debugName + ': this.doorContactPresent: ' + this.doorContactPresent);
this.myAPI.knxWrite("KNXDoorOpened", !this.sensorOn, "DPT1"); // Door not open
}
else if (this.simulateDoorContactMode==="knx" && this.doorContactPresent==="closed"){
// simulate "open"-contact on knx
console.log('INFO ' + this.debugName + ': this.simulateDoorContactMode: ' + this.simulateDoorContactMode);
console.log('INFO ' + this.debugName + ': this.doorContactPresent: ' + this.doorContactPresent);
// simulate this even on the bus
this.myAPI.knxWrite("KNXDoorOpened", !this.sensorOn, "DPT1"); // Door not open
console.log('INFO ' + this.debugName + ': Timer für KNXDoorOpened started');
this.timer1 = setTimeout (function () {
console.log('INFO ' + this.debugName + ': Timeout, simulating Door Open');
console.log('INFO ' + this.debugName + ': KNXDoorOpened = ' + this.sensorOn + ' set');
this.myAPI.knxWrite("KNXDoorOpened", this.sensorOn, "DPT1"); // Door open
this.percentageOpen = 1;
this.dateRunStart = undefined;
}.bind(this),this.doorRunTime);
} else if (this.simulateDoorContactMode==="internal" && this.doorContactPresent==="closed"){
// simulate "open"-contact internally
console.log('INFO ' + this.debugName + ': this.simulateDoorContactMode: ' + this.simulateDoorContactMode);
console.log('INFO ' + this.debugName + ': this.doorContactPresent: ' + this.doorContactPresent);
console.log('INFO ' + this.debugName + ': Timer für KNXDoorOpened started');
this.timer1 = setTimeout (function () {
console.log('INFO ' + this.debugName + ': Timeout, simulating Door Open');
console.log('INFO ' + this.debugName + ': CurrentDoorState = 0 OPEN set');
this.myAPI.setValue("CurrentDoorState", 0); // OPEN
console.log('INFO ' + this.debugName + ': TargetDoorState = 0 OPEN set');
this.myAPI.setValue("TargetDoorState", 0); // OPEN
this.percentageOpen = 1;
this.dateRunStart = undefined;
this.lastMove = "Stopped";
console.log('INFO ' + this.debugName + ': lastMove = ' + this.lastMove+ ' set'); // Door open
}.bind(this),this.doorRunTime);
} // simulateDoorContactMode
} // ("KNXDoorClosed")===1
else if (myCurrentDoorState===2){ // IF DOOR IS OPENING
console.log('INFO ' + this.debugName + ': CurrentDoorState = 2 OPENING detected');
console.log('INFO ' + this.debugName + ': CurrentDoorState = 4 STOPPED set');
this.myAPI.setValue("CurrentDoorState", 4); // STOPPED
// calculate percentageOpen
percentageRun = (curDate.getTime() - this.dateRunStart.getTime()) / this.doorRunTime;
console.log('INFO ' + this.debugName + ': percentageRun = ' + percentageRun);
console.log('INFO ' + this.debugName + ': percentageOpen before = ' + this.percentageOpen);
// put min/max 0/1 - just to be sure
this.percentageOpen = this.percentageOpen + percentageRun;
console.log('INFO ' + this.debugName + ': percentageOpen = ' + this.percentageOpen);
if (this.percentageOpen < 0 || this.percentageOpen > 1) {
if (this.percentageOpen < 0) {
this.percentageOpen = 0;
} else {
this.percentageOpen = 1;
}
console.log('WARNING: percentageOpen out of bounds, limiting to percentageOpen = ' + this.percentageOpen);
}
// clear timer
if (this.timer1 !== undefined){
clearTimeout(this.timer1);
this.timer1 = undefined;
console.log('INFO ' + this.debugName + ': Timer für KNXDoorOpened reset');
}
} // ("CurrentDoorState")===2 //OPENING
else if (myCurrentDoorState===3){ // IF DOOR IS CLOSING
console.log('INFO ' + this.debugName + ': CurrentDoorState = 3 CLOSING detected');
console.log('INFO ' + this.debugName + ': CurrentDoorState = 4 STOPPED set');
this.myAPI.setValue("CurrentDoorState", 4); // STOPPED
// calculate percentageOpen
percentageRun = (curDate.getTime() - this.dateRunStart.getTime()) / this.doorRunTime;
console.log('INFO ' + this.debugName + ': percentageRun = ' + percentageRun);
console.log('INFO ' + this.debugName + ': percentageOpen before = ' + this.percentageOpen);
this.percentageOpen = this.percentageOpen - percentageRun;
console.log('INFO ' + this.debugName + ': percentageOpen = ' + this.percentageOpen);
if (this.percentageOpen < 0 || this.percentageOpen > 1) {
if (this.percentageOpen < 0) {
this.percentageOpen = 0;
} else {
this.percentageOpen = 1;
}
console.log('WARNING: percentageOpen out of bounds, limiting to percentageOpen = ' + this.percentageOpen);
}
// clear timer
if (this.timer1 !== undefined){
clearTimeout(this.timer1);
this.timer1 = undefined;
console.log('INFO ' + this.debugName + ': Timer für KNXDoorOpened reset');
}
} // ("CurrentDoorState")===3 //CLOSING
else if (myCurrentDoorState===4){ // IF DOOR IS STOPPED
console.log('INFO ' + this.debugName + ': CurrentDoorState = 4 STOPPED detected');
if (this.lastMove === "goingUp"){
console.log('INFO ' + this.debugName + ': TargetDoorState = 1 CLOSED set');
this.myAPI.setValue("TargetDoorState", 1); // CLOSED
console.log('INFO ' + this.debugName + ': CurrentDoorState = 3 CLOSING set');
this.myAPI.setValue("CurrentDoorState", 3); // CLOSING
this.dateRunStart = new Date();
this.lastMove = "goingDown";
console.log('INFO ' + this.debugName + ': lastMove = ' + this.lastMove+ ' set');
// simulate
if (this.simulateDoorContactMode==="knx" && this.doorContactPresent==="open"){
// simulate "open"-contact on knx
console.log('INFO ' + this.debugName + ': this.simulateDoorContactMode: ' + this.simulateDoorContactMode);
console.log('INFO ' + this.debugName + ': this.doorContactPresent: ' + this.doorContactPresent);
console.log('INFO ' + this.debugName + ': Timer für KNXDoorClosed started');
this.timer1 = setTimeout (function () {
console.log('INFO ' + this.debugName + ': Timeout, simulating Door Closed');
console.log('INFO ' + this.debugName + ': KNXDoorClosed = ' + this.sensorOn + ' set');
this.myAPI.knxWrite("KNXDoorClosed", this.sensorOn, "DPT1"); // Door open
// setting HK-state and percentage is done in KNXDoorClosed
}.bind(this),this.doorRunTime*(this.percentageOpen));
} else if (this.simulateDoorContactMode==="internal" && this.doorContactPresent==="open"){
// simulate "open"-contact internally
console.log('INFO ' + this.debugName + ': this.simulateDoorContactMode: ' + this.simulateDoorContactMode);
console.log('INFO ' + this.debugName + ': this.doorContactPresent: ' + this.doorContactPresent);
console.log('INFO ' + this.debugName + ': Timer für KNXDoorClosed started');
this.timer1 = setTimeout (function () {
console.log('INFO ' + this.debugName + ': Timeout, simulating Door Closed');
console.log('INFO ' + this.debugName + ': KNXDoorClosed = ' + this.sensorOn + ' set');
this.myAPI.setValue("CurrentDoorState", 1); // Closed
console.log('INFO ' + this.debugName + ': TargetDoorState = ' + this.sensorOn + ' set');
this.myAPI.setValue("TargetDoorState", 1); // Closed
this.percentageOpen = 1;
this.dateRunStart = undefined;
this.lastMove = "Stopped";
console.log('INFO ' + this.debugName + ': lastMove = ' + this.lastMove+ ' set'); // Door open
}.bind(this),this.doorRunTime*(this.percentageOpen));
} // simulateDoorContactMode
}
else if (this.lastMove === "goingDown"){
console.log('INFO ' + this.debugName + ': TargetDoorState = 1 OPEN set');
this.myAPI.setValue("TargetDoorState", 0); // OPEN
console.log('INFO ' + this.debugName + ': CurrentDoorState = 3 OPENING set');
this.myAPI.setValue("CurrentDoorState", 2); // OPENING
this.dateRunStart = new Date();
this.lastMove = "goingUp";
console.log('INFO ' + this.debugName + ': lastMove = ' + this.lastMove+ ' set');
// simulate
if (this.simulateDoorContactMode==="knx" && this.doorContactPresent==="closed"){
// simulate "open"-contact on knx
console.log('INFO ' + this.debugName + ': this.simulateDoorContactMode: ' + this.simulateDoorContactMode);
console.log('INFO ' + this.debugName + ': this.doorContactPresent: ' + this.doorContactPresent);
console.log('INFO ' + this.debugName + ': Timer für KNXDoorOpened started');
this.timer1 = setTimeout (function () {
console.log('INFO ' + this.debugName + ': Timeout, simulating Door Open');
console.log('INFO ' + this.debugName + ': KNXDoorOpened = ' + this.sensorOn + ' set');
this.myAPI.knxWrite("KNXDoorOpened", this.sensorOn, "DPT1"); // Door open
// setting HK-state and percentage is done in KNXDoorClosed
}.bind(this),this.doorRunTime*(1-this.percentageOpen));
} else if (this.simulateDoorContactMode==="internal" && this.doorContactPresent==="closed"){
// simulate "open"-contact internally
console.log('INFO ' + this.debugName + ': this.simulateDoorContactMode: ' + this.simulateDoorContactMode);
console.log('INFO ' + this.debugName + ': this.doorContactPresent: ' + this.doorContactPresent);
console.log('INFO ' + this.debugName + ': Timer für KNXDoorOpened started');
this.timer1 = setTimeout (function () {
console.log('INFO ' + this.debugName + ': Timeout, simulating Door Open');
console.log('INFO ' + this.debugName + ': CurrentDoorState = 0 OPEN set');
this.myAPI.setValue("CurrentDoorState", 0); // OPEN
console.log('INFO ' + this.debugName + ': TargetDoorState = 0 OPEN set');
this.myAPI.setValue("TargetDoorState", 0); // OPEN
this.percentageOpen = 1;
this.lastMove = "Stopped";
console.log('INFO ' + this.debugName + ': lastMove = ' + this.lastMove+ ' set'); // Door open
}.bind(this),this.doorRunTime*(1-this.percentageOpen));
} // simulateDoorContactMode
}
} // ("CurrentDoorState")===4 // STOPPED
else if (myCurrentDoorState===0){ // IF DOOR IS OPEN
console.log('INFO ' + this.debugName + ': CurrentDoorState = 0 OPEN detected');
console.log('INFO ' + this.debugName + ': TargetDoorState = 1 CLOSED set');
// Handling the setting here,
// -> removed this in KNXDoorOpened and KNXDoorClosed-handling
this.myAPI.setValue("TargetDoorState", 1); // CLOSED
console.log('INFO ' + this.debugName + ': CurrentDoorState = 3 CLOSING set');
this.myAPI.setValue("CurrentDoorState", 3); // CLOSING
this.dateRunStart = new Date();
this.lastMove = "goingDown";
console.log('INFO ' + this.debugName + ': lastMove = ' + this.lastMove+ ' set');
if (this.simulateDoorContactMode==="knx" && this.doorContactPresent==="closed"){
console.log('INFO ' + this.debugName + ': this.simulateDoorContactMode: ' + this.simulateDoorContactMode);
console.log('INFO ' + this.debugName + ': this.doorContactPresent: ' + this.doorContactPresent);
this.myAPI.knxWrite("KNXDoorOpened", !this.sensorOn, "DPT1"); // Door not open
}
else if (this.simulateDoorContactMode==="knx" && this.doorContactPresent==="open"){
// simulate the "closed contact" on knx
console.log('INFO ' + this.debugName + ': this.simulateDoorContactMode: ' + this.simulateDoorContactMode);
console.log('INFO ' + this.debugName + ': this.doorContactPresent: ' + this.doorContactPresent);
// simulate this even on the bus
this.myAPI.knxWrite("KNXDoorClosed", !this.sensorOn, "DPT1"); // Door not open
console.log('INFO ' + this.debugName + ': Timer für KNXDoorClosed started');
this.timer1 = setTimeout (function () {
console.log('INFO ' + this.debugName + ': Timeout, simulating Door Closed');
console.log('INFO ' + this.debugName + ': KNXDoorClosed = ' + this.sensorOn + ' set');
this.myAPI.knxWrite("KNXDoorClosed", this.sensorOn, "DPT1"); // Door open
this.percentageOpen = 1;
this.dateRunStart = undefined;
}.bind(this),this.doorRunTime);
} else if (this.simulateDoorContactMode==="internal" && this.doorContactPresent==="open"){
// simulate the "closed contact" internally
console.log('INFO ' + this.debugName + ': this.simulateDoorContactMode: ' + this.simulateDoorContactMode);
console.log('INFO ' + this.debugName + ': this.doorContactPresent: ' + this.doorContactPresent);
console.log('INFO ' + this.debugName + ': Timer für KNXDoorClosed started');
this.timer1 = setTimeout (function () {
console.log('INFO ' + this.debugName + ': Timeout, simulating Door Closed');
console.log('INFO ' + this.debugName + ': CurrentDoorState = 1 CLOSED set');
this.myAPI.setValue("CurrentDoorState", 1); // Closed
console.log('INFO ' + this.debugName + ': TargetDoorState = 1 CLOSED set');
this.myAPI.setValue("TargetDoorState", 1); // Closed
this.percentageOpen = 0;
this.dateRunStart = undefined;
this.lastMove = "Stopped";
console.log('INFO ' + this.debugName + ': lastMove = ' + this.lastMove+ ' set'); // Door closed
}.bind(this),this.doorRunTime);
} // simulateDoorContactMode
} // ("CurrentDoorState")===0 // OPEN
} // oldValue!==1)
} // knxValue===1
} // KNXPulseMove
if (field === "KNXPulseUp") {
if (knxValue === 1 && oldValue !== 1) {
this.myAPI.setValue("TargetDoorState", 0); // OPEN
this.myAPI.setValue("CurrentDoorState", 2); // OPENING
// calculate percentageOpen
var curDate = new Date();
var percentageRun = undefined;
if(!this.dateRunStart) {
this.dateRunStart = new Date();
}
percentageRun = (curDate.getTime() - this.dateRunStart.getTime()) / this.doorRunTime;
console.log('INFO ' + this.debugName + ': percentageRun = ' + percentageRun);
// has been going down before -> '-'
console.log('INFO ' + this.debugName + ': percentageOpen before = ' + this.percentageOpen);
this.percentageOpen = this.percentageOpen - percentageRun;
console.log('INFO ' + this.debugName + ': percentageOpen = ' + this.percentageOpen);
if (this.percentageOpen < 0 || this.percentageOpen > 1) {
if (this.percentageOpen < 0) {
this.percentageOpen = 0;
} else {
this.percentageOpen = 1;
}
console.log('WARNING: percentageOpen out of bounds, limiting to percentageOpen = ' + this.percentageOpen);
}
// simulate
if (this.simulateDoorContactMode==="knx" && this.doorContactPresent==="closed"){
// simulate "open"-contact on knx
console.log('INFO ' + this.debugName + ': this.simulateDoorContactMode: ' + this.simulateDoorContactMode);
console.log('INFO ' + this.debugName + ': this.doorContactPresent: ' + this.doorContactPresent);
console.log('INFO ' + this.debugName + ': Timer für KNXDoorClosed started, timer to expire in = ' + this.doorRunTime*(1-this.percentageOpen));
this.timer1 = setTimeout (function () {
console.log('INFO ' + this.debugName + ': Timeout, simulating Door Open');
console.log('INFO ' + this.debugName + ': KNXDoorOpened = ' + this.sensorOn + ' set');
this.myAPI.knxWrite("KNXDoorOpened", this.sensorOn, "DPT1"); // Door open
// setting HK-state and percentage is done in KNXDoorClosed
}.bind(this),this.doorRunTime*(1-this.percentageOpen));
} else if (this.simulateDoorContactMode==="internal" && this.doorContactPresent==="closed"){
// simulate "open"-contact internally
console.log('INFO ' + this.debugName + ': this.simulateDoorContactMode: ' + this.simulateDoorContactMode);
console.log('INFO ' + this.debugName + ': this.doorContactPresent: ' + this.doorContactPresent);
console.log('INFO ' + this.debugName + ': Timer für KNXDoorClosed started, timer to expire in = ' + this.doorRunTime*(1-this.percentageOpen));
this.timer1 = setTimeout (function () {
console.log('INFO ' + this.debugName + ': Timeout, simulating Door Open');
console.log('INFO ' + this.debugName + ': CurrentDoorState = 0 OPEN set');
this.myAPI.setValue("CurrentDoorState", 0); // OPEN
console.log('INFO ' + this.debugName + ': TargetDoorState = 0 OPEN set');
this.myAPI.setValue("TargetDoorState", 0); // OPEN
this.percentageOpen = 1;
this.dateRunStart = undefined;
this.lastMove = "Stopped";
console.log('INFO ' + this.debugName + ': lastMove = ' + this.lastMove+ ' set'); // Door open
}.bind(this),this.doorRunTime*(1-this.percentageOpen));
}
}
} // KNXPulseUp
if (field === "KNXPulseDown") {
if (knxValue === 1 && oldValue !== 1) {
this.myAPI.setValue("TargetDoorState", 1); // CLOSED
this.myAPI.setValue("CurrentDoorState", 3); // CLOSING
// calculate percentageOpen
var curDate = new Date();
var percentageRun = undefined;
if(!this.dateRunStart) {
this.dateRunStart = new Date();
}
percentageRun = (curDate.getTime() - this.dateRunStart.getTime()) / this.doorRunTime;
console.log('INFO ' + this.debugName + ': percentageRun = ' + percentageRun);
console.log('INFO ' + this.debugName + ': percentageOpen before = ' + this.percentageOpen);
// has been going donw before -> '+'
this.percentageOpen = this.percentageOpen + percentageRun;
console.log('INFO ' + this.debugName + ': percentageOpen = ' + this.percentageOpen);
if (this.percentageOpen < 0 || this.percentageOpen > 1) {
if (this.percentageOpen < 0) {
this.percentageOpen = 0;
} else {
this.percentageOpen = 1;
}
console.log('WARNING: percentageOpen out of bounds, limiting to percentageOpen = ' + this.percentageOpen);
}
// INFO: It could happen that this timer is set twice in case KNXDoorOpened get's in first,
// but that shouldn't matter
// simulate - put this to a function?
if (this.simulateDoorContactMode==="knx" && this.doorContactPresent==="open"){
// simulate the "closed contact" on knx
console.log('INFO ' + this.debugName + ': this.simulateDoorContactMode: ' + this.simulateDoorContactMode);
console.log('INFO ' + this.debugName + ': this.doorContactPresent: ' + this.doorContactPresent);
// simulate this even on the bus
this.myAPI.knxWrite("KNXDoorClosed", !this.sensorOn, "DPT1"); // Door not open
console.log('INFO ' + this.debugName + ': Timer für KNXDoorClosed started, timer to expire in = ' + this.doorRunTime*(this.percentageOpen));
this.timer1 = setTimeout (function () {
console.log('INFO ' + this.debugName + ': Timeout, simulating Door Closed');
console.log('INFO ' + this.debugName + ': KNXDoorClosed = ' + this.sensorOn + ' set');
this.myAPI.knxWrite("KNXDoorClosed", this.sensorOn, "DPT1"); // Door open
this.percentageOpen = 1;
this.dateRunStart = undefined;
}.bind(this),this.doorRunTime*(this.percentageOpen));
} else if (this.simulateDoorContactMode==="internal" && this.doorContactPresent==="open"){
// simulate the "closed contact" internally
console.log('INFO ' + this.debugName + ': this.simulateDoorContactMode: ' + this.simulateDoorContactMode);
console.log('INFO ' + this.debugName + ': this.doorContactPresent: ' + this.doorContactPresent);
console.log('INFO ' + this.debugName + ': Timer für KNXDoorClosed started, timer to expire in = ' + this.doorRunTime*(this.percentageOpen));
this.timer1 = setTimeout (function () {
console.log('INFO ' + this.debugName + ': Timeout, simulating Door Closed');
console.log('INFO ' + this.debugName + ': CurrentDoorState = 1 CLOSED set');
this.myAPI.setValue("CurrentDoorState", 1); // Closed
console.log('INFO ' + this.debugName + ': TargetDoorState = 1 CLOSED set');
this.myAPI.setValue("TargetDoorState", 1); // Closed
this.percentageOpen = 0;
this.dateRunStart = undefined;
this.lastMove = "Stopped";
console.log('INFO ' + this.debugName + ': lastMove = ' + this.lastMove+ ' set'); // Door closed
}.bind(this),this.doorRunTime*(this.percentageOpen));
}
}
} // KNXPulseDown
if (field==="KNXDoorClose") {
console.log('INFO ' + this.debugName + ': In if-case -> field===KNXDoorClosed');
console.log('INFO ' + this.debugName + ': knxValue: ' + knxValue);
console.log('INFO ' + this.debugName + ': oldValue: ' + oldValue);
// value changed?
if (knxValue === this.sensorOn) {
console.log('INFO ' + this.debugName + ': In if-case -> knxValue changed and not null');
this.percentageOpen = 0;
this.dateRunStart = undefined;
// clear timer
if (this.timer1 !== undefined){
clearTimeout(this.timer1);
this.timer1 = undefined;
console.log('INFO ' + this.debugName + ': Timer für KNXDoorClosed reset');
}
this.myAPI.setValue("CurrentDoorState", 1); // CLOSED
this.myAPI.setValue("TargetDoorState", 1); // CLOSED
console.log('INFO ' + this.debugName + ': CurrentDoorState = 1 CLOSED set');
if (oldValue !== null){
console.log('INFO ' + this.debugName + ': KNXDoorClosed detected');
} else { // Init run
console.log('INFO ' + this.debugName + ': Init Garage Door HK Status');
if (this.simulateDoorContactMode==="knx" && this.doorContactPresent==="closed"){
// simulate "open"-contact
this.myAPI.knxWrite("KNXDoorOpened", !this.sensorOn, "DPT1");
}
} // Init run
this.lastMove = "Stopped";
console.log('INFO ' + this.debugName + ': lastMove = ' + this.lastMove+ ' set');
} // (knxValue===0)
else if (knxValue !== this.sensorOn) {
if (oldValue === this.sensorOn){ // oldValue = sensorOn
console.log('INFO ' + this.debugName + ': KNXDoorClosed = false detected');
// For automatically closing doors (e.g. a barrier) there is not necessarily a Pulse on the bus for
// closing. That is why, in case the timer is not running already, it is started.
if (!this.timer1) {
if (this.simulateDoorContactMode==="knx" && this.doorContactPresent==="closed"){
// simulate the "closed contact" on knx
console.log('INFO ' + this.debugName + ': this.simulateDoorContactMode: ' + this.simulateDoorContactMode);
console.log('INFO ' + this.debugName + ': this.doorContactPresent: ' + this.doorContactPresent);
// simulate this even on the bus
this.myAPI.knxWrite("KNXDoorOpened", !this.sensorOn, "DPT1"); // Door not closed
console.log('INFO ' + this.debugName + ': Timer für KNXDoorOpened started, timer to expire in = ' + this.doorRunTime);
this.timer1 = setTimeout (function () {
console.log('INFO ' + this.debugName + ': Timeout, simulating Door Opened');
console.log('INFO ' + this.debugName + ': KNXDoorOpened = ' + this.sensorOn + ' set');
this.myAPI.knxWrite("KNXDoorOpened", this.sensorOn, "DPT1"); // Door open
this.percentageOpen = 1;
this.dateRunStart = undefined;
}.bind(this),this.doorRunTime);
} else if (this.simulateDoorContactMode==="internal" && this.doorContactPresent==="closed"){
// simulate the "closed contact" internally
console.log('INFO ' + this.debugName + ': this.simulateDoorContactMode: ' + this.simulateDoorContactMode);
console.log('INFO ' + this.debugName + ': this.doorContactPresent: ' + this.doorContactPresent);
console.log('INFO ' + this.debugName + ': Timer für KNXDoorOpened started, timer to expire in = ' + this.doorRunTime);
this.timer1 = setTimeout (function () {
console.log('INFO ' + this.debugName + ': Timeout, simulating Door Open');
console.log('INFO ' + this.debugName + ': CurrentDoorState = 1 OPEN set');
this.myAPI.setValue("CurrentDoorState", 0); // Open
console.log('INFO ' + this.debugName + ': TargetDoorState = 1 OPEN set');
this.myAPI.setValue("TargetDoorState", 0); // Open
this.percentageOpen = 1;
this.dateRunStart = undefined;
this.lastMove = "Stopped";
console.log('INFO ' + this.debugName + ': lastMove = ' + this.lastMove+ ' set'); // Door open
}.bind(this),this.doorRunTime);
}
}else {
console.log('INFO ' + this.debugName + ': KNXDoorClosed = timer running detected');
}
} else if (oldValue === null) { // Init run
console.log('INFO ' + this.debugName + ': Init Garage Door HK Status KNXDoorClosed = false');
// Init to closed as we don't know better and that's the best guess
this.myAPI.setValue("CurrentDoorState", 0); // OPEN
this.myAPI.setValue("TargetDoorState", 0); // OPEN
this.percentageOpen = 1;
if (this.simulateDoorContactMode==="knx" && this.doorContactPresent==="open"){
// simulate "closed"-contact
this.myAPI.knxWrite("KNXDoorOpened", this.sensorOn, "DPT1");
}
} // Init run
// This was probably the culprit for receiving two push notifications
// it should be ok to just have the TargetDoorState set on receiving a pulse
// this.myAPI.setValue("TargetDoorState", 0); // OPENED
}
} // KNXDoorClosed
// TODO: Door is open, gets closed automatically by someone going through
// -> TargetDoorState needs to be set.
if (field==="KNXDoorOpened") {
console.log('INFO ' + this.debugName + ': In if-case -> field===KNXDoorOpened');
console.log('INFO ' + this.debugName + ': knxValue: ' + knxValue);
console.log('INFO ' + this.debugName + ': oldValue: ' + oldValue);
// value changed?
if (knxValue === this.sensorOn) {
// Status 0 (open) detected
this.percentageOpen = 1;
this.dateRunStart = undefined;
// clear timer
if (this.timer1 !== undefined){
clearTimeout(this.timer1);
this.timer1 = undefined;
console.log('INFO ' + this.debugName + ': Timer für KNXDoorOpened reset');
}
this.myAPI.setValue("CurrentDoorState", 0); // OPEN
this.myAPI.setValue("TargetDoorState", 0); // OPEN
console.log('INFO ' + this.debugName + ': CurrentDoorState = 0 OPEN set');
if (oldValue !== null){
console.log('INFO ' + this.debugName + ': KNXDoorOpened detected');
} else { // Init run
console.log('INFO ' + this.debugName + ': Init Garage Door HK Status KNXDoorOpened = true');
if (this.simulateDoorContactMode==="knx" && this.doorContactPresent==="open"){
// simulate "closed"-contact
this.myAPI.knxWrite("KNXDoorClosed", !this.sensorOn, "DPT1");
}
} // Init run
this.lastMove = "Stopped";
console.log('INFO ' + this.debugName + ': lastMove = ' + this.lastMove+ ' set');
} // field==="KNXDoorOpened = 0
else if (knxValue !== this.sensorOn) {
if (oldValue === this.sensorOn){ // oldValue == sensorOn
console.log('INFO ' + this.debugName + ': KNXDoorOpened = false detected');
// For automatically closing doors (e.g. a barrier) there is not necessarily a Pulse on the bus for
// closing. That is why, in case the timer is not running already, it is started.
if (!this.timer1) {
if (this.simulateDoorContactMode==="knx" && this.doorContactPresent==="open"){
// simulate the "closed contact" on knx
console.log('INFO ' + this.debugName + ': this.simulateDoorContactMode: ' + this.simulateDoorContactMode);
console.log('INFO ' + this.debugName + ': this.doorContactPresent: ' + this.doorContactPresent);
// simulate this even on the bus
this.myAPI.knxWrite("KNXDoorClosed", !this.sensorOn, "DPT1"); // Door not open
console.log('INFO ' + this.debugName + ': Timer für KNXDoorClosed started, timer to expire in = ' + this.doorRunTime);
this.timer1 = setTimeout (function () {
console.log('INFO ' + this.debugName + ': Timeout, simulating Door Closed');
console.log('INFO ' + this.debugName + ': KNXDoorClosed = ' + this.sensorOn + ' set');
this.myAPI.knxWrite("KNXDoorClosed", this.sensorOn, "DPT1"); // Door open
this.percentageOpen = 0;
this.dateRunStart = undefined;
}.bind(this),this.doorRunTime);
} else if (this.simulateDoorContactMode==="internal" && this.doorContactPresent==="open"){
// simulate the "closed contact" internally
console.log('INFO ' + this.debugName + ': this.simulateDoorContactMode: ' + this.simulateDoorContactMode);
console.log('INFO ' + this.debugName + ': this.doorContactPresent: ' + this.doorContactPresent);
console.log('INFO ' + this.debugName + ': Timer für KNXDoorClosed started, timer to expire in = ' + this.doorRunTime);
this.timer1 = setTimeout (function () {
console.log('INFO ' + this.debugName + ': Timeout, simulating Door Closed');
console.log('INFO ' + this.debugName + ': CurrentDoorState = 1 CLOSED set');
this.myAPI.setValue("CurrentDoorState", 1); // Closed
console.log('INFO ' + this.debugName + ': TargetDoorState = 1 CLOSED set');
this.myAPI.setValue("TargetDoorState", 1); // Closed
this.percentageOpen = 0;
this.dateRunStart = undefined;
this.lastMove = "Stopped";
console.log('INFO ' + this.debugName + ': lastMove = ' + this.lastMove+ ' set'); // Door closed
}.bind(this),this.doorRunTime);
}
} else {
console.log('INFO ' + this.debugName + ': KNXDoorOpened = timer running detected');
}
} else if (oldValue === null) { // Init run
console.log('INFO ' + this.debugName + ': Init Garage Door HK Status KNXDoorOpened = false');
// Init to closed as we don't know better and that's the best guess
this.myAPI.setValue("CurrentDoorState", 1); // CLOSED
this.myAPI.setValue("TargetDoorState", 1); // CLOSED
this.percentageOpen = 0;
if (this.simulateDoorContactMode==="knx" && this.doorContactPresent==="open"){
// simulate "closed"-contact
this.myAPI.knxWrite("KNXDoorClosed", this.sensorOn, "DPT1");
}
} // Init run
// This was probably the culprit for receiving two push notifications
// it should be ok to just have the TargetDoorState set on receiving a pulse
// this.myAPI.setValue("TargetDoorState", 1); // CLOSED
}
} // KNXDoorOpened
} // onKNXValueChange
/****
* onHKValueChange is invoked if HomeKit is changing characteristic values
*
*/
onHKValueChange(field, oldValue, newValue) {
var myCurrentDoorState = this.myAPI.getValue("CurrentDoorState");
// sets the mode to simulate the DoorOpen-contact.
// Available modes:
// - off
// - knx
// - internal
this.simulateDoorContactMode = this.myAPI.getLocalConstant("simulateDoorContactMode");
// configures which contacts are really present in a setup.
// if simulateDoorContactMode is set to "knx" or "internal", the other contact will be
// simulated
//
// Available modes:
// - open - if the "open"-contact is present
// - closed - if the "closed"-contact is present
// - both - if both ontacts are present - no simulation in this case
this.doorContactPresent = this.myAPI.getLocalConstant("doorContactPresent");
// Door run-time
this.doorRunTime = this.myAPI.getLocalConstant("doorRunTime"); // in mil.seconds
// Define the length for a pulse. This needs to be set regardless staircase-function on or off
// In case the staircase-function is used, it needs to be set to the same value (or a little more)
this.pulseLength = this.myAPI.getLocalConstant("pulseLength");
// Staircase function
this.staircaseFunc = this.myAPI.getLocalConstant("staircaseFunc");
// Does the door use separate pulses for up and down?
this.separatePulseUpDown = this.myAPI.getLocalConstant("separatePulseUpDown");
// get the sensor value for "On"
this.sensorOn = this.myAPI.getLocalConstant("sensorOn");
// set debugName
this.debugName = this.myAPI.getLocalConstant("debugName");
console.log('INFO ' + this.debugName + ': on HK Value Change (' + field + ", old="+ oldValue + ", new="+ newValue + ")");
console.log('INFO ' + this.debugName + ': myCurrentDoorState = ' + myCurrentDoorState);
if (field === "TargetDoorState") {
// The value property of TargetDoorState must be one of the following:
// Characteristic.TargetDoorState.OPEN = 0;
// Characteristic.TargetDoorState.CLOSED = 1;
if (newValue === 0){ // OPEN
if (this.separatePulseUpDown) {
if (myCurrentDoorState !== 0){ // not equal open
this.sendPulseUp();
} else {
console.log('INFO ' + this.debugName + ': CurrentDoorState = 0 OPEN already, not sending PulseUp');
}
} else { // only up/stop/down - 1 type of pulse available
if (myCurrentDoorState===0){ // IF DOOR IS OPEN
console.log('INFO ' + this.debugName + ': CurrentDoorState = 2 OPEN detected');
// Do nothing, opening already
} // ("CurrentDoorState")===2 //OPENING
else if (myCurrentDoorState===2){ // IF DOOR IS OPENING
console.log('INFO ' + this.debugName + ': CurrentDoorState = 2 OPENING detected');
// Do nothing, opening already
}
else if (myCurrentDoorState===1){ // IF DOOR IS CLOSED
// send pulse for Opening
console.log('INFO ' + this.debugName + ': Calling this.sendPulse()');
this.sendPulse(1);
} // ("CurrentDoorState")===0 // CLOSED
else if (myCurrentDoorState===3){ // IF DOOR IS CLOSING
console.log('INFO ' + this.debugName + ': CurrentDoorState = 3 CLOSING detected');
// Send pulsees for Stop - Opening
this.sendPulse(2);
// CurrentDoorState is taken care in KNXValueChange
} // ("CurrentDoorState")===2 //OPENING
else if (myCurrentDoorState===4){ // IF DOOR IS STOPPED
console.log('INFO ' + this.debugName + ': CurrentDoorState = 4 STOPPED detected');
// Door is stopped (not closed or opened and was goingUp)
if (this.lastMove === "goingUp"){
// send pulsees for Down - Stop - Opening
console.log('INFO ' + this.debugName + ': goingUp, Calling this.sendPulse(3)');
this.sendPulse(3);
// CurrentDoorState is taken care in KNXValueChange
}
// Door is stopped (not closed or opened and was goingDown)
else if (this.lastMove === "goingDown"){
// send pulse for Opening
console.log('INFO ' + this.debugName + ': goingDown, Calling this.sendPulse(1)');
this.sendPulse(1);
// CurrentDoorState is taken care in KNXValueChange
}
} // ("CurrentDoorState")===4 // STOPPED
}
} // TargetDoorState = OPEN
if (newValue === 1){ // CLOSE
if (this.separatePulseUpDown) {
if (myCurrentDoorState !== 1){ // not equal CLOSED
this.sendPulseDown();
} else {
console.log('INFO ' + this.debugName + ': CurrentDoorState = 1 CLOSED already, not sending PulseDown');
}
} else { // only up/stop/down - 1 type of pulse available
if (myCurrentDoorState===1){ // IF DOOR IS CLOSED
console.log('INFO ' + this.debugName + ': CurrentDoorState = 2 CLOSED detected');
// Do nothing, closing already
} // ("CurrentDoorState")===0 // CLOSED
else if (myCurrentDoorState===3){ // IF DOOR IS CLOSING
console.log('INFO ' + this.debugName + ': CurrentDoorState = 2 CLOSING detected');
// Do nothing, closing already
} // ("CurrentDoorState")===2 //OPENING
else if (myCurrentDoorState===0){ // IF DOOR IS OPEN
// send pulse for Closing
this.sendPulse(1);
} // ("CurrentDoorState")===0 // OPEN
else if (myCurrentDoorState===2){ // IF DOOR IS OPENING
console.log('INFO ' + this.debugName + ': CurrentDoorState = 3 OPENING detected');
// Send pulses for Stop - Opening
this.sendPulse(2);
// CurrentDoorState is taken care in KNXValueChange
} // ("CurrentDoorState")===2 //OPENING
else if (myCurrentDoorState===4){ // IF DOOR IS STOPPED
console.log('INFO ' + this.debugName + ': CurrentDoorState = 4 STOPPED detected');
if (this.lastMove === "goingDown"){
// send pulsees for Down - Stop - Opening
this.sendPulse(3);
// CurrentDoorState is taken care in KNXValueChange
}
else if (this.lastMove === "goingUp"){
// send pulse for Opening
this.sendPulse(1);
// CurrentDoorState is taken care in KNXValueChange
}
} // ("CurrentDoorState")===4 // STOPPED
}
} // TargetDoorState = CLOSE
} // TargetDoorState
} // onHKValueChange
/****
* sendPulse is used to send an pulse for up/down/stop to the bus
*
*/
sendPulse(numPulses) {
console.log('INFO ' + this.debugName + ': sendPulse called. Number of pulses = ' + numPulses);
var date = new Date();
if (numPulses === 1){
date = new Date();
console.log('INFO ' + this.debugName + ': KNXPulseMove = 1 first pulse - calling Up/Stop/Down, ' + date.getSeconds() +'s:'+ date.getMilliseconds() +'ms');
this.myAPI.knxWrite("KNXPulseMove", 1, "DPT1"); // Up/Stop/Down
setTimeout(function(){
date = new Date();
console.log('INFO ' + this.debugName + ': KNXPulseMove = 0 first pulse - calling Up/Stop/Down, ' + date.getSeconds() +'s:'+ date.getMilliseconds() +'ms');
if (!this.staircaseFunc) {this.myAPI.knxWrite("KNXPulseMove", 0, "DPT1");} // Up/Stop/Down
}.bind(this), this.pulseLength);
} else if (numPulses === 2){
date = new Date();
console.log('INFO ' + this.debugName + ': KNXPulseMove = 1 first pulse - calling Up/Stop/Down, ' + date.getSeconds() +'s:'+ date.getMilliseconds() +'ms');
this.myAPI.knxWrite("KNXPulseMove", 1, "DPT1"); // Up/Stop/Down
setTimeout(function(){
date = new Date();
console.log('INFO ' + this.debugName + ': KNXPulseMove = 0 first pulse - calling Up/Stop/Down, ' + date.getSeconds() +'s:'+ date.getMilliseconds() +'ms');
if (!this.staircaseFunc) {this.myAPI.knxWrite("KNXPulseMove", 0, "DPT1");} // Up/Stop/Down
setTimeout(function(){
date = new Date();
console.log('INFO ' + this.debugName + ': KNXPulseMove = 1 second pulse - calling Up/Stop/Down, ' + date.getSeconds() +'s:'+ date.getMilliseconds() +'ms');
this.myAPI.knxWrite("KNXPulseMove", 1, "DPT1"); // Up/Stop/Down
setTimeout(function(){
date = new Date();
console.log('INFO ' + this.debugName + ': KNXPulseMove = 0 second pulse - calling Up/Stop/Down, ' + date.getSeconds() +'s:'+ date.getMilliseconds() +'ms');
if (!this.staircaseFunc) {this.myAPI.knxWrite("KNXPulseMove", 0, "DPT1");} // Up/Stop/Down
}.bind(this), this.pulseLength);
}.bind(this), this.pulseLength);
}.bind(this), this.pulseLength);
} else if (numPulses === 3){
date = new Date();
console.log('INFO ' + this.debugName + ': KNXPulseMove = 1 first pulse - calling Up/Stop/Down, ' + date.getSeconds() +'s:'+ date.getMilliseconds() +'ms');
this.myAPI.knxWrite("KNXPulseMove", 1, "DPT1"); // Up/Stop/Down
setTimeout(function(){
date = new Date();
console.log('INFO ' + this.debugName + ': KNXPulseMove = 0 first pulse - calling Up/Stop/Down, ' + date.getSeconds() +'s:'+ date.getMilliseconds() +'ms');
if (!this.staircaseFunc) {this.myAPI.knxWrite("KNXPulseMove", 0, "DPT1");} // Up/Stop/Down
setTimeout(function(){
date = new Date();
console.log('INFO ' + this.debugName + ': KNXPulseMove = 1 second pulse - calling Up/Stop/Down, ' + date.getSeconds() +'s:'+ date.getMilliseconds() +'ms');
this.myAPI.knxWrite("KNXPulseMove", 1, "DPT1"); // Up/Stop/Down
setTimeout(function(){
date = new Date();
console.log('INFO ' + this.debugName + ': KNXPulseMove = 0 second pulse - calling Up/Stop/Down, ' + date.getSeconds() +'s:'+ date.getMilliseconds() +'ms');
if (!this.staircaseFunc) {this.myAPI.knxWrite("KNXPulseMove", 0, "DPT1");} // Up/Stop/Down
setTimeout(function(){
date = new Date();
console.log('INFO ' + this.debugName + ': KNXPulseMove = 1 third pulse - calling Up/Stop/Down, ' + date.getSeconds() +'s:'+ date.getMilliseconds() +'ms');
this.myAPI.knxWrite("KNXPulseMove", 1, "DPT1"); // Up/Stop/Down
setTimeout(function(){
date = new Date();
console.log('INFO ' + this.debugName + ': KNXPulseMove = 0 third pulse - calling Up/Stop/Down, ' + date.getSeconds() +'s:'+ date.getMilliseconds() +'ms');
if (!this.staircaseFunc) {this.myAPI.knxWrite("KNXPulseMove", 0, "DPT1");} // Up/Stop/Down
}.bind(this), this.pulseLength);
}.bind(this), this.pulseLength);
}.bind(this), this.pulseLength);
}.bind(this), this.pulseLength);
}.bind(this), this.pulseLength);
}
}
/****
* sendPulseUp is used to send an pulse for up to the bus
*
*/
sendPulseUp() {
var date = new Date();
console.log('INFO ' + this.debugName + ': KNXPulseUp = 1 pulse, ' + date.getSeconds() +'s:'+ date.getMilliseconds() +'ms');
this.myAPI.knxWrite("KNXPulseUp", 1, "DPT1"); // Up
setTimeout(function(){
if (!this.staircaseFunc) {
date = new Date();
console.log('INFO ' + this.debugName + ': KNXPulseUp = 0 pulse, ' + date.getSeconds() +'s:'+ date.getMilliseconds() +'ms');
this.myAPI.knxWrite("KNXPulseUp", 0, "DPT1");
} // Up
}.bind(this), this.pulseLength);
}
/****
* sendPulseUp is used to send an pulse for up to the bus
*
*/
sendPulseDown() {
var date = new Date();
console.log('INFO ' + this.debugName + ': KNXPulseDown = 1 pulse, ' + date.getSeconds() +'s:'+ date.getMilliseconds() +'ms');
this.myAPI.knxWrite("KNXPulseDown", 1, "DPT1"); // Down
setTimeout(function(){
if (!this.staircaseFunc) {
date = new Date();
console.log('INFO ' + this.debugName + ': KNXPulseDown = 0 pulse, ' + date.getSeconds() +'s:'+ date.getMilliseconds() +'ms');
this.myAPI.knxWrite("KNXPulseDown", 0, "DPT1");
} // Down
}.bind(this), this.pulseLength);
}
} // class
module.exports= GarageDoorOpenerAdvanced;
/*****************************************************************************
The config for that should look like this in knx_config.json:
{
"DeviceName": "Garagento