MagicMirror² v2.5.0 is available! For more information about this release, check out this topic.

Stuck in development



  • So im trying to build my own module without any real programming experence. With help from This post and MagicMirror-Module-Template i have gotten really really far but right now im stuck, im getting the results from the api in the console instead of it printing on the screen
    Any help would be greatly appreciated

    SHL.js

    Module.register("SHL", {
    	defaults: {
    		updateInterval: 60000,
    		retryDelay: 5000
    	},
    
    	requiresVersion: "2.1.0", // Required version of MagicMirror
    
    	start: function() {
    		var self = this;
    		var dataRequest = null;
    		var dataNotification = null;
    
    		//Flag for check if module is loaded
    		this.loaded = false;
    
    		// Schedule update timer.
    		this.getData();
    		setInterval(function() {
    			self.updateDom();
    		}, this.config.updateInterval);
    	},
    
    	/*
    	 * getData
    	 * function example return data and show it in the module wrapper
    	 * get a URL request
    	 *
    	 */
    	getData: function() {
    		var self = this;
    
    		var urlApi = "https://jsonplaceholder.typicode.com/posts/1";
    		var retry = true;
    
    		var dataRequest = new XMLHttpRequest();
    		dataRequest.open("GET", urlApi, true);
    		dataRequest.onreadystatechange = function() {
    			console.log(this.readyState);
    			if (this.readyState === 4) {
    				console.log(this.status);
    				if (this.status === 200) {
    					self.processData(JSON.parse(this.response));
    				} else if (this.status === 401) {
    					self.updateDom(self.config.animationSpeed);
    					Log.error(self.name, this.status);
    					retry = false;
    				} else {
    					Log.error(self.name, "Could not load data.");
    				}
    				if (retry) {
    					self.scheduleUpdate((self.loaded) ? -1 : self.config.retryDelay);
    				}
    			}
    		};
    		dataRequest.send();
    	},
    
    
    	/* scheduleUpdate()
    	 * Schedule next update.
    	 *
    	 * argument delay number - Milliseconds before next update.
    	 *  If empty, this.config.updateInterval is used.
    	 */
    	scheduleUpdate: function(delay) {
    		var nextLoad = this.config.updateInterval;
    		if (typeof delay !== "undefined" && delay >= 0) {
    			nextLoad = delay;
    		}
    		nextLoad = nextLoad ;
    		var self = this;
    		setTimeout(function() {
    			self.getData();
    		}, nextLoad);
    	},
    
    	getDom: function() {
    		var self = this;
    
    		// create element wrapper for show into the module
    		var wrapper = document.createElement("div");
    		// If this.dataRequest is not empty
    		if (this.dataRequest) {
    			var wrapperDataRequest = document.createElement("div");
    			// check format https://jsonplaceholder.typicode.com/posts/1
    			wrapperDataRequest.innerHTML = this.dataRequest.title;
    
    			var labelDataRequest = document.createElement("label");
    			// Use translate function
    			//             this id defined in translations files
    			labelDataRequest.innerHTML = this.translate("TITLE");
    
    
    			wrapper.appendChild(labelDataRequest);
    			wrapper.appendChild(wrapperDataRequest);
    		}
    
    		// Data from helper
    		if (this.dataNotification) {
    			var wrapperDataNotification = document.createElement("div");
    			// translations  + datanotification
    			wrapperDataNotification.innerHTML =  this.translate("UPDATE") + ": " + this.dataNotification.date;
    
    			wrapper.appendChild(wrapperDataNotification);
    		}
    		return wrapper;
    	},
    
    	getScripts: function() {
    		return [];
    	},
    
    	getStyles: function () {
    		return [
    			"SHL.css",
    		];
    	},
    
    	start: function () {
    		this.sendSocketNotification("GET_STANDINGS")
    	},
    
    	// Load translations files
    	getTranslations: function() {
    		//FIXME: This can be load a one file javascript definition
    		return {
    			en: "translations/en.json",
    			es: "translations/es.json"
    		};
    	},
    
    	processData: function(data) {
    		var self = this;
    		this.dataRequest = data;
    		if (this.loaded === false) { self.updateDom(self.config.animationSpeed) ; }
    		this.loaded = true;
    
    		// the data if load
    		// send notification to helper
    		this.sendSocketNotification("SHL-NOTIFICATION_TEST", data);
    	},
    
    	// socketNotificationReceived from helper
    	socketNotificationReceived: function (notification, payload) {
    		if(notification === "STANDINGS"){
    			// set dataNotification
    			this.dataNotification = payload;
    			this.updateDom();
    		}
    	},
    });
    

    node_helper.js

    
    var NodeHelper = require("node_helper");
    const shl = require("open-shl");
    const client = shl.connect({
        clientId:"XXXX", 
        clientSecret:"XXXX"
    });
    
    module.exports = NodeHelper.create({
    	
    	
    	teamStandings: function() {
    			  client.season(2017).statistics.teams.standings({teamIds: []})
    			     .then(teams => {
          			for (i = 0; i < 14; i++) {
            			a = i + 1;
           			  console.log(a + ": " + teams[i].team_code);
         				 };
    				     var standings = {};
    				     this.sendSocketNotification('STANDINGS', standings);
     			 });
    		},
    	// Override socketNotificationReceived method.
    
    	/* socketNotificationReceived(notification, payload)
    	 * This method is called when a socket notification arrives.
    	 *
    	 * argument notification string - The identifier of the noitication.
    	 * argument payload mixed - The payload of the notification.
    	 */
    	socketNotificationReceived: function(notification, payload) {
    		if (notification === "SHL-NOTIFICATION_TEST") {
    			// console.log("Working notification system. Notification:", notification, "payload: ", payload);
    			console.log("Working notification system.", notification) 
    		}
    		if (notification === "GET_STANDINGS"){
    			this.teamStandings();
    		}
    	},
    
    	// this you can create extra routes for your module
    	extraRoutes: function() {
    		var self = this;
    		this.expressApp.get("/SHL/extra_route", function(req, res) {
    			// call another function
    			values = self.anotherFunction();
    			res.send(values);
    		});
    	},
    
    	// Test another function
    	anotherFunction: function() {
    		return {date: new Date()};
    	}
    });
    
    


  • @Baxer said in Stuck in development:

    var standings = {};
    this.sendSocketNotification(‘STANDINGS’, standings);

    You are almost there. This is the one bit where you currently are missing code. You need to send the teams data via the socket notification system to the module.

    Since I have no idea how the data exactly looks like I can only give you the hint that you can either populate the standings object yourself (maybe it’s worth to take a look at arrays in javascript)

    var standings = [];
    
    for(myLoopCodition){
      standings.push(teams[i] ...);
    }
    

    or send the entire teams data via the socket and let the module handle it. Now in the getDom() function you can maybe create a nice table to display the data in a fitting way.


  • Module Developer

    I could seriously also use some help with developing a module…

    I have code that works great in HTML…

      var playlistId = "PLl_KM23gznEAZW-INW8ty4QNaHH8JCnNW"; // playlist ID found in the URL on YouTube (starts with PLI_) 
      var tag = document.createElement('script');
      tag.src = "https://www.youtube.com/iframe_api";  // needed to call iFrame API from YouTube
      var firstScriptTag = document.getElementsByTagName('script')[0];
      firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
      var player;
    
      function onYouTubeIframeAPIReady() {
        player = new YT.Player('player', {
          height: '411', // variable that can be changed to suit your need
          width: '548', // variable that can be changed to suit your need
          events: {
            'onReady': onPlayerReady,
            'onStateChange': onPlayerStateChange
          }
        });
      }
    
      // pulls the videos from the playlist and places then in an array for randomization
      var playlistArray;
      var playListArrayLength; // total number of videos in the playlist. Can be changed in the playlist on YouTube without having to change your code...
      var maxNumber; // equals to the number of videos in the playlist
      var oldNumber = 0;
      var NewNumber = 0;
    
      function newRandomNumber() {  // shuffles the videos and gets a random one ready to be played
        oldNumber = NewNumber;
        NewNumber = Math.floor(Math.random() * maxNumber);
        if (NewNumber = oldNumber) {
          newRandomNumber();
        } else {
          return NewNumber;
        }
      }
    
      function onPlayerReady(event) { // loads the playlist into the player
        player.loadPlaylist({
          'listType': 'playlist',
          'list': playlistId
        });
      }
      var firstLoad = true;
    
      function onPlayerStateChange(event) { // gets new random video after current one stops playing
        console.log(event.data);
        if (event.data == YT.PlayerState.ENDED) {
          player.playVideoAt(newRandomNumber());
        } else {
          if (firstLoad && event.data == YT.PlayerState.PLAYING) {
            firstLoad = false;
            playlistArray = player.getPlaylist();
            playListArrayLength = playlistArray.length;
            maxNumber = playListArrayLength;
            NewNumber = newRandomNumber();
            player.playVideoAt(newRandomNumber());
          }
        }
      }
    

    Now, I need it to work in a module so it will work in my MagicMirror… this is what I have come up with so far and am now stuck on where to go from here…

    Module.register("MMM-RandomYouTube", {
        // these parameters are defined here -- https://developers.google.com/youtube/player_parameters#Parameters
        defualts: {
            autoplay: true,
            color: "red", // can only be red or white
            controls: true,
            disablekb: false,
            fs: false,
            loop: true,
            modestbranding: false,
            rel: false,
            showinfo: false
        },
    
        requiresVersion: "2.1.0", // Required version of MagicMirror
    
        start: function () {
            var playlistId = "PLl_KM23gznEAZW-INW8ty4QNaHH8JCnNW";
            var tag = document.createElement('script');
            tag.src = "https://www.youtube.com/iframe_api";
    
            var firstScriptTag = document.getElementsByTagName('script')[0];
            firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
    
            var player;
    
            function onYouTubeIframeAPIReady() {
                player = new YT.Player('player', {
                    height: '420',
                    width: '708',
                    events: {
                        'onReady': onPlayerReady,
                        'onStateChange': onPlayerStateChange
                    }
    
                });
            }
        
    
            var playlistArray;
            var playListArrayLength;
            var maxNumber;
    
            var oldNumber = 0;
            var NewNumber = 0;
    
            function newRandomNumber() {
                oldNumber = NewNumber;
                NewNumber = Math.floor(Math.random() * maxNumber);
                if (NewNumber == oldNumber) {
                    newRandomNumber();
                } else {
                    return NewNumber;
                }
            },
    
            function onPlayerReady(event) {
                player.loadPlaylist({
                    'listType': 'playlist',
                    'list': playlistId
                });
            }
    
            var firstLoad = true;
    
            function onPlayerStateChange(event) {
                console.log(event.data);
                if (event.data == YT.PlayerState.ENDED) {
                    player.playVideoAt(newRandomNumber());
                } else {
                    if (firstLoad && event.data == YT.PlayerState.PLAYING) {
                        firstLoad = false;
                        playlistArray = player.getPlaylist();
                        playListArrayLength = playlistArray.length;
                        maxNumber = playListArrayLength;
                        NewNumber = newRandomNumber();
                        player.playVideoAt(newRandomNumber());
                    }
                }
    
            }
        });
    

    Any help with this will be greatly appreciated!!!



  • @patex said in Stuck in development:

    populate the standings object yourself

    If i would send the entire teams data how would i go about doing that? thx btw for the answer