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


Log in to reply
 

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