Display values from a JSON file hosted online



  • Want to display two fields from this file:

    https://www.dropbox.com/s/k1t6mjjc3knxp3a/dataset.json?raw=1

    Kind of like this:

    Customers today - Astronomy department:
    88

    The file looks like this:

    {
    "graph": {
    "title" : "Customers today",
    "total" : true,
    "datasequences" : [
    {
    "title" : "Astronomy department",
    "datapoints" : [
    { "title" : "Amount", "value" : 88 }
    	] } ] } }
    

    I want to display the amount value (88 in the example), and the titles, (Customers today and Astronomy department in the example).

    The module I have so far looks like this:

    
    
    Module.register("MMM-backlog",{
    
    
    
    	// Default module config.
    	defaults: {
    		text: "test text"
    	},
    
    	// Override dom generator.
    	getDom: function() {
    		var wrapper = document.createElement("div");
    		wrapper.innerHTML = this.config.text;
    		return wrapper;
    	}
    });
    
    
    

    Anybody able to help me get it working?


  • Moderator

    Quick and dirty, but should get you going :)

    You have to use the node_helper, because using XMLHttpRequest would result in an “origin error”.

    MMM-backlog.js

    /* global Module */
    
    /* Magic Mirror
     * Module: MMM-backlog
     *
     * By Stefan Krause http://yawns.de
     * MIT Licensed.
     */
    
    Module.register('MMM-backlog',{
    
    	defaults: {
    		units: config.units,
    		animationSpeed: 1000,
    		updateInterval: 1000 * 3600, //update every hour
    		refreshInterval: 1000 * 60 * 10, //refresh every minute		
    		timeFormat: config.timeFormat,
    		lang: config.language,
    
    		initialLoadDelay: 0, // 0 seconds delay
    		retryDelay: 2500,
    
    		fileUrl: "https://www.dropbox.com/s/k1t6mjjc3knxp3a/dataset.json?raw=1"
    	},
    
    	// Define required scripts.
    	getScripts: function() {
    		return ["moment.js"];
    	},
    
    	// Define requird styles
    	getStyles: function() {
    		return ["font-awesome.css"];
    	},
    
    	start: function() {
    		Log.info('Starting module: ' + this.name);
    
    		this.loaded = false;
    		this.sendSocketNotification('CONFIG', this.config);
    	},
    
    	getDom: function() {
    		var wrapper = document.createElement("div");
    
    		if (!this.loaded) {
    			wrapper.innerHTML = this.translate('LOADING');
    			wrapper.className = "dimmed light small";
    			return wrapper;
    		}
    
    		if (!this.data) {
    			wrapper.innerHTML = "No data";
    			wrapper.className = "dimmed light small";
    			return wrapper;
    		}
    
    		var t = this.data.graph;
    		var content = document.createElement("div");
    		content.innerHTML = "";	
    		
    		for (var i in t.datasequences) {
    			content.innerHTML += t.title  + " - " + t.datasequences[i].title + "<br />";
    			for (var j in t.datasequences[i].datapoints) {
    				content.innerHTML += t.datasequences[i].datapoints[j].title + ": " + t.datasequences[i].datapoints[j].value + "<br />";
    			}
    		}
    		
    		wrapper.appendChild(content);
    
    		return wrapper;
    	},
    
     	socketNotificationReceived: function(notification, payload) {
        		if (notification === "STARTED") {
    				this.updateDom();
    			}
    			else if (notification === "DATA") {
    				this.loaded = true;
    				this.processData(JSON.parse(payload));
    				this.updateDom();
        		}
    	},
    
    	/* processData(data)
    	 * Uses the received data to set the various values.
    	 *
    	 * argument data object - tide information received form worldtides.info
    	 */
    	processData: function(data) {
    
    		if (!data) {
    			// Did not receive usable new data.
    			// Maybe this needs a better check?
    			return;
    		}
    
    		this.data = data;
    
    		this.loaded = true;
    		this.updateDom(this.config.animationSpeed);
    	}
    
    });
    

    node_helper.js

    'use strict';
    
    /* Magic Mirror
     * Module: MMM-backlog
     *
     * By Stefan Krause http://yawns.de
     * MIT Licensed.
     */
    
    const NodeHelper = require('node_helper');
    var request = require('request');
    
    module.exports = NodeHelper.create({
    
    	start: function() {
    		this.started = false;
    		this.config = null;
    	},
    
    	getData: function() {
    		var self = this;
    		
    		var myUrl = this.config.fileUrl;
    				
    		request({
    			url: myUrl,
    			method: 'GET',
    		}, function (error, response, body) {
    			if (!error && response.statusCode == 200) {
    				self.sendSocketNotification("DATA", body);
    			}
    		});
    
    		setTimeout(function() { self.getData(); }, this.config.refreshInterval);
    	},
    
    	socketNotificationReceived: function(notification, payload) {
    		var self = this;
    		if (notification === 'CONFIG' && self.started == false) {
    			self.config = payload;
    			self.sendSocketNotification("STARTED", true);
    			self.getData();
    			self.started = true;
    		}
    	}
    });
    
    


  • wow! This looks great! I cant wait to try this out!

    Thank you so much! 👍🏻



  • @yawns HAVE MY BABIES!

    It works! Thank you so much! I’ll now start to play around with the CSS! Thank you so much! :)


  • Moderator

    Glad it gets you going. Of course you can add more divs/spans or even a table to place your output and adjust proper css to single lines or values.
    If you need explanation of single commands or routines just let us know.

    @looolz said in Display values from a JSON file hosted online:

    @yawns HAVE MY BABIES!

    I doubt my wife would be happy with that :rofl:



  • You are very kind!

    I’ve got a couple of issues so far:

    1: The module doesn’t seem to survive a manual refresh. For some reason, if I hit CTRL R to refresh, all other modules load, but this one is stuck at “loading…” If I do CTRL Q, quit the Magic Mirror and try again, it works. Even more strangely, it does correctly update on it’s own, when the JSON file changes. Just a minor thing.

    2: I’ve been trying to create en separate class for the value, so that I can style the number individually. So I tried to create an element that I can style with xlarge from the css file. But so far I’ve only been able to style the titles. I tried to read up on this on w3schools.com, but it’s evident that I lack a pillar of information to understand the syntax completely.

    How would change the code to make the numbervalue an element I can style in the CSS?


  • Moderator

    1: This is a know issue. If the module uses a node_helper, it does not survive a manual refresh of the webpage. It requires a restart of the magic mirror process. If someone knows how to get rid of this, I am more than happy to learn. @Module-Developers

    2:

    	getDom: function() {
    		var wrapper = document.createElement("div");
    
    		if (!this.loaded) {
    			wrapper.innerHTML = this.translate('LOADING');
    			wrapper.className = "dimmed light small";
    			return wrapper;
    		}
    
    		if (!this.data) {
    			wrapper.innerHTML = "No data";
    			wrapper.className = "dimmed light small";
    			return wrapper;
    		}
    
    		var t = this.data.graph;
    		var content = document.createElement("div");
    		var titleDiv = document.createElement("div");
    		var dataDiv = document.createElement("div");
    		var titleDataSpan = document.createElement("span");
    		var valueDataSpan = document.createElement("span");
    				
    		for (var i in t.datasequences) {
    
    			titleDiv.className = "LIST YOUR CLASSES HERE";
    			titleDiv.innerHTML = t.title  + " - " + t.datasequences[i].title;
    			content.appendChild(titleDiv);
    			for (var j in t.datasequences[i].datapoints) {
    
    				dataDiv.className = "LIST YOUR CLASSES HERE";
    
    				titleDataSpan.className = "LIST YOUR CLASSES HERE";
    				titleDataSpan.innerHTML = t.datasequences[i].datapoints[j].title + ":";
    				
    
    				valueDataSpan.className = "LIST YOUR CLASSES HERE";
    				valueDataSpan.innerHTML = t.datasequences[i].datapoints[j].value;
    				
    				dataDiv.appendChild(titleDataSpan);	
    				dataDiv.appendChild(valueDataSpan);	
    				content.appendChild(dataDiv);
    			}
    		}
    		
    		wrapper.appendChild(content);
    
    		return wrapper;
    	},
    

    You could even use the datapoint title (“amount” in this example), define a css class with this selector and add the datapoint title to the list of classnames ;)
    I did not test it, I just wrote it in notepad++, so there might be a typo. You could also try to add more entries to your JSON file to see if the loops are correct and fetch all data.



  • @yawns i could imagine that the start flag of the node_helper is still true so the getdata call gets skipped


  • Moderator

    @strawberry-3.141
    good point. Maybe I find some time at the weekend to debug this and check where it is stopping/skipping



  • @yawns Was that re-load issue ever resolved? I have my own basic issues and I’m considering using this code instead…


Log in to reply
 

Looks like your connection to MagicMirror Forum was lost, please wait while we try to reconnect.