Read the statement by Michael Teeuw here.
Trying to fix my module
-
Hello, I come to you because I started trying to create my own module. Because I didn’t know anything about javascript, html and css 2 weeks ago and not much in programmation either, I pretty much learned everything in 2 weeks so please, be indulgent :p
The module I’m creating is supposed to display the data from a french public transport API. I worked on the display using a local server, just to test things out, I made it work, then I tried to implement it to my magic mirror, but here started the problems, I used the default modules as a guide and tried to move the diffrents pieces where they should be and now, I have this, but when I start my mirror, the screen stays black and it doesn’t start:
Module.register(“schedules”, {
defaults: { updateInterval: 20000 fadeSpeed: 4000 }, getScripts: function() { return ["moment.js"] }, getStyles: function() { return ["font-awesome.css", "schedules.css"] }, start: function() { Log.info("Starting module: " + this.name); var self = this; setInterval(function() { self.updateDom(self.config.fadeSpeed); }, this.config.updateInterval); }, getDom: function() { dataDirSM = loadJSON("https://api-ratp.pierre-grimaud.fr/v2/rers/B/stations/les+baconnets?destination=robinson+saint+remy+les+chevreuse&endingstation=les+baconnets") data = loadJSON("https://api-ratp.pierre-grimaud.fr/v2/rers/B/stations/les+baconnets?destination=charles+de+gaulle+mitry+claye&endingstation=les+baconnets"); setTimeout(function() { var wrapper = document.createElement("div") var realtable = document.createElement('table'); realtable.appendChild(this.createUpperRow()); var row1 = document.createElement('tr') row1.appendChild(this.boxHeader(data.response.schedules[0].message)) row1.appendChild(this.boxHeader(data.response.schedules[0].id)) row1.appendChild(this.boxHeader(dataDirSM.response.schedules[0].id)) row1.appendChild(this.boxHeader(dataDirSM.response.schedules[0].message)) realtable.appendChild(row1) var row2 = document.createElement('tr') row2.appendChild(this.boxHeader(data.response.schedules[1].message)) row2.appendChild(this.boxHeader(data.response.schedules[1].id)) row2.appendChild(this.boxHeader(dataDirSM.response.schedules[1].id)) row2.appendChild(this.boxHeader(dataDirSM.response.schedules[1].message)) realtable.appendChild(row2) var row3 = document.createElement('tr') row3.appendChild(this.boxHeader(data.response.schedules[2].message)) row3.appendChild(this.boxHeader(data.response.schedules[2].id)) row3.appendChild(this.boxHeader(dataDirSM.response.schedules[2].id)) row3.appendChild(this.boxHeader(dataDirSM.response.schedules[2].message)) realtable.appendChild(row3) wrapper.appendChild(realtable) return wrapper }, (5 * 1000)); }, createUpperRow: function() { function createUpperRow() { var firstTableRow = document.createElement('tr'); var tableh1 = document.createElement('th'); tableh1.classList.add('align-left'); var tx1 = document.createTextNode('Time'); tableh1.appendChild(tx1); firstTableRow.appendChild(tableh1); var tableh2 = document.createElement('th'); tableh2.classList.add('align-left'); var tx2 = document.createTextNode('Paris'); tableh2.appendChild(tx2); firstTableRow.appendChild(tableh2); // deuxième moitier var tableh3 = document.createElement('th'); tableh3.classList.add('align-right'); var tx3 = document.createTextNode('Sud'); tableh3.appendChild(tx3); firstTableRow.appendChild(tableh3); var tableh4 = document.createElement('th'); tableh4.classList.add('align-right'); var tx4 = document.createTextNode('Time'); tableh4.appendChild(tx4); firstTableRow.appendChild(tableh4); return firstTableRow; }, boxHeader: function(inside) { if (inside == 'Train à l\'approche' || inside == 'Train à quai') { inside = 'no way' } else if (inside == 'Train retardé') { inside = 'retard' } var fillNode = document.createTextNode(inside); var realBox = document.createElement('td') realBox.appendChild(fillNode); return realBox; } })
and my css file :
.schedules .logo {
margin-right: 5px;
}.schedules .centered {
text-align: center;
}.schedules .table {
border-spacing: 10px 0px;
border-collapse: separate;
}(I don’t know why it doesn’t auto format)
if you guys had little hints for me to fix my mistakes, I’ll be highly thankful.
-
what jumped on my eyes on the first look,
the getDom function requires a synchronous answer, but with the timeout it’s asynchronous, you should load your data outside of this function and in getdom check if the data is there otherwise display a placeholder, then when you received data in the other function you call updateDom to refresh your display
and there is a ratp module out there, maybe you will extend this one instead of creating a new one https://github.com/lgmorand/MMM-Ratp
-
Thank you for your reply, I didn’t know about this synchronous problem. But I think I saw that the start function is only called once, not each reload, so in which function should I get the data ?
I couldn’t find the ratp module you told me about, if you could send me a link, that would be cool :)
-
@skoz the link is above
to give you an idea i wrote something little quick to give you an idea how it can be
set an interval in start()
setInterval(() => { this.getData(); this.updateDom(); }, 30*60*1000); //calls getData every 30 mins
getData()
this.dataDirSM = loadJSON("https://api-ratp.pierre-grimaud.fr/v2/rers/B/stations/les+baconnets?destination=robinson+saint+remy+les+chevreuse&endingstation=les+baconnets"); this.data = loadJSON("https://api-ratp.pierre-grimaud.fr/v2/rers/B/stations/les+baconnets?destination=charles+de+gaulle+mitry+claye&endingstation=les+baconnets");
getDom()
var wrapper = document.createElement("div") if(this.dataDirSM && this.data){ var realtable = document.createElement('table'); realtable.appendChild(this.createUpperRow()); for(var i = 0; i < Math.min(this.data.response.schedules.length, this.dataDirSM.response.schedules.length); i++){ var row = document.createElement('tr') row.appendChild(this.boxHeader(this.data.response.schedules[i].message)) row.appendChild(this.boxHeader(this.data.response.schedules[i].id)) row.appendChild(this.boxHeader(this.dataDirSM.response.schedules[i].id)) row.appendChild(this.boxHeader(this.dataDirSM.response.schedules[i].message)) realtable.appendChild(row) } wrapper.appendChild(realtable) } else { wrapper.innerHTML = "NO DATA"; } return wrapper
-
oh, i’m blind xD I had never seen this module, thanks for pointing it out !
You fixed the for loop, i had trouble with this one, I refused to work and i still don’t know why so i decided to bypass it. Thanks alot for fixing my code, if I understand right, the getDom function will check if data has arrived and if True, it will display the table, if False, it will display the"NO DATA" ? and each reload, the program will reload the data and display it ?
I’ll just have to shorten the time between each refresh because train pass by a bit more regularly so it wont be up to date if i wait 30 minutes each time.Thank you alot, I will try this new code now :)
-
@skoz yes, but it’s not tested i just wrote it down to give you an idea. if you get in trouble feel free to wite me a pn or check out the other module
-
Well at least, this time, something happened, the mirror boot up but where the table should be, its written :
schedules
module_5_schedulesModule.register(“schedules”, {
defaults: { updateInterval: 20000 fadeSpeed: 4000 }, getScripts: function() { return ["moment.js"] }, getStyles: function() { return ["font-awesome.css", "schedules.css"] }, start: function() { Log.info("Starting module: " + this.name); setInterval(() => { this.getData(); this.updateDom(); }, 20 * 1000); //calls getData every 20 second }, getDom: function() { var wrapper = document.createElement("div") if (this.dataDirSM && this.data) { var realtable = document.createElement('table'); realtable.appendChild(this.createUpperRow()); for (var i = 0; i < Math.min(this.data.response.schedules.length, this.dataDirSM.response.schedules.length); i++) { var row = document.createElement('tr') row.appendChild(this.boxHeader(this.data.response.schedules[i].message)) row.appendChild(this.boxHeader(this.data.response.schedules[i].id)) row.appendChild(this.boxHeader(this.dataDirSM.response.schedules[i].id)) row.appendChild(this.boxHeader(this.dataDirSM.response.schedules[i].message)) realtable.appendChild(row) } wrapper.appendChild(realtable) } else { wrapper.innerHTML = "NO DATA"; }, getData: function() { this.dataDirSM = loadJSON("https://api-ratp.pierre-grimaud.fr/v2/rers/B/stations/les+baconnets?destination=robinson+saint+remy+les+chevreuse&endingstation=les+baconnets"); this.data = loadJSON("https://api-ratp.pierre-grimaud.fr/v2/rers/B/stations/les+baconnets?destination=charles+de+gaulle+mitry+claye&endingstation=les+baconnets"); }, createUpperRow: function() { function createUpperRow() { var firstTableRow = document.createElement('tr'); var tableh1 = document.createElement('th'); tableh1.classList.add('align-left'); var tx1 = document.createTextNode('Time'); tableh1.appendChild(tx1); firstTableRow.appendChild(tableh1); var tableh2 = document.createElement('th'); tableh2.classList.add('align-left'); var tx2 = document.createTextNode('Paris'); tableh2.appendChild(tx2); firstTableRow.appendChild(tableh2); // deuxième moitier var tableh3 = document.createElement('th'); tableh3.classList.add('align-right'); var tx3 = document.createTextNode('Sud'); tableh3.appendChild(tx3); firstTableRow.appendChild(tableh3); var tableh4 = document.createElement('th'); tableh4.classList.add('align-right'); var tx4 = document.createTextNode('Time'); tableh4.appendChild(tx4); firstTableRow.appendChild(tableh4); return firstTableRow; }, boxHeader: function(inside) { if (inside == 'Train à l\'approche' || inside == 'Train à quai') { inside = 'no way' } else if (inside == 'Train retardé') { inside = 'retard' } var fillNode = document.createTextNode(inside); var realBox = document.createElement('td') realBox.appendChild(fillNode); return realBox; } })
and here is what I got from your advices
-
@skoz you forgot to return wrapper at the end of getDom and remove
function createUpperRow() {
in vreateUpperRow -
Oh you are right, I also forget a curly brace after the ‘else’, I changed all that but it still doesn’t work
I paste the code again if you want to see it clearModule.register(“schedules”, {
defaults: { updateInterval: 20000 fadeSpeed: 4000 }, getScripts: function() { return ["moment.js"] }, getStyles: function() { return ["font-awesome.css", "schedules.css"] }, start: function() { Log.info("Starting module: " + this.name); setInterval(() => { this.getData(); this.updateDom(); }, 20 * 1000); //calls getData every 20 seconds }, getDom: function() { var wrapper = document.createElement("div") if (this.dataDirSM && this.data) { var realtable = document.createElement('table'); realtable.appendChild(this.createUpperRow()); for (var i = 0; i < Math.min(this.data.response.schedules.length, this.dataDirSM.response.schedules.length); i++) { var row = document.createElement('tr') row.appendChild(this.boxHeader(this.data.response.schedules[i].message)) row.appendChild(this.boxHeader(this.data.response.schedules[i].id)) row.appendChild(this.boxHeader(this.dataDirSM.response.schedules[i].id)) row.appendChild(this.boxHeader(this.dataDirSM.response.schedules[i].message)) realtable.appendChild(row) } wrapper.appendChild(realtable) } else { wrapper.innerHTML = "NO DATA"; }; return wrapper }, getData: function() { this.dataDirSM = loadJSON("https://api-ratp.pierre-grimaud.fr/v2/rers/B/stations/les+baconnets?destination=robinson+saint+remy+les+chevreuse&endingstation=les+baconnets"); this.data = loadJSON("https://api-ratp.pierre-grimaud.fr/v2/rers/B/stations/les+baconnets?destination=charles+de+gaulle+mitry+claye&endingstation=les+baconnets"); }, createUpperRow: function() { var firstTableRow = document.createElement('tr'); var tableh1 = document.createElement('th'); tableh1.classList.add('align-left'); var tx1 = document.createTextNode('Time'); tableh1.appendChild(tx1); firstTableRow.appendChild(tableh1); var tableh2 = document.createElement('th'); tableh2.classList.add('align-left'); var tx2 = document.createTextNode('Paris'); tableh2.appendChild(tx2); firstTableRow.appendChild(tableh2); // deuxième moitier var tableh3 = document.createElement('th'); tableh3.classList.add('align-right'); var tx3 = document.createTextNode('Sud'); tableh3.appendChild(tx3); firstTableRow.appendChild(tableh3); var tableh4 = document.createElement('th'); tableh4.classList.add('align-right'); var tx4 = document.createTextNode('Time'); tableh4.appendChild(tx4); firstTableRow.appendChild(tableh4); return firstTableRow; }, boxHeader: function(inside) { if (inside == 'Train à l\'approche' || inside == 'Train à quai') { inside = 'no way' } else if (inside == 'Train retardé') { inside = 'retard' } var fillNode = document.createTextNode(inside); var realBox = document.createElement('td') realBox.appendChild(fillNode); return realBox; }
})