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.2k 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.
    • S Offline
      sdetweil @ChrisLeduex
      last edited by sdetweil

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

      I think you meant pinctrl get 19, after sometime prior doing pinctrl set

      pinctrl help
      shows all it can do

      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 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
                • 3 / 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