• Recent
  • Tags
  • Unsolved
  • Solved
  • MagicMirror² Repository
  • Documentation
  • 3rd-Party-Modules
  • Donate
  • Discord
  • Register
  • Login
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.

Stuck in development

Scheduled Pinned Locked Moved Development
4 Posts 3 Posters 1.5k Views 2 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.
  • B Offline
    Baxer
    last edited by Baxer Jun 16, 2018, 7:47 PM Apr 23, 2018, 5:18 PM

    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()};
    	}
    });
    
    
    1 Reply Last reply Reply Quote 0
    • PatexP Offline
      Patex
      last edited by Apr 23, 2018, 9:48 PM

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

      B 1 Reply Last reply May 5, 2018, 8:51 PM Reply Quote 1
      • justjim1220J Offline
        justjim1220 Module Developer
        last edited by May 4, 2018, 6:53 AM

        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!!!

        "Life's Too Short To Dance With Ugly People"
        Jim Hallock - 1995

        1 Reply Last reply Reply Quote 0
        • B Offline
          Baxer @Patex
          last edited by May 5, 2018, 8:51 PM

          @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

          1 Reply Last reply Reply Quote 0
          • 1 / 1
          • 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