From f1e5ecd07a58f49f5c681b33a2f7d62b4904efef Mon Sep 17 00:00:00 2001 From: Tom Hirschberger Date: Tue, 17 Jan 2023 20:54:33 +0100 Subject: [PATCH 1/7] removed fixme as already fixed part --- node_helper.js | 1 - 1 file changed, 1 deletion(-) diff --git a/node_helper.js b/node_helper.js index 7e76dc9..4d91f8a 100644 --- a/node_helper.js +++ b/node_helper.js @@ -101,7 +101,6 @@ module.exports = NodeHelper.create({ self.name + ": Sending notifications of pin " + curPin + "..." ); self.lastMessures[String(curPin)] = curTimestamp; - //FIXME: Add notifications_low and notifications_high let curNotifications = [] if (typeof self.config[String(curPin)].notifications !== "undefined"){ curNotification = curNotification.concat(self.config[String(curPin)].notifications) From 291607b1686c0e6a59e3487c0d6732bf43cdeebf Mon Sep 17 00:00:00 2001 From: Tom Hirschberger Date: Sun, 22 Jan 2023 00:02:23 +0100 Subject: [PATCH 2/7] added depreaction warning for old notification syntax; added new delay_low and delay_high options --- README.md | 43 +------ examples/HC-SR501/HC-SR501-GPIO4-README-DE.md | 3 +- examples/HC-SR501/HC-SR501-GPIO4-README-EN.md | 3 +- node_helper.js | 112 +++++++++++++----- 4 files changed, 90 insertions(+), 71 deletions(-) diff --git a/README.md b/README.md index 91b5768..eb39d5c 100644 --- a/README.md +++ b/README.md @@ -27,10 +27,9 @@ To use the module insert it in the config.js file. Here is an example: module: 'MMM-GPIO-Notifications', config: { '17': { - gpio_state: 1, gpio_debounce: 10, delay: 1000, - notifications: [ + notifications_high: [ { notification: 'USER_PRESENCE', payload: true @@ -42,46 +41,8 @@ To use the module insert it in the config.js file. Here is an example: ] }, '4': { - gpio_state: 1, gpio_debounce: 20, - notifications: [ - { - 'notification': 'SCREEN_TOGGLE', - 'payload': { 'forced': true }, - 'profiles': 'pageOneEveryone pageTwoEveryone' - } - ] - } - } - }, -``` - -As of version 0.0.8 of the module it is possible to send specific notifications for both states of the the pin. Instead of specifying `gpio_state` and `notifications` the two arrays `notifications_low` and `notifications_high` are used in this case: - -```json5 - { - module: 'MMM-GPIO-Notifications', - config: { - '17': { - gpio_debounce: 10, - delay: 1000, - notifications_low: [ - { - notification: 'USER_PRESENCE', - payload: true - } - ], notifications_high: [ - { - notification: 'USER_PRESENCE', - payload: false - } - ] - }, - '4': { - gpio_state: 1, - gpio_debounce: 20, - notifications: [ { 'notification': 'SCREEN_TOGGLE', 'payload': { 'forced': true }, @@ -93,6 +54,8 @@ As of version 0.0.8 of the module it is possible to send specific notifications }, ``` +There are two buttons configured in this example. As of version 0.0.8 of the module it is possible to send specific notifications for both states of the the pin. Instead of specifying `gpio_state` and `notifications` the two arrays `notifications_low` and `notifications_high` are used. In the example above both gpio pins cause notifications being send if high state is triggered. + | Option | Description | Type | Default | | ------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------- | ------- | ------- | | THE_KEY | the number of the pin you want to watch. MAKE SURE TO ADD IT IN '' | String | | diff --git a/examples/HC-SR501/HC-SR501-GPIO4-README-DE.md b/examples/HC-SR501/HC-SR501-GPIO4-README-DE.md index cad8cb5..d2af554 100644 --- a/examples/HC-SR501/HC-SR501-GPIO4-README-DE.md +++ b/examples/HC-SR501/HC-SR501-GPIO4-README-DE.md @@ -124,10 +124,9 @@ Unser Ziel ist es, dass jedes mal, wenn der PIR-Sensor die Trigger-Leitung (GPIO module: 'MMM-GPIO-Notifications', config: { '4': { - gpio_state: 1, gpio_debounce: 0, delay: 10000, - notifications: [ + notifications_high: [ { notification: 'SCREEN_ON', payload: { 'forced': false } diff --git a/examples/HC-SR501/HC-SR501-GPIO4-README-EN.md b/examples/HC-SR501/HC-SR501-GPIO4-README-EN.md index 89d8687..f31ccc2 100644 --- a/examples/HC-SR501/HC-SR501-GPIO4-README-EN.md +++ b/examples/HC-SR501/HC-SR501-GPIO4-README-EN.md @@ -118,10 +118,9 @@ My PIR sensor triggers every 5 seconds. I do not want to send a notification tha module: 'MMM-GPIO-Notifications', config: { '4': { - gpio_state: 1, gpio_debounce: 0, delay: 10000, - notifications: [ + notifications_high: [ { notification: 'SCREEN_ON', payload: { 'forced': false } diff --git a/node_helper.js b/node_helper.js index 4d91f8a..cad3577 100644 --- a/node_helper.js +++ b/node_helper.js @@ -13,46 +13,69 @@ module.exports = NodeHelper.create({ this.started = false; this.currentProfile = ""; this.currentProfilePattern = new RegExp(".*"); + this.lastMessuresLow = {} + this.lastMessuresHigh = {} }, sendAllNotifications: function (curPin, curValue) { const self = this; const curTimestamp = Date.now(); if (curPin) { + let curDelay + let curMessures + if (curValue === 0){ + curDelay = self.config[String(curPin)].delay_low + curMessures = self.lastMessuresLow[String(curPin)] + } else { + curDelay = self.config[String(curPin)].delay_high + curMessures = self.lastMessuresHigh[String(curPin)] + } + if ( - curTimestamp - self.lastMessures[String(curPin)] > - self.config[String(curPin)].delay + curTimestamp - curMessures > + curDelay ) { let toSendNotifications = [] if ((typeof self.config[String(curPin)].gpio_state !== "undefined") && (curValue === self.config[String(curPin)].gpio_state) ){ - toSendNotifications = toSendNotifications.concat(self.config[String(curPin)].notifications) + if (typeof self.config[String(curPin)].notifications !== "undefined"){ + toSendNotifications = toSendNotifications.concat(self.config[String(curPin)].notifications) + } } if ((typeof self.config[String(curPin)].notifications_low !== "undefined") && - (curValue == 0) + (curValue === 0) ){ toSendNotifications = toSendNotifications.concat(self.config[String(curPin)].notifications_low) } if ((typeof self.config[String(curPin)].notifications_high !== "undefined") && - (curValue == 1) + (curValue === 1) ){ toSendNotifications = toSendNotifications.concat(self.config[String(curPin)].notifications_high) } let curLength = toSendNotifications.length - console.log("Length of toSendNotifications: "+curLength) if (curLength > 0) { - console.log( - self.name + ": Sending notifications of pin " + curPin + "..." - ); - self.lastMessures[String(curPin)] = curTimestamp; - for (var i = 0; i < curLength; i++) { - var curNotification = toSendNotifications[i]; + if (curValue === 0){ + console.log( + self.name + ": Sending notifications for low state of pin " + curPin + "..." + ); + self.lastMessuresLow[String(curPin)] = curTimestamp; + } else { + console.log( + self.name + ": Sending notifications for high state of pin " + curPin + "..." + ); + self.lastMessuresHigh[String(curPin)] = curTimestamp; + } + + console.log(JSON.stringify(toSendNotifications)) + + for (let i = 0; i < curLength; i++) { + let curNotification = toSendNotifications[i]; // console.log("CurProfile: " + self.currentProfile); // console.log("CurProfileString: " + curNotification.profiles); if ( @@ -93,29 +116,48 @@ module.exports = NodeHelper.create({ } else { console.log(self.name + ": Sending notifications of all pins..."); for (curPin in self.config) { + let curDelay + let pinLow + let curMessures + if (self.gpio[String(curPin)].readSync() == 0){ + curDelay = self.config[String(curPin)].delay_low + pinLow = true + curMessures = self.lastMessuresLow[String(curPin)] + } else { + curDelay = self.config[String(curPin)].delay_high + pinLow = false + curMessures = self.lastMessuresHigh[String(curPin)] + } + if ( - curTimestamp - self.lastMessures[String(curPin)] > - self.config[String(curPin)].delay + curTimestamp - curMessures > + curDelay ) { console.log( self.name + ": Sending notifications of pin " + curPin + "..." ); - self.lastMessures[String(curPin)] = curTimestamp; + + if(pinLow){ + self.lastMessuresLow[String(curPin)] = curTimestamp; + } else { + self.lastMessuresHigh[String(curPin)] = curTimestamp; + } + let curNotifications = [] if (typeof self.config[String(curPin)].notifications !== "undefined"){ - curNotification = curNotification.concat(self.config[String(curPin)].notifications) + curNotifications = curNotifications.concat(self.config[String(curPin)].notifications) } if (typeof self.config[String(curPin)].notifications_low !== "undefined"){ - curNotification = curNotification.concat(self.config[String(curPin)].notifications_low) + curNotifications = curNotifications.concat(self.config[String(curPin)].notifications_low) } if (typeof self.config[String(curPin)].notifications_high !== "undefined"){ - curNotification = curNotification.concat(self.config[String(curPin)].notifications_high) + curNotifications = curNotifications.concat(self.config[String(curPin)].notifications_high) } curLength = curNotifications.length; for (i = 0; i < curLength; i++) { - curNotification = curNotifications[i]; + let curNotification = curNotifications[i]; if ( typeof curNotification.profiles === "undefined" || self.currentProfilePattern.test(curNotification.profiles) @@ -149,7 +191,14 @@ module.exports = NodeHelper.create({ const self = this; if (notification === "CONFIG" && self.started === false) { self.config = payload; - self.lastMessures = []; + + for (var curPin in self.config) { + if (( typeof self.config[String(curPin)].gpio_state !== "undefined" ) || + ( typeof self.config[String(curPin)].notifications !== "undefined" ) + ){ + console.log(self.name + ": DEPRECATION WARNING: Your config of pin "+curPin+" uses the old, deprecated syntax for configuration. Please change to the new \"notification_low\" and \"notification_high\" arrays as the old syntax handling may be removed in future versions!") + } + } if (Gpio.accessible) { self.gpio = []; @@ -158,16 +207,25 @@ module.exports = NodeHelper.create({ self.gpio[String(curPin)] = new Gpio(curPin, "in", "both", { debounceTimeout: self.config[String(curPin)].gpio_debounce }); - self.lastMessures[String(curPin)] = -1; + self.lastMessuresLow[String(curPin)] = -1; + self.lastMessuresHigh[String(curPin)] = -1; if (typeof self.config[String(curPin)].delay === "undefined") { - console.log( - self.name + - ": Setting delay of pin " + - curPin + - " to default value 0!" - ); self.config[String(curPin)].delay = 0; } + if (typeof self.config[String(curPin)].delay_high === "undefined") { + self.config[String(curPin)].delay_high = self.config[String(curPin)].delay; + } + if (typeof self.config[String(curPin)].delay_low === "undefined") { + self.config[String(curPin)].delay_low = self.config[String(curPin)].delay; + } + + console.log( + self.name + ": Watched pin: " + curPin + " has low state delay of "+self.config[String(curPin)].delay_low+"!" + ); + + console.log( + self.name + ": Watched pin: " + curPin + " has high state delay of "+self.config[String(curPin)].delay_high+"!" + ); (function (gpiox, theCurPin) { gpiox.watch(function (err, value) { From 819f64b75d7da80b9f4559a6379bd81c8214d786 Mon Sep 17 00:00:00 2001 From: Tom Hirschberger Date: Sun, 22 Jan 2023 00:09:05 +0100 Subject: [PATCH 3/7] removed debug output --- node_helper.js | 3 --- 1 file changed, 3 deletions(-) diff --git a/node_helper.js b/node_helper.js index cad3577..e2dbe35 100644 --- a/node_helper.js +++ b/node_helper.js @@ -71,8 +71,6 @@ module.exports = NodeHelper.create({ ); self.lastMessuresHigh[String(curPin)] = curTimestamp; } - - console.log(JSON.stringify(toSendNotifications)) for (let i = 0; i < curLength; i++) { let curNotification = toSendNotifications[i]; @@ -86,7 +84,6 @@ module.exports = NodeHelper.create({ self.name + ": Sending notification:" ); - console.log(JSON.stringify(curNotification)) self.sendSocketNotification( curNotification.notification, curNotification.payload From 99d26437beb876f646e5ea6498ce865c5d35d043 Mon Sep 17 00:00:00 2001 From: Thomas Hirschberger Date: Sun, 22 Jan 2023 13:14:20 +0100 Subject: [PATCH 4/7] add a default gpio_debounce value of 0; add some more examples about delay and debounce to the readme. --- README.md | 77 ++++++++++++++++++++++++++++++++++++++++++++++---- node_helper.js | 2 +- 2 files changed, 73 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index eb39d5c..f8ec969 100644 --- a/README.md +++ b/README.md @@ -54,14 +54,81 @@ To use the module insert it in the config.js file. Here is an example: }, ``` -There are two buttons configured in this example. As of version 0.0.8 of the module it is possible to send specific notifications for both states of the the pin. Instead of specifying `gpio_state` and `notifications` the two arrays `notifications_low` and `notifications_high` are used. In the example above both gpio pins cause notifications being send if high state is triggered. +There are two buttons configured in this example. +As of version 0.0.8 of the module it is possible to send specific notifications for both states of the the pin. Instead of specifying `gpio_state` and `notifications` the two arrays `notifications_low` and `notifications_high` are used. In the example above both gpio pins cause notifications being send if high state is triggered. + +As of version 0.0.9 of the module the old syntax using `gpio_state` and `notifications` is depcreated. Use `notifications_low` and `notifications_high` instead! + +As of version 0.0.9 of the module it is possible to configure different delays depending on the state with the options `delay_high` and `delay_low`. If only `delay` is configured it will be used for both the high and the low state. | Option | Description | Type | Default | | ------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------- | ------- | ------- | | THE_KEY | the number of the pin you want to watch. MAKE SURE TO ADD IT IN '' | String | | -| gpio_state | the state of the gpio pin on which the notifications should be send | Integer | | -| gpio_debounce | the debounce value to use for the gpio event handling; if the pin changes the state during this period after the last event the new event will be ignored | Integer | | -| delay | time in milliseconds till the notifications will be send again altough the pin has been triggered | Integer | 0 | -| notifications | An array of natifications. Each notification needs a key "notification", the payload is optional. Also a optional profile string can be set | Array | +| gpio_state | DEPRECATED! The state of the gpio pin on which the notifications should be send. Use `notification_low` and `notifications_high` instead. | Integer | | +| gpio_debounce | the debounce value to use for the gpio event handling; if the pin changes the state during this period after the last event the new event will be ignored. Look in the section `Debounce vs. Delay` for more information. | Integer | | +| delay | time in milliseconds till the notifications will be send again altough the pin has been triggered. Look in the section `Debounce vs. Delay` for more information. | Integer | 0 | +| delay_low | time in milliseconds till the notifications of the low state will be send again after it got triggered. Look in the section `Debounce vs. Delay` for more information.| Integer | the value of `delay` | +| delay_high | time in milliseconds till the notifications of the high state will be send again after it got triggered. Look in the section `Debounce vs. Delay` for more information.| Integer | the value of `delay` | +| notifications | DEPRECATED! An array of natifications. Each notification needs a key "notification", the payload is optional. Also a optional profile string can be set. Use `notification_low` and `notifications_high` instead. | Array | | notifications_low | Instead of the use of `gpio_state` this array of notifications can be used to send specific notifications if the low state of the pin is triggered. | Array | | notifications_high | Instead of the use of `gpio_state` this array of notifications can be used to send specific notifications if the high state of the pin is triggered. | Array | + +### Debounce vs. Delay + +This section tries to describe the difference between the `gpio_debounce` and the different delay options `delay`, `delay_low` and `delay_high`. + +So first of all why do we need debounce in some cases... +Let us assume you have connected a button connected to a GPIO pin and want to do some action every time the button gets pressed and the GPIO changes to high state. Usually buttons do not provide debounce machanism by there self. Cause of the mechanics in the button our cause the fingers are shaking a little bit it can happen that the state changes from low to high, from high to low and back again to high within milliseconds of time. If no debounce mechanism is implemented the module will fire the actions for every of this changes. But WE know that if the user pressed the button he/she usally does not do that again with in the next seconds. So we can provide a debounce time within we ignore further input after the last one. +As this is a common problem the low-level GPIO libraries already provide such a machanism. You can simple set a debounce time and all input during this pirod will be ignored. As this already happens in the operating system it does save a lot of processing power. +But as the module does not get informored during the debounce time that an state change happend i can not provide any debug output about it as i simple do not recognize it. +The other thing is that this mechanism is usally to set debounce intervals in the amount of a maximum of a few seconds. Thats way i introduced the `delay` option some time ago. + +**The main difference between the `gpio_debounce` and the `delay`, `delay_low` and `delay_high` is that the delay options are handled by the module itself and cost more cpu power!** + +The advantage of the delay options are that we can log if we suppress output and we can configure a different delay depending on the GPIOs state. + +Let's look at a example with the following configuration: + +```json5 + { + module: 'MMM-GPIO-Notifications', + config: { + '4': { + delay_high: 10000, + delay_low: 30000, + notifications_high: [ + { + 'notification': 'USER_PRESENCE', + 'payload': true, + } + ], + notifications_low: [ + { + 'notification': 'USER_PRESENCE', + 'payload': false, + } + ] + }, + '17': { + gpio_debounce: 1000, + notifications_high: [ + { + notification: 'TOGGLE_LED', + } + ] + } + } + }, +``` + +We have the following goals in this example: + +* There is connected a radar sensor (RCWL-0516) sensor to GPIO 4 which is a kind of movement detector like PIR but is much faster and can detect movement through class and wood. If the sensor gets triggered and the GPIO changes to high state we want a `USER_PRESENCE` notification send with payload `true`. +* If the sensor on GPIO 4 does not recognize any further movement and the state of the pin changes back to low state we want a `USER_PRESENCE` notification being send with payload `false`. +* As the sensor is very fast and changes the state every 2 seconds we set a delay of the high state with the `delay_high` option of `10000` milliseconds which are 10 seconds. So only every 10 seconds a notification will be send. As our screensave module has a delay of 30 seconds configured we are totally fine with that and do not need to flush the mirror with notifications. +* As we use the `USER_PRESENCE` notification with payload `false` only for some external systems like HomeAssistent or NodeRed which do need to know after the user finally leaves we configure a `delay_low` of `30000` and suppress all notifications within the 30 seconds. +* Additionally there is a button connected to GPIO 17. Everytime the button is pressed we want a module that controls a led strip to toggle the state of the strip. We baught a cheap button which does not have any debounce machnism in it. Cause it fires random state changes after we pressed it for about a second we set a `gpio_debounce` of `1000` milliseconds wich is 1 second. + +To sum things up: +If you want to set a small delay where state changes should be ignored after a state change and you do not care of different delays depending on the state use the `gpio_debounce`. This saves some performance for other things with the cost that you will not see the ignored events in the log file. +If you want to be more flexible, you want to set a different delays for the high or low state and you want to see ignored events in the log file use the `delay`, `delay_low` and `delay_high` option. It will cost some performance but it is not that much. diff --git a/node_helper.js b/node_helper.js index e2dbe35..3ec6da2 100644 --- a/node_helper.js +++ b/node_helper.js @@ -202,7 +202,7 @@ module.exports = NodeHelper.create({ for (var curPin in self.config) { console.log(self.name + ": Registering pin: " + curPin); self.gpio[String(curPin)] = new Gpio(curPin, "in", "both", { - debounceTimeout: self.config[String(curPin)].gpio_debounce + debounceTimeout: self.config[String(curPin)].gpio_debounce || 0 }); self.lastMessuresLow[String(curPin)] = -1; self.lastMessuresHigh[String(curPin)] = -1; From 9e5ad25e14e091e390e396df99d130722c9f4dab Mon Sep 17 00:00:00 2001 From: Thomas Hirschberger Date: Sun, 22 Jan 2023 13:18:39 +0100 Subject: [PATCH 5/7] added new default value of gpio_debounce to readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index f8ec969..e33a52b 100644 --- a/README.md +++ b/README.md @@ -65,7 +65,7 @@ As of version 0.0.9 of the module it is possible to configure different delays d | ------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------- | ------- | ------- | | THE_KEY | the number of the pin you want to watch. MAKE SURE TO ADD IT IN '' | String | | | gpio_state | DEPRECATED! The state of the gpio pin on which the notifications should be send. Use `notification_low` and `notifications_high` instead. | Integer | | -| gpio_debounce | the debounce value to use for the gpio event handling; if the pin changes the state during this period after the last event the new event will be ignored. Look in the section `Debounce vs. Delay` for more information. | Integer | | +| gpio_debounce | the debounce value to use for the gpio event handling; if the pin changes the state during this period after the last event the new event will be ignored. Look in the section `Debounce vs. Delay` for more information. | Integer | 0 as of version 0.0.9 | | delay | time in milliseconds till the notifications will be send again altough the pin has been triggered. Look in the section `Debounce vs. Delay` for more information. | Integer | 0 | | delay_low | time in milliseconds till the notifications of the low state will be send again after it got triggered. Look in the section `Debounce vs. Delay` for more information.| Integer | the value of `delay` | | delay_high | time in milliseconds till the notifications of the high state will be send again after it got triggered. Look in the section `Debounce vs. Delay` for more information.| Integer | the value of `delay` | From cd15c1f4935154582ba21500b7477749660ac035 Mon Sep 17 00:00:00 2001 From: Tom Hirschberger Date: Sun, 22 Jan 2023 13:22:41 +0100 Subject: [PATCH 6/7] fixed default gpio_debounce --- node_helper.js | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/node_helper.js b/node_helper.js index 3ec6da2..7723702 100644 --- a/node_helper.js +++ b/node_helper.js @@ -201,9 +201,16 @@ module.exports = NodeHelper.create({ self.gpio = []; for (var curPin in self.config) { console.log(self.name + ": Registering pin: " + curPin); + let curDebounce = 0 + if (typeof self.config[String(curPin)].gpio_debounce !== "undefined"){ + curDebounce = self.config[String(curPin)].gpio_debounce + } self.gpio[String(curPin)] = new Gpio(curPin, "in", "both", { - debounceTimeout: self.config[String(curPin)].gpio_debounce || 0 + debounceTimeout: curDebounce }); + console.log( + self.name + ": Watched pin: " + curPin + " has debounce of "+curDebounce+"!" + ); self.lastMessuresLow[String(curPin)] = -1; self.lastMessuresHigh[String(curPin)] = -1; if (typeof self.config[String(curPin)].delay === "undefined") { From 3ce7a6c23b6809edafdddf1a3960c2585fac7a30 Mon Sep 17 00:00:00 2001 From: Thomas Hirschberger Date: Sun, 22 Jan 2023 13:23:28 +0100 Subject: [PATCH 7/7] changed version to 0.0.9 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index a995911..2bb35aa 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "MMM-GPIO-Notifications", - "version": "0.0.8", + "version": "0.0.9", "description": "", "main": "MMM-GPIO-Notifications.js", "devDependencies": {},