Read the statement by Michael Teeuw here.
Problem Adding Buttons & required Remote-Control Modules
-
Dear Mr @sdetweil
Please see above, it seems “on-off” is throwing errors. It seems it is used by Remote-Control-Modules as well as Buttons. I wnet back and tried buttons. The error is below: Thank you very much. Anthony[2024-09-22 11:34:50.557] [LOG] Launching application.
[2024-09-22 11:35:05.029] [ERROR] ERROR! Could not validate main module js file.
[2024-09-22 11:35:05.037] [ERROR] ReferenceError: Log is not defined
at Object. (/home/awwbaker/MagicMirror/modules/MMM-RAIN-MAP/MMM-RAIN-MAP.js:28:158622)
at Module._compile (node:internal/modules/cjs/loader:1373:14)
at Module._extensions…js (node:internal/modules/cjs/loader:1432:10)
at Module.load (node:internal/modules/cjs/loader:1215:32)
at Module._load (node:internal/modules/cjs/loader:1031:12)
at c._load (node:electron/js2c/node_init:2:17025)
at Module.require (node:internal/modules/cjs/loader:1240:19)
at require (node:internal/modules/helpers:179:18)
at Class.loadModuleDefaultConfig (/home/awwbaker/MagicMirror/modules/MMM-Remote-Control/node_helper.js:314:30)
at /home/awwbaker/MagicMirror/modules/MMM-Remote-Control/node_helper.js:268:26
at FSReqCallback.oncomplete (node:fs:198:5)
[2024-09-22 11:35:05.689] [INFO] System information:SYSTEM: manufacturer: ; model: ; raspberry: undefined; virtual: false
OS: platform: linux; distro: Debian GNU/Linux; release: 12; arch: arm64; kernel: 6.6.47+rpt-rpi-v8
VERSIONS: electron: 31.1.0; used node: 20.14.0; installed node: 22.9.0; npm: 10.8.3; pm2:
OTHER: timeZone: America/New_York; ELECTRON_ENABLE_GPU: undefined
[2024-09-22 11:35:13.286] [LOG] Initialize button monitor_control on PIN 6
[2024-09-22 11:35:13.293] [ERROR] Whoops! There was an uncaught exception…
[2024-09-22 11:35:13.318] [ERROR] Error: EINVAL: invalid argument, write
at Object.writeFileSync (node:fs:2346:20)
at exportGpio (/home/awwbaker/MagicMirror/modules/MMM-Buttons/node_modules/onoff/onoff.js:18:8)
at new Gpio (/home/awwbaker/MagicMirror/modules/MMM-Buttons/node_modules/onoff/onoff.js:172:36)
at Class.intializeButton (/home/awwbaker/MagicMirror/modules/MMM-Buttons/node_helper.js:74:19)
at Class.intializeButtons (/home/awwbaker/MagicMirror/modules/MMM-Buttons/node_helper.js:90:18)
at Class.socketNotificationReceived (/home/awwbaker/MagicMirror/modules/MMM-Buttons/node_helper.js:26:18)
at Socket. (/home/awwbaker/MagicMirror/js/node_helper.js:98:11)
at Socket.emit (node:events:519:28)
at Socket.emitUntyped (/home/awwbaker/MagicMirror/node_modules/socket.io/dist/typed-events.js:69:22)
at /home/awwbaker/MagicMirror/node_modules/socket.io/dist/socket.js:704:39
at process.processTicksAndRejections (node:internal/process/task_queues:77:11) {
errno: -22,
code: ‘EINVAL’,
syscall: ‘write’
}
[2024-09-22 11:35:13.335] -
@awwbaker yes as i posted before
errno: -22,
code: ‘EINVAL’,
syscall: ‘write’
}the os has changed how this needs to be done
i posted a link to suggestions on how to resolve it without code changesthe Log not found is caused by the remotecontrol module
-
Thank you, I tried the pinctrl to no avail. Thank you though! Anthony
-
@awwbaker did you solve this?
-
@sdetweil Sorry have been on travel last several weeks. No I never did. I have the remote control module in and working just never could not get the button push. I have mmm-GroveGesture installed and working with sensor. Still working towards getting modules to hide and show. Could I ask another question???
What can/should I do on this?:
[2024-10-28 10:10:15.299] [ERROR] ERROR! Could not validate main module js file. [2024-10-28 10:10:15.528] [ERROR] ReferenceError: Log is not defined at Object.<anonymous> (/home/awwbaker/MagicMirror/modules/MMM-RAIN-MAP/MMM-RAIN-MAP.js:28:158622) at Module._compile (node:internal/modules/cjs/loader:1484:14) at Module._extensions..js (node:internal/modules/cjs/loader:1564:10) at Module.load (node:internal/modules/cjs/loader:1295:32) at Module._load (node:internal/modules/cjs/loader:1111:12) at c._load (node:electron/js2c/node_init:2:17025) at Module.require (node:internal/modules/cjs/loader:1318:19) at require (node:internal/modules/helpers:179:18) at Class.loadModuleDefaultConfig (/home/awwbaker/MagicMirror/modules/MMM-Remote-Control/node_helper.js:318:30) at /home/awwbaker/MagicMirror/modules/MMM-Remote-Control/node_helper.js:272:26 at FSReqCallback.oncomplete (node:fs:198:5) ----------------------------------------------------
-
@awwbaker remote control is loading the main js from other modules, but in the wrong runtime context.
i don’t know why it is doing that
-
@sdetweil ,
Hmmm…thanks Sam!!! -
Hi guys, I’ve been trying to figure this out too. I think I’m close with these two files using ‘pinctrl’ instead of ‘/sys/class/gpio/’ but I can’t figure out what I’m missing.
Based on the console log it looks like there’s an issue in my node_helper file, possible with the socketNotification functions because I’m not seeing any of my test messages.
And based on the log files there may be something missing from the package.json file because sometimes I get this error “Error: Cannot find module ‘node helper’ MODULE_NOT_FOUND” but other times I don’t. And I tried running this fix but couldn’t get it to work.
[https://forum.magicmirror.builders/user/jorickjuh](link url)Other than that I’m not seeing any other errors and module does appear to be working but it’s just not processing any button presses. I’ll keep trying but I’ll post my progress so far on here in case someone can see what I’m missing.
test file:
Module.register("MMM-PinToggleTest", { defaults: { pin: 19, modulesToToggle: ["clock", "calendar"], interval: 1000 }, //consol.log("MMM-PinToggleTest is starting..."); start: function() { Log.info("MMM-PinToggleTest is starting, sending CONFIG..."); consol.log("MMM-PinToggleTest is starting, sending CONFIG..."); this.sendSocketNotification("CONFIG", { interval: this.config.interval, pin: this.config.pin }); }, start: function() { console.log("MMM-PinToggleTest started"); this.previousPinState = null; // Request initial pin check from the helper this.sendSocketNotification("CONFIG", this.config); }, 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:
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("node_helper for MMM-PinToggleTest has started."); // Confirm helper initialization this.previousPinState = null; this.lastChangeTime = 0; this.debounceDelay = 200; }, socketNotificationReceived: function(notification, payload) { if (notification === "CONFIG") { console.log("Received CONFIG in node_helper:", payload); // Log receipt of configuration this.config = payload; this.schedulePinCheck(); } }, schedulePinCheck: function() { console.log(`Setting up pin check every ${this.config.interval} ms`); // Confirmation log setInterval(() => { this.checkPinState(); }, this.config.interval); }, checkPinState: function() { const pinNumber = this.config.pin; exec(`pinctrl ${pinNumber}`, (error, stdout, stderr) => { if (error) { console.error(`Error reading GPIO pin ${pinNumber}: ${stderr}`); return; } const pinState = parseInt(stdout.trim(), 10); const now = Date.now(); console.log(`Current pin state for GPIO ${pinNumber}: ${pinState}`); if (pinState !== this.previousPinState && (now - this.lastChangeTime > this.debounceDelay)) { this.previousPinState = pinState; this.lastChangeTime = now; console.log(`Pin state changed to ${pinState} at ${new Date(now).toISOString()}`); this.sendSocketNotification("PIN_STATE", pinState); // Small delay to avoid multiple triggers //setTimeout(() => {}, 100); } }); } });
-
@ChrisLeduex well, you don’t have any source errors. altho you have 2 start: functions in the modulename.js
I see this as output of the pinctrl command on my pi 4
pinctrl 0: ip pu | hi // ID_SDA/GPIO0 = input 1: ip pu | hi // ID_SCL/GPIO1 = input 2: ip pu | hi // GPIO2 = input 3: ip pu | hi // GPIO3 = input 4: ip pu | hi // GPIO4 = input 5: ip pu | hi // GPIO5 = input 6: ip pu | hi // GPIO6 = input 7: ip pu | hi // GPIO7 = input 8: ip pu | hi // GPIO8 = input 9: ip pd | lo // GPIO9 = input 10: ip pd | lo // GPIO10 = input 11: ip pd | lo // GPIO11 = input 12: ip pd | lo // GPIO12 = input 13: ip pd | lo // GPIO13 = input 14: ip pn | hi // GPIO14 = input 15: ip pu | hi // GPIO15 = input 16: ip pd | lo // GPIO16 = input 17: ip pd | lo // GPIO17 = input 18: ip pd | lo // GPIO18 = input 19: ip pd | lo // GPIO19 = input 20: ip pd | lo // GPIO20 = input 21: ip pd | lo // GPIO21 = input 22: ip pd | lo // GPIO22 = input 23: ip pd | lo // GPIO23 = input 24: ip pd | lo // GPIO24 = input 25: ip pd | lo // GPIO25 = input 26: ip pd | lo // GPIO26 = input 27: ip pd | lo // GPIO27 = input 28: a5 pu | hi // RGMII_MDIO/GPIO28 = RGMII_MDIO 29: a5 pd | lo // RGMIO_MDC/GPIO29 = RGMII_MDC 30: a3 pu | lo // CTS0/GPIO30 = CTS0 31: a3 pn | lo // RTS0/GPIO31 = RTS0 32: a3 pn | hi // TXD0/GPIO32 = TXD0 33: a3 pu | hi // RXD0/GPIO33 = RXD0 34: a3 pn | hi // SD1_CLK/GPIO34 = SD1_CLK 35: a3 pu | hi // SD1_CMD/GPIO35 = SD1_CMD 36: a3 pu | hi // SD1_DATA0/GPIO36 = SD1_DAT0 37: a3 pu | hi // SD1_DATA1/GPIO37 = SD1_DAT1 38: a3 pu | hi // SD1_DATA2/GPIO38 = SD1_DAT2 39: a3 pu | hi // SD1_DATA3/GPIO39 = SD1_DAT3 40: a0 pn | lo // PWM0_MISO/GPIO40 = PWM1_0 41: a0 pn | lo // PWM1_MOSI/GPIO41 = PWM1_1 42: op -- pu | lo // STATUS_LED_G_CLK/GPIO42 = output 43: ip pu | hi // SPIFLASH_CE_N/GPIO43 = input 44: ip pu | hi // SDA0/GPIO44 = input 45: ip pu | hi // SCL0/GPIO45 = input 46: ip pu | lo // RGMII_RXCLK/GPIO46 = input 47: ip pu | lo // RGMII_RXCTL/GPIO47 = input 48: ip pd | lo // RGMII_RXD0/GPIO48 = input 49: ip pd | lo // RGMII_RXD1/GPIO49 = input 50: ip pd | lo // RGMII_RXD2/GPIO50 = input 51: ip pd | lo // RGMII_RXD3/GPIO51 = input 52: ip pd | lo // RGMII_TXCLK/GPIO52 = input 53and : ip pd | lo // RGMII_TXCTL/GPIO53 = input
and this for output of pinctrl 19
19: ip pd | lo // GPIO19 = input
so the “pinctrl 19” command and parseInt(“19: ip pd | lo // GPIO19 = input”, 10);
will return 19I think you meant pinctrl get 19, after sometime prior doing pinctrl set
pinctrl help
shows all it can do -
@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); } }); } });