Read the statement by Michael Teeuw here.
Problem Adding Buttons & required Remote-Control Modules
-
@sdetweil Thank you for catching those, too much copying and pasting.
Removed one of the start functions from the module.js file and also updated this line in the node_helper.js file so now it is returning the pin state instead of the pin number.
//const pinState = parseInt(stdout.trim(), 10);
const pinState = stdout.includes(“hi”) ? 1 : 0;There still seems to be an issue somewhere in my node_helper.js file though because I’m still not seeing anything from that file in the console. Looking through the forum it seems node_helper file issues are common and I’ve tried implementing a few of the solutions I found there but still haven’t found the problem but I will keep trying. I suspect maybe I’m not nesting my socket notifications correctly.
PinToggleTest.js
Module.register("MMM-PinToggleTest", { defaults: { pin: 19, modulesToToggle: ["clock", "calendar"], interval: 1000 }, start: function() { console.log("MMM-PinToggleTest started"); Log.info("MMM-PinToggleTest is starting, sending CONFIG..."); this.previousPinState = null; // Request initial pin check from the helper this.sendSocketNotification("CONFIG", this.config); }, socketNotificationReceived: function(notification, payload) { if (notification === 'STARTED') { console.log("STARTED notification received from node_helper"); this.config.text = 'Started'; this.updateDom(); } }, socketNotificationReceived: function(notification, payload) { if (notification === "PIN_STATE") { const pinState = payload; console.log(`Received pin state: ${pinState}`); // Log received state // Toggle modules based on pin state if (pinState !== this.previousPinState) { this.previousPinState = pinState; this.toggleModules(pinState === 1); } } }, toggleModules: function(show) { console.log(`Toggling modules to ${show ? "show" : "hide"}`); this.config.modulesToToggle.forEach(moduleName => { const modules = MM.getModules().withClass(moduleName); modules.forEach(module => { if (show) { module.show(1000); // Show module with fade-in effect } else { module.hide(1000); // Hide module with fade-out effect } }); }); }, getDom: function() { const wrapper = document.createElement("div"); wrapper.innerHTML = "<small>MMM-PinToggleTest</small>"; return wrapper; } });
node_helper.js
const NodeHelper = require("node_helper"); const exec = require("child_process").exec; //const rpio = require("rpio"); //const Gpio = require("onoff").Gpio; //module.exports = NodeHelper.create({ // start: function() { // console.log("Starting node_helper for MMM-PinToggleTest"); // this.previousPinState = null; // this.config = null; // }, module.exports = NodeHelper.create({ start() { this.started = false; }, socketNotificationReceived: function(notification, payload) { if (notification === "CONFIG" && !this.started) { const self = this; console.log("CONFIG notification received"); this.config = payload; this.schedulePinCheck(); this.sendSocketNotification('STARTED', {message: 'test'}); console.log("STARTED notification sent back to front end"); } }, schedulePinCheck: function() { console.log(`Setting up pin check every ${this.config.interval} ms`); setInterval(() => { this.checkPinState(); }, this.config.interval); }, checkPinState: function() { const pinNumber = this.config.pin; // Execute pinctrl command exec(`pinctrl get ${pinNumber}`, (error, stdout, stderr) => { if (error) { console.error(`Error reading GPIO pin ${pinNumber}: ${stderr}`); return; } //const pinState = parseInt(stdout.trim(), 10); const pinState = stdout.includes("hi") ? 1 : 0; console.log(`Detected pin state for pin ${pinNumber}: ${pinState}`); // Log the detected state // Only send if state has changed if (pinState !== this.previousPinState) { this.previousPinState = pinState; console.log(`Pin state changed to ${pinState}`); this.sendSocketNotification("PIN_STATE", pinState); // Small delay to avoid multiple triggers setTimeout(() => {}, 100); } }); } });
-
@ChrisLeduex I see this from the output of npm start
[2024-11-05 12:32:28.225] [LOG] Current pin state for GPIO 19: 1 [2024-11-05 12:32:28.225] [LOG] Pin state changed to 1 at 2024-11-05T18:32:28.224Z [2024-11-05 12:32:28.244] [INFO] [MMM-MealieMenu] Week starts: 2024-11-04, next week starts: 2024-11-11 [2024-11-05 12:32:28.375] [INFO] Mealie error={} [2024-11-05 12:32:28.400] [INFO] Newsfeed-Fetcher: Broadcasting 15 items. [2024-11-05 12:32:28.413] [INFO] Newsfeed-Fetcher: Broadcasting 22 items. [2024-11-05 12:32:28.819] [INFO] Newsfeed-Fetcher: reloadInterval set to ttl=5400000 for url http://www.tagesschau.de/xml/rss2 [2024-11-05 12:32:28.847] [INFO] Newsfeed-Fetcher: Broadcasting 40 items. [2024-11-05 12:32:29.225] [LOG] Current pin state for GPIO 19: 1 [2024-11-05 12:32:30.225] [LOG] Current pin state for GPIO 19: 1 [2024-11-05 12:32:31.225] [LOG] Current pin state for GPIO 19: 1 [2024-11-05 12:32:32.225] [LOG] Current pin state for GPIO 19: 1 [2024-11-05 12:32:33.224] [LOG] Current pin state for GPIO 19: 1 [2024-11-05 12:32:34.225] [LOG] Current pin state for GPIO 19: 1 [2024-11-05 12:32:35.226] [LOG] Current pin state for GPIO 19: 1 [2024-11-05 12:32:36.227] [LOG] Current pin state for GPIO 19: 1 [2024-11-05 12:32:37.229] [LOG] Current pin state for GPIO 19: 1 [2024-11-05 12:32:38.227] [LOG] Current pin state for GPIO 19: 1
I wrote a little pinctrl script that just outputs 1
#!/bin/bash echo 1
as pinctrl is not on my linux desktop
-
@sdetweil Ah yes, I forgot I have a python script I was kicking off manually that I forgot to run before testing those fixes. It is working now and both files are communicating with each other, thank you.
My next step is to see if I can get this working with the MMM-Buttons/MMM-ModuleToggleButton modules.
-
@ChrisLeduex buttons is interrupt driven, but can be changed to polling like you are doing
-
@sdetweil Yeah you’re right, that one might be more difficult. But I do have MMM-ModuleToggleButton working with pinctrl. Here’s the updated node_helper.js file just in case anyone’s interested.
node_helper.js
const NodeHelper = require('node_helper'); // eslint-disable-line import/no-extraneous-dependencies //const Gpio = require('onoff').Gpio; const { exec } = require("child_process"); module.exports = NodeHelper.create({ start() { this.started = false; }, socketNotificationReceived(notification, payload) { if (notification === 'TOGGLE_BUTTON_CONFIG' && !this.started) { const self = this; this.config = payload; //const button = new Gpio(this.config.buttonGpioPin, 'in', 'both', { persistentWatch: true, debounceTimeout: this.config.debounceTimeoutInMilliseconds }); //button.watch((err, state) => { // if (state === 1) { // self.sendSocketNotification(self.config.notificationName, true); // } //}); //this.started = true; // Set up GPIO as input using pinctrl command const pin = this.config.buttonGpioPin; const debounceTimeout = this.config.debounceTimeoutInMilliseconds; const notificationName = this.config.notificationName; let lastState = null; // Function to read the pin state using pinctrl const checkPinState = () => { exec(`pinctrl get ${pin}`, (err, stdout, stderr) => { if (err) { console.error(`Error reading GPIO state: ${err.message}`); return; } // Parse the pin state from stdout const state = stdout.includes("hi") ? 1 : 0; // Handle state change with debounce if (state !== lastState && state === 1) { this.sendSocketNotification(notificationName, true); } // Update last state lastState = state; }); }; // Set up an interval to check the pin state with debounce setInterval(checkPinState, debounceTimeout || 100); // Defaults to 100ms if debounce is not defined } } });
-