MagicMirror² v2.4.1 is available! For more information about this release, check out this topic.
Please read the release notes carefully since this update requires adjustments to your Raspberry Pi configuration!

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.



  • @skoz

    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_schedules

    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);
    
    
                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 clear

    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);
    
    
        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;
    }
    

    })