MagicMirror Forum
    • Recent
    • Tags
    • Unsolved
    • Solved
    • MagicMirror² Repository
    • Documentation
    • 3rd-Party-Modules
    • Donate
    • Discord
    • Register
    • Login
    1. Home
    2. Alyx
    3. Posts
    A New Chapter for MagicMirror: The Community Takes the Lead
    Read the statement by Michael Teeuw here.
    A
    Offline
    • Profile
    • Following 0
    • Followers 0
    • Topics 6
    • Posts 69
    • Groups 0

    Posts

    Recent Best Controversial
    • RE: How to send a notification

      @sdetweil

      Hi Sam,

      My replies are getting flagged as spam apologies for the delay. But I think I found where the Selfie script sends out the notification. Do you think the other scripts I sent earlier are configured correctly?

      posted in Troubleshooting
      A
      Alyx
    • How to send a notification

      So I’ve been playing around with this or a while now but cant seem to get it. I essentially want to send a notification to a modules using another. Sounds simple but I cant find any examples on how to do this. If anyone can help that would be great I’m sure its something simple in the end but please have a look at the below files and let me know what I’m missing and where, many thanks in advance!

      Node_Helper.js for MMM-ALEXACONTROL

      /**
       * Magic Mirror
       * Node Helper: MMM-AlexaControl
       * 
       * By JoChef2
       * MIT Licensed.
       */
      
      var NodeHelper = require("node_helper");
      var FauxMo = require('node-fauxmo');
      var pm2 = require('pm2');
      const exec = require("child_process").exec;
      
      module.exports = NodeHelper.create({
      	
      	start: function () {
              console.log('MMM-AlexaControl helper, started...');
              this.config = null;
              this.setDevicesCounter = 0;  //  Counter for only one node_helper start look line 225 
          },
      	
          formattedName: function(devname,actionString){
              var result=actionString
              if(devname != undefined){
                  var s = actionString.split(' ')
                  if(s.length>1)
                      s.splice(1,0,devname)
                  else
                      s.unshift(devname)
                  result = s.join(' ')
              }        
              return result;
          },
          
      	setDevices: function(){
              _this = this;
      
              cD = this.customDevices(this.config.devices);
              nD = this.notificationDevices(cD, this.config.notifications);
              coD = this.commandDevices(nD, this.config.commands)
              pD = this.pageDevices(coD);
              mD = this.menuDevices(pD);
              //console.log(pD);
              //console.log(mD);
      
              fauxMoPages = new FauxMo(mD);       // creates fauxmo devices
          },
      
          customDevices : function(customD){      //  creates your custom devices from config
              _this = this
              for(i = 0; i < Object.keys(customD.devices).length; i++){
                  if(customD.devices[i].port === undefined){
                      customD.devices[i].port = _this.config.startPort + 30 + i;
                  }
                  customD.devices[i].handler = new Function('action', customD.devices[i].handler)
              }
              return customD;
          },
      
          notificationDevices: function(notificationD, notifications){    //  creates your notification devices
              _this = this
      
              counter = 0 + Object.keys(notificationD.devices).length        
              _this.n = []
      
              for(i = 0; i < Object.keys(notifications).length; i++){
                  device = {}
                  device.name = _this.formattedName(_this.translations["deviceName"],notifications[i].name)
                  if(notifications[i].port === undefined){
                      device.port = _this.config.startPort + 50 + i
                  }else{
                      device.port = notifications[i].port
                  }
                  if(notifications[i].OnOff){
                      _this.n[i] = notifications[i].notification
                      device.handler = new Function('action', 'if(action === 1){_this.sendSocketNotification("CUSTOM",' + JSON.stringify(_this.n[i][0]) + ')}else{_this.sendSocketNotification("CUSTOM",' + JSON.stringify(_this.n[i][1]) + ')}')
                  }else{
                      _this.n[i] = notifications[i].notification
                      device.handler = new Function('action', '_this.sendSocketNotification("CUSTOM",' + JSON.stringify(_this.n[i]) + ')')
                  }
                  notificationD.devices[i + counter] = device
              }
              return notificationD;
          }, 
      
          commandDevices: function(commandD, commands){
              _this = this
      
              counter = 0 + Object.keys(commandD.devices).length        
              _this.n = []
              _this.opts = { timeout: 8000 };
              _this.exec = exec
      
              for(i = 0; i < Object.keys(commands).length; i++){
                  device = {}
                  device.name = _this.formattedName(_this.translations["deviceName"],commands[i].name)
                  if(commands[i].port === undefined){
                      device.port = _this.config.startPort + 75 + i
                  }else{
                      device.port = commands[i].port
                  }
                  _this.n[i] = commands[i].command
                  if(commands[i].OnOff){
                      device.handler = new Function('action', 'if(action === 1){_this.exec(' + JSON.stringify(_this.n[i][0]) + '), _this.opts, (error, stdout, stderr) => {_this.checkForExecError(error, stdout, stderr); }}else{_this.exec(' + JSON.stringify(_this.n[i][1]) + '), _this.opts, (error, stdout, stderr) => {_this.checkForExecError(error, stdout, stderr); }}')
                  }
                  else{
                      device.handler = new Function('action', 'if(action === 1){_this.exec(' + JSON.stringify(_this.n[i]) + '), _this.opts, (error, stdout, stderr) => {_this.checkForExecError(error, stdout, stderr); }}')
                  }
                  commandD.devices[i + counter] = device
              }
              return commandD;
          },
      
          pageDevices: function(pageD){      //  creates your page devices
              _this = this;
      
              counter = 0 + Object.keys(pageD.devices).length
              this.pPort = _this.config.startPort
      
              if(_this.config.pages > 0){
                  for(i = 0; i < _this.config.pages; i++){
                      device = {}
                      device.name = _this.formattedName(_this.translations["deviceName"],_this.translations["page"] + (i + 1))
                      device.port = _this.pPort - 100
                      device.handler = new Function('action', `_this.sendSocketNotification("PAGE_CHANGED", ` + i +`)`)
      
                      pageD.devices[i + counter] = device
                      this.pPort++
                  }
              }
              return pageD
          },
      
          menuDevices: function(menuD){       //  create your devices to control the Mirror and pi
              _this = this;
              var opts = { timeout: 8000 };
              //console.log("menu device ")
              counter = 0 + Object.keys(menuD.devices).length
      
              if(this.config.refresh){
                  device = {}
                  device.name = _this.formattedName(_this.translations["deviceName"],_this.translations["refresh"])
                  device.port = _this.config.startPort
                  device.handler = function(action) {_this.sendSocketNotification("ACTION", "refresh")}
      
                  menuD.devices[counter] = device;
                  counter++;
              }
              _this.config.startPort++
      
              if(this.config.restart){        // only with PM2
                  device = {}
                  device.name = _this.formattedName(_this.translations["deviceName"],_this.translations["restart"])
                  device.port = _this.config.startPort
                  device.handler = function(action) {
                      pm2.connect((err) => {
                          if (err) {
                              console.error(err);
                          }
              
                          console.log("Restarting PM2 process: " + _this.config.pm2ProcessName);
                          pm2.restart(_this.config.pm2ProcessName, function(err, apps) {
                              pm2.disconnect();
                              if (err) { console.log(err); }
                          });
                      });
                  }
                  
                  menuD.devices[counter] = device;
                  counter++;
              }
              _this.config.startPort++
              
              if(this.config.stop){        // only with PM2
                  device = {}
                  device.name = _this.formattedName(_this.translations["deviceName"],_this.translations["stop"])
                  device.port = _this.config.startPort
                  device.handler = function(action) {
                      pm2.connect((err) => {
                          if (err) {
                              console.error(err);
                          }
              
                          console.log("Stopping PM2 process: " + _this.config.pm2ProcessName);
                          pm2.stop(_this.config.pm2ProcessName, function(err, apps) {
                              pm2.disconnect();
                              if (err) { console.log(err); }
                          });
                      });
                  }
      
                  menuD.devices[counter] = device;
                  counter++;
              }
              _this.config.startPort++
              
              if(this.config.reboot){        //reboot the pi
                  device = {}
                  device.name = _this.formattedName(_this.translations["deviceName"],_this.translations["reboot"])
                  device.port = _this.config.startPort
                  device.handler = function(action) {
                      exec("sudo shutdown -r now", opts, (error, stdout, stderr) => {
                           _this.checkForExecError(error, stdout, stderr); 
                          });
                      }
                  menuD.devices[counter] = device;
                  counter++;
              }
              _this.config.startPort++
              
              if(this.config.shutdown){        // shutdwon the pi
                  device = {}
                  device.name = _this.formattedName(_this.translations["deviceName"],_this.translations["shutdown"])
                  device.port = _this.config.startPort
                  device.handler = function(action) {
                      exec("sudo shutdown -h now", opts, (error, stdout, stderr) => {
                          _this.checkForExecError(error, stdout, stderr); 
                      });
                  }           
                  menuD.devices[counter] = device;
                  counter++;
              }
              _this.config.startPort++
      
              /**
               * for me worked only vcgencmd display_power 0 and vcgencmd display_power 1
               * probably for you work tvservice --off and tvservice --preferred
               * test it in terminal if you aren't sure
               */
              
              if(this.config.monitorToggle){ 
              	console.log("monitorToggle requested")
                  device = {}
                  device.name = _this.formattedName(_this.translations["deviceName"],_this.translations["monitor"])
                  device.port = _this.config.startPort
                  if(this.config.vcgencmd =='vcgencmd'){
                      device.handler = function(action) {     
                          if(action === 1){
                              exec("vcgencmd display_power 1", opts, (error, stdout, stderr) => {
                                  _this.checkForExecError(error, stdout, stderr); 
                              });
                          }if(action === 0){
                              exec("vcgencmd display_power 0", opts, (error, stdout, stderr) => {
                                  _this.checkForExecError(error, stdout, stderr); 
                              });
                          }
                      }
                  }
                  else if(this.config.vcgencmd =='tvservice'){
                      device.handler = function(action) {     
                          if(action === 1){
                              exec("tvservice --preferred", opts, (error, stdout, stderr) => {
                                  _this.checkForExecError(error, stdout, stderr);
                              });
                          }if(action === 0){
                              exec("tvservice --off", opts, (error, stdout, stderr) => {
                                  _this.checkForExecError(error, stdout, stderr);
                              });
                          }
                      }
                  }
                  else if(this.config.vcgencmd =='cec-client'){
                      device.handler = function(action) {     
                          if(action === 1){
                              exec("echo \'on "+ _this.config.cecAddress +"\' | cec-client -s -d 1", opts, (error, stdout, stderr) => {
                                  _this.checkForExecError(error, stdout, stderr);
                              });
                          }if(action === 0){
                              exec("echo \'standby "+ _this.config.cecAddress +"\' | cec-client -s -d 1", opts, (error, stdout, stderr) => {
                                  _this.checkForExecError(error, stdout, stderr);
                              });
                          }
                      }
                  }
                  else if(this.config.vcgencmd =='hide'){
                  	console.log("configuring toggle with hide")
                  	device.handler = function(action) {     
                  		console.log("received monitor toggle with hide action="+action)
                 	 		_this.sendSocketNotification('MONITOR_ACTION', action?"SLEEP_WAKE":"SLEEP_HIDE")
                		}	
                  }
                  else{
                      device.handler = function(action){
                          console.log("Please configure the option vcgencmd")
                      }
                  }
                  menuD.devices[counter] = device;
                  counter++;
              }
              _this.config.startPort++
      
              if(this.config.usb){        // toggle usb power of your pi
                  device = {}
                  device.name = _this.formattedName(_this.translations["deviceName"],_this.translations["usb"])
                  device.port = _this.config.startPort
                  device.handler = function(action) {
                      if(action === 0){
                          exec("echo '1-1' |sudo tee /sys/bus/usb/drivers/usb/unbind", opts, (error, stdout, stderr) => {
                              _this.checkForExecError(error, stdout, stderr); 
                          });
                      }
                      else{
                          exec("echo '1-1' |sudo tee /sys/bus/usb/drivers/usb/bind", opts, (error, stdout, stderr) => {
                              _this.checkForExecError(error, stdout, stderr); 
                          });
                      }
                  }           
                  menuD.devices[counter] = device;
                  counter++;
              }
              _this.config.startPort++
              return menuD; 
          },
      
        /*  monitorOff: function(){
              var opts = { timeout: 8000 };
              if(this.config.vcgencmd){
                  exec("vcgencmd display_power 0", opts, (error, stdout, stderr) => {
                      _this.checkForExecError(error, stdout, stderr); 
                  });
              }else{
                  exec("tvservice --off", opts, (error, stdout, stderr) => {
                      _this.checkForExecError(error, stdout, stderr);
                  });
              }
          }, */
      
          checkForExecError: function(error, stdout, stderr) {
              if (stderr) {
                  console.log('stderr: "' + stderr + '"');
                  return 1;
              }
              if (error !== null) {
                  console.log('exec error: ' + error);
                  return 1;
              }
              return 0;
          },
          
      	socketNotificationReceived: function(notification, payload) {
      		if(notification === "SET_DEVICE"){      //  set all your devices
                  this.config = payload;
                  if(this.setDevicesCounter === 0){   //  set your devices only the first time a 
                      this.setDevices();              //  notification is received
                      this.setDevicesCounter++;
                  }
              }
              if(notification === "TRANSLATIONS"){    //  get translations and put them in an array
                  this.translations = [];            
                  this.translations = payload;
      		}
      	}	
      });
      
      

      MMM- AlexaControl config.js

      /**
       * Magic Mirror
       * Module: MMM-AlexaControl
       * 
       * By JoChef2
       * MIT Licensed.
       */
      
      Module.register("MMM-AlexaControl",{
           
          defaults:{
              image: true,    //  shows the image
              height: 265,    // heigth of the image
              width: 265,     // width of the image
              pages: 0,       //  number off pages in MMM-Pages module. 0 means you doesn't use it
              devices: {      //  empty object for your custom devices
                  devices: []
              },
              notifications: [],  //  empty array for your notification devices
              commands: [],       // empty array for your command devices
              startPort: 11000,   //  the lowest used port
              refresh: true,      //  refresh your Mirror
              restart: true,      //  restart your Mirror with pm2
              stop: true,         //  stops your Mirror with pm2
              reboot: false,      //  reboot your pi
              shutdown: false,    //  shutdown your pi
              pm2ProcessName: "mm",  //  name of your pm2 process
              monitorToggle: true,   //  switch your monitor on and off
              vcgencmd: 'vcgencmd',  //  command you use for monitor toggle
              cecAddress: "0.0.0.0", //  Address for the cec-client
              usb: false          // toggle usb power of your pi
          },
      
          getTranslations: function(){            // add more translations
              return {
                  en: "translations/en.json",
                  de: "translations/de.json"
              }
          },
      
          start: function(){
              Log.log('Starting module: ' + this.name);
      
              // send all translations to node_helper
              this.sendSocketNotification('TRANSLATIONS', {"monitor": this.translate("MONITOR"), "shutdown": this.translate("SHUTDOWN"), "reboot": this.translate("REBOOT"), "page": this.translate("PAGE"), "refresh": this.translate("REFRESH"), "restart": this.translate("RESTART"), "stop": this.translate("STOP"), "usb": this.translate("USB"), "deviceName":this.translate(this.config.deviceName)});
              this.sendSocketNotification('SET_DEVICE', this.config);  // send the config to node_helper
          },
      
          getDom: function(){             // returns only an image or an empty div (necessary for MMM-Pages)
              if(this.config.image){
                  let img = document.createElement("img");
                  img.classList = "img";
                  img.src = "MMM-AlexaControl/AlexaLogoGrey.png";
                  img.height = this.config.height;
                  img.width = this.config.width;
                  return img;
              }else{
                  return document.createElement("div");
              }
          },
      
          socketNotificationReceived: function(notification, payload) {
              if(notification === "PAGE_CHANGED"){              //  change pages of MMM-Pages
                  this.sendNotification("PAGE_CHANGED", payload);
              }
              if(notification === "ACTION"){                    //  refresh the Mirror
                  if(payload === "refresh"){
                      window.location.reload(true);
                  }
              } 
              if(notification === "SELFIE_SHOOT"){
                  this.sendNotification("SELFIE_SHOOT");  //  send any notification to any module
              }
              if(notification =='MONITOR_ACTION'){
                  Log.log('RECEIVE monitor NOTIFICATION='+payload)
                  this.sendNotification(notification,payload)
              }
          }
       });
      
      

      Config.js

      /* Magic Mirror Config Sample
       *
       * By Michael Teeuw https://michaelteeuw.nl
       * MIT Licensed.
       *
       * For more information on how you can configure this file
       * see https://docs.magicmirror.builders/getting-started/configuration.html#general
       * and https://docs.magicmirror.builders/modules/configuration.html
       */
      let config = {
      	address: "localhost", 	// Address to listen on, can be:
      							// - "localhost", "127.0.0.1", "::1" to listen on loopback interface
      							// - another specific IPv4/6 to listen on a specific interface
      							// - "0.0.0.0", "::" to listen on any interface
      							// Default, when address config is left out or empty, is "localhost"
      	port: 8080,
      	basePath: "/", 	// The URL path where MagicMirror is hosted. If you are using a Reverse proxy
      					// you must set the sub path here. basePath must end with a /
      	ipWhitelist: ["127.0.0.1", "::ffff:127.0.0.1", "::1"], 	// Set [] to allow all IP addresses
      															// or add a specific IPv4 of 192.168.1.5 :
      															// ["127.0.0.1", "::ffff:127.0.0.1", "::1", "::ffff:192.168.1.5"],
      															// or IPv4 range of 192.168.3.0 --> 192.168.3.15 use CIDR format :
      															// ["127.0.0.1", "::ffff:127.0.0.1", "::1", "::ffff:192.168.3.0/28"],
      
      	useHttps: false, 		// Support HTTPS or not, default "false" will use HTTP
      	httpsPrivateKey: "", 	// HTTPS private key path, only require when useHttps is true
      	httpsCertificate: "", 	// HTTPS Certificate path, only require when useHttps is true
      
      	language: "en",
      	locale: "en-UK",
      	logLevel: ["INFO", "LOG", "WARN", "ERROR"], // Add "DEBUG" for even more logging
      	timeFormat: 12,
      	units: "metric",
      	serverOnly:  true,
      	// local for armv6l processors, default
      	//   starts serveronly and then starts chrome browser
      	// false, default for all NON-armv6l devices
      	// true, force serveronly mode, because you want to.. no UI on this device
      
      	modules: [
      			{
      		disabled: false,
      		module:"MMM-Config",
      		position:"top_right",  // the QR code (if requested) will appear here
      		config:{
      			showQR: false,
      			//restart: "pm2",
      			//force_update: true,
      			//debug: true
      			
      		}
      	},
      	
          {
              module: 'MMM-AlexaControl',
              position: 'middle_center',
      	notifications:[
          {
              name: 'Next page',
              port: 11102,
              OnOff: false,
              notification: ["PAGE_INCREMENT", 'payload']
          },
           {
              name: 'Previous page',
              port: 11103,
              OnOff: false,
              notification: ["PAGE_DECREMENT", 'payload']
          },
          {
              name: 'Selfie',
              port: 11104,
              OnOff: false,
              notification: ["SELFIE_SHOOT"]
          }
      ],
      
      	config:{
      		
                  image: true,
      	    deviceName: "mirror",
                  pm2ProcessName: "mm",
                  vcgencmd: "hide",
      	    startPort: 11001,
      	    refresh: true,
      	    restart: true,
      	    //stop: true,
      	    reboot: true,
      	    shutdown: true,
      	    monitorToggle: true,
      	    //cecAddress: "0.0.0.0",
      	    //usb: false
      	    pages: 2,
              }
          },
          {
          module: 'MMM-SleepWake',
          config:{
             //delay:  15,               // default
             mode: 'pi'
          }
      },
       {
              module: 'MMM-pages',
      	
              config: {
      		pages: 2,
                      modules:
                          [[ "MMM-Astro" ],
                           [ "MMM-OpenWeatherMapForecast", "compliments" ]],
                      fixed: [ "clock", "MMM-page-indicator" ],
                      hiddenPages: {
                          "screenSaver": [ "clock", "MMM-SomeBackgroundImageModule" ],
                          "admin": [ "MMM-ShowMeSystemStatsModule", "MMM-AnOnScreenMenuModule" ],
                      },
              }
          },
          {
              module: 'MMM-page-indicator',
              position: 'bottom_bar',
              config: {
                  pages: 2,
              }
          },
          {
      	disabled: false,
      	module: "MMM-Selfieshot",
          position: "bottom_center",
      	config: {
          displayButton: "portrait",
      	storePath: "/media/smartmirror/Storage/Photos",
      	width:1280,
      	height:720,
      	quality: 100,
      	device: null,
      	shootMessage: "Smile!",
      	shootCountdown: 3,
      	displayCountdown: true,
      	displayResult: true,
      	playShutter: true,
      	shutterSound: "shutter.mp3",
      	}
      },
      
      
      
      		{
              disabled: false,
              module: 'MMM-Astro',
              position: 'top_left',
      		      config: {
      		      sign: "leo",
      		      iconset: "4",
      		      extend: false,
      		             }
             },
             {
        		module: "MMM-OpenWeatherMapForecast",
        		header: "Weather",
        		position: "top_right",
        		classes: "default everyone",
        		disabled: true,
        		config: { 
          			iconset: "4c",
          			units: "metric",
          			useAnimatedIcons: true,
          			concise: false,
          			forecastLayout: "table",
          			showWind: true
        			}
      		},
      		
      
      
      		{
      			module: "alert",
      		},
      		{
      			module: "updatenotification",
      			position: "top_bar"
      		},
      		{
      			module: "clock",
      			position: "top_center"
      		},
      		
      		{
      			module: "compliments",
      			position: "lower_third"
      		},
      		
      		
      		
      	]
      };
      
      /*************** DO NOT EDIT THE LINE BELOW ***************/
      if (typeof module !== "undefined") {module.exports = config;}
      
      
      posted in Troubleshooting
      A
      Alyx
    • RE: Are you tired of editing config.js, or have trouble doing it, see my new module

      @alyx ok I found the issue, I commented out all the options in alexa and then ran them individually and etc.

      Turns out the notification/ command and devices options werent configured correctly by the conf generator. after commenting those out I can now find them on alexa

      posted in Utilities
      A
      Alyx
    • RE: Are you tired of editing config.js, or have trouble doing it, see my new module

      @sdetweil Ive rebooted the machine 3 times at this point ahah, I have an echo3 would that be considered new? I know the 4th gen is the latest

      posted in Utilities
      A
      Alyx
    • RE: Are you tired of editing config.js, or have trouble doing it, see my new module

      @sdetweil I did delete and rediscover but the thing is they arent showing up in the discovery now lol

      posted in Utilities
      A
      Alyx
    • RE: Are you tired of editing config.js, or have trouble doing it, see my new module

      @sdetweil
      Yes thats what I mean I haven’t changed anything like that although. I just used the script and the generated config file. It seems alexa can no longer find the devices and is displaying them as offline

      posted in Utilities
      A
      Alyx
    • RE: Are you tired of editing config.js, or have trouble doing it, see my new module

      @alyx ok screw that its working now all of a sudden ahaha

      The alexa thing still isnt working tho

      posted in Utilities
      A
      Alyx
    • RE: Are you tired of editing config.js, or have trouble doing it, see my new module

      @sdetweil Before I was able to connect my alexa as a smart device with pm2 but now its not showing at all on alexa is what i mean.

      Yep that the link I use but I get the the home page and its the same blank interface as before with no modules tab or anything? Like I just used it to make the latest conf file so I know it works some how haha

      posted in Utilities
      A
      Alyx
    • RE: Are you tired of editing config.js, or have trouble doing it, see my new module

      @sdetweil OK back working now with that thanks! Although the conf for my pm2 seems to be not working anymore, I think I saw a similar issue somewhere in the comments here?

      Also I cant get the conf page anymore cause it can no longer get /modules/MMM-Config/review

      ?

      posted in Utilities
      A
      Alyx
    • RE: Are you tired of editing config.js, or have trouble doing it, see my new module

      @sdetweil Ah no worries was out for some materials to build the mirror frame myself haha

      posted in Utilities
      A
      Alyx
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 3 / 7