MagicMirror Forum
    • Recent
    • Tags
    • Unsolved
    • Solved
    • MagicMirror² Repository
    • Documentation
    • 3rd-Party-Modules
    • Donate
    • Discord
    • Register
    • Login
    A New Chapter for MagicMirror: The Community Takes the Lead
    Read the statement by Michael Teeuw here.

    Problem Adding Buttons & required Remote-Control Modules

    Scheduled Pinned Locked Moved Solved Troubleshooting
    26 Posts 4 Posters 2.7k Views 4 Watching
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • C Offline
      ChrisLeduex @sdetweil
      last edited by

      @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);
            }
          });
        }
      });
      
      S 1 Reply Last reply Reply Quote 0
      • S Offline
        sdetweil @ChrisLeduex
        last edited by

        @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

        Sam

        How to add modules

        learning how to use browser developers window for css changes

        C 1 Reply Last reply Reply Quote 0
        • C Offline
          ChrisLeduex @sdetweil
          last edited by

          @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.

          S 1 Reply Last reply Reply Quote 0
          • S Offline
            sdetweil @ChrisLeduex
            last edited by

            @ChrisLeduex buttons is interrupt driven, but can be changed to polling like you are doing

            Sam

            How to add modules

            learning how to use browser developers window for css changes

            C 1 Reply Last reply Reply Quote 0
            • C Offline
              ChrisLeduex @sdetweil
              last edited by

              @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
                    
                  }
                }
              });
              
              1 Reply Last reply Reply Quote 0
              • S sdetweil has marked this topic as solved on
              • 1
              • 2
              • 3
              • 2 / 3
              • First post
                Last post
              Enjoying MagicMirror? Please consider a donation!
              MagicMirror created by Michael Teeuw.
              Forum managed by Sam, technical setup by Karsten.
              This forum is using NodeBB as its core | Contributors
              Contact | Privacy Policy