Read the statement by Michael Teeuw here.
Trying to write my own Module...
-
MMM-EMonitor.js
Module.register ("MMM-EMonitor", { //default module config. defaults: { // Insert defaults here interval: 900000, // Every 15 mins security_key: null, animationSpeed: 1000 }, getStyles: function() { return ["MMM-EMonitor.css"]; }, // Define the start sequence start: function() { Log.log("Starting module: " + this.name); this.loaded = false; this.xml = null; this.url = 'https://api.emonitor.us/location/getCurrentData?security_key='; setInterval(this.getCurrentData(), this.config_interval); }, getCurrentData: function() { var self = this; var xhttp = new XMLHttpRequest(); xhttp.onreadystatechange = function() { if (this.readyState == 4 && this.status == 200) { self.xml = self.parseXML(this.responseText); self.loaded = true; self.updateDom(self.config.animationSpeed); } }; xhttp.open("GET", this.url+this.config.security_key, true); xhttp.send(); }, getDom: function(){ var wrapper = document.createElement("div"); if(!this.loaded) { wrapper.innerHTML = "Loading..."; return wrapper; } if(this.xml !== null){ var table = document.createElement("table"); table.classList.add("xsmall", "table"); var channels = this.xml.getElementsByTagName("channel"); for(var i = 0; i < channels.length; i++){ var row = document.createElement("tr"); for(var n = 0; n < channels[i].children.length; n++){ if(channels[i].children[n].tagName === "name" || channels[i].children[n].tagName === "watts"){ var element = document.createElement("td"); element.classList.add(channels[i].children[n].tagName); element.innerHTML = channels[i].children[n].textContent; row.appendChild(element); } table.appendChild(row); } } wrapper.appendChild(table); } else { console.log("Returned no Data"); wrapper.innerHTML = "NO DATA"; } return wrapper; }, parseXML: function(xmlStr){ return ( new window.DOMParser() ).parseFromString(xmlStr, "text/xml"); } });
Your config.js should have:
{ module: 'MMM-EMonitor', position: 'top_left', config: { security_key: 'XXXXXXXXXXXXXXX' //your security key } }
This just displays everything in a large table. You may want to modify the for loop to not display data when the wattage is 0, that should get rid of a bunch of rows.
-
This is awesome.
A few clarifying questions:
-
Is the purpose of the
xhttp.open("GET"...
line to make the API call to the website? Is this when the connection is made to the XML page? -
So, you’re going through each
"channel"
and creating a row in the table for each channel? And then for each channel’s name and wattage, a data object is created? -
If I didn’t have any
.css
file, would the data still show up?
Thanks for the clarifications, and again, thanks for the great support. This community is top-notch!
-
-
- yes the xmlhttprequest is also better known as ajax request
- for each channel a row will be created and for name and watts a column will be created with their specific values
- the data will still be displayed, but without any custom styling
-
I’m trying to display just the
names
where thewatts
that are != 0. I want both the values greater than 0 and the values less than 0 (in order to include the negative values from the solar generation).I attempted to modify the
getDom
. It is displaying everynames
in the .XML and shows thewatts
value only if it is != 0. But how do I also remove thenames
that are 0? The output currently looks like the following:Power Panel 66 Outlets 20 Heat Pump Oven East Solar Panel -70 West Solar Panel -50
getDom: function(){ var wrapper = document.createElement("div"); if(!this.loaded) { wrapper.innerHTML = "Loading..."; return wrapper; } if(this.xml !== null){ var table = document.createElement("table"); table.classList.add("xsmall", "table"); var channels = this.xml.getElementsByTagName("channel"); for(var i = 0; i < channels.length; i++){ var row = document.createElement("tr"); for(var n = 0; n < channels[i].children.length; n++){ if(channels[i].children[n].tagName === "name" || channels[i].children[n].tagName === "watts"){ var element = document.createElement("td"); element.classList.add(channels[i].children[n].tagName); if (channels[i].children[n].textContent != 0){ element.innerHTML = channels[i].children[n].textContent; row.appendChild(element); } } table.appendChild(row); } } wrapper.appendChild(table); } else { console.log("Returned no Data"); wrapper.innerHTML = "NO DATA"; } return wrapper; },
-
Looks like you need to modify your other if/then statement. The one you’ve modified checks both the name and watts to see if they are !=0. Since the name always !=0, it’s displayed.
-
It looks like the values are not updating. (The wattage values didn’t change at all overnight).
Should the line:
setInterval(this.getCurrentData(), this.config_interval);
be changed to:
setInterval(this.getCurrentData(), this.interval);
Are we calling the
interval
variable in the config incorrectly?Thanks!
-
@nbrenn
this.config.interval
-
For posterity, I modified the if statement as follows, to remove the row items that have a 0 for wattage:
if (channels[i].children[n].textContent != 0) { element.innterHTML = channels[i].children[n].textContent; row.appendChild(element); table.appendChild(row); } else { table.removeChild(row); }
-
Glad it all worked out for you!
-
I’m working on getting historical data (my API has a function
getHistoricalData
). The XML looks like the following:<Time Time="2016-11-03 00:00:00"> <channel channel="194882" name="Main Power Main Panel"> <kWh>0.319</kWh> </channel> <channel channel="194885" name="Outlet 1"> <kWh>0.000</kWh> </channel> <channel channel="194886" name="Solar Panel 1"> <kWh>-5.737</kWh> </channel> <channel channel="194887" name="Solar Panel 2"> <kWh>-4.877</kWh> </channel>
The difference between this XML output, and the XML output from my
getCurrentData
call, is thatname
is not it’s own element. With the old function,<name>
was in brackets. Now, it isname = ...
.Would be
getDom
be the same as it was forgetCurrentData
, or is it different since it’sname=
and not it’s own<name> ... </name>