• Recent
  • Tags
  • Unsolved
  • Solved
  • MagicMirror² Repository
  • Documentation
  • 3rd-Party-Modules
  • Donate
  • Discord
  • Register
  • Login
MagicMirror Forum
  • Recent
  • Tags
  • Unsolved
  • Solved
  • MagicMirror² Repository
  • Documentation
  • 3rd-Party-Modules
  • Donate
  • Discord
  • Register
  • Login
  1. Home
  2. doubleT
  3. Posts
A New Chapter for MagicMirror: The Community Takes the Lead
Read the statement by Michael Teeuw here.
D
Offline
  • Profile
  • Following 0
  • Followers 4
  • Topics 4
  • Posts 176
  • Groups 1

Posts

Recent Best Controversial
  • RE: Currated Art

    I’m sure there’s an API for Arts&Culture. Everything on Google has an API. And it’s in the Cloud. There’s API documentation for the previous version, Google’s “Project Art” / “OpenGallery”.

    Edit: https://developers.google.com/opengallery/ => 404 :(
    https://opengallery.culturalspot.org/home
    Everything seems reachable … :/

    posted in Requests
    D
    doubleT
    Aug 17, 2018, 8:10 AM
  • RE: Currated Art

    First thing that came to my mind:
    “Every piece of art you’ve ever wanted to see – up close and searchable” by Amit Sood at TED, https://www.youtube.com/watch?v=CjB6DQGalU0
    (if you don’t watch the full 15 min, check 4:00 min)

    https://artsandculture.google.com/

    In a quick search, I couldn’t find any current information on whether there is an API, but I’d guess so.

    posted in Requests
    D
    doubleT
    Aug 16, 2018, 2:47 PM
  • RE: MMM-CountEvents

    More is always good! Nice module, I like that you can count the time since past events.

    posted in Utilities
    D
    doubleT
    Aug 8, 2018, 8:19 PM
  • RE: Help with converting this HTML file to MM2 module format...

    I’d put them in a different structure, perhaps, depending on what you want to achieve.

    If it’s just this list that you want: Remove all line breaks and tabs, lead all quotation marks with a backslash (\") and put that complete one line of code in:

    targetElement.innerHTML = "your Code here";
    

    More flexible:


    var newsSources = [
    {
    “id”:“washington_post”,
    “name”:“Washington Post”,
    “alt”:“Washington Post”,
    “link”:“https://www.washingtonpost.com/?reload=true”
    },
    {
    “id”:“usa_today”,
    “name”:“USA Today”,
    “alt”:“USA Today”,
    “link”:“http://rssfeeds.usatoday.com/UsatodaycomNation-TopStories”
    },
    {
    “id”:“irish_news”,
    “name”:“Irish News”,
    “alt”:“Irish News”,
    “link”:“http://www.irishnews.com/news/worldnews/”
    },
    {
    “id”:“wall_street_journal”,
    “name”:“Wall St. Journal”,
    “alt”:“Wall St. Journal”,
    “link”:“https://www.wsj.com/news/us”
    },
    {
    “id”:“kansas_city_star”,
    “name”:“The Kansas City Star”,
    “alt”:“Kansas City, MO News”,
    “link”:“https://www.kansascity.com/news/”
    },
    {
    “id”:“bbc_news”,
    “name”:“BBC World News”,
    “alt”:“BBC World News”,
    “link”:“https://www.bbc.com/news/world”
    }
    ];
    newMainElement = document.createElement(“div”);
    newMainHeadline = document.createElement(“h2”);
    newMainHeadline.innerHTML = “< img src="pix/break_news.png" alt="Breaking News" />”;
    newMainElement.apply(newMainHeadline);
    frstWrapper = document.createElement(“div”);
    scndWrapper = document.createElement(“div”); // really neccessary?
    thrdWrapper = document.createElement(“div”); // really neccessary?
    newsList = document.createElement(“ul”);
    for (i=0; i< =newsSources.length; i++) {
    newsItem = document.createElement(“li”);
    newsLogo = document.createElement(“div”);
    newsLogo.innerHTML = “< img src="pix"+newsSources[i].id+”.png" alt="“+newsSources[i].alt+”" />"
    newsLink = document.createElement(“h3”);
    newsLink.innerHTML = “< a href="”+newsSources[i].link+“" target="myIframe">”+newsSources[i].name+“”;
    newsItem.apply(newsLogo);
    newsItem.apply(newsLink);
    newsList.apply(newsItem);
    }
    thrdWrapper.apply(newsList); // really neccessary? see above
    scndWrapper.apply(thrdWrapper); // really neccessary? see above
    frstWrapper.apply(scndWrapper);
    newMainElement.apply(frstWrapper);


    I didn’t use the code block because it can’t handle \".
    In < img and < a you have to remove the space.
    id = image name, you’ll have to adapt a little, I wrote them in a more uniform style.
    alt = could be the same as the name, but I put it in as you varied a little with your alt titles.


    Oh, by the way:
    Seems like this could also be a good case for a template system.
    https://forum.magicmirror.builders/topic/2443/html-templating-system
    https://forum.magicmirror.builders/topic/5053/better-way-to-use-html-in-module-development

    posted in Development
    D
    doubleT
    Aug 8, 2018, 3:24 PM
  • RE: Real Time ECG

    For anything involving a graph drawn from JS(ON) data, I can only recommend highcharts.

    It’s possible to display dynamic graphs from live data. Example: https://www.highcharts.com/stock/demo/dynamic-update/
    https://www.highcharts.com/docs/working-with-data/live-data

    Your python code could provide a JSON and the MM-module calls the JSON and prints the graph.

    I’ve used highcharts before but never dynamically like in the example above.
    Here’s an example where I used it in a module: https://github.com/TTigges/MMM-Oiltank/blob/master/MMM-Oiltank.js

    posted in Development
    D
    doubleT
    Aug 8, 2018, 1:22 PM
  • RE: Multiples of same module?

    If you want a quick and dirty solution, copy the module folder, rename the copy and then change the module’s name to match the new module/folder name in all occurances (file names and within the code).

    posted in Troubleshooting
    D
    doubleT
    Aug 8, 2018, 12:59 PM
  • RE: countdown module for repeating aniversary

    As you said, MMM-doomsDay isn’t really the module you’re looking for. I wrote a possible solution as an answer to your question in the other thread. But the downside is, it’d only be possible for one event as that module can’t even list several events (at least that’s what I saw from a short look at the code).

    So in your case I’d take MMM-doomsDay and built your own module from that with the code changes I posted in the other thread.

    posted in Productivity
    D
    doubleT
    Aug 8, 2018, 12:56 PM
  • RE: MMM-doomsDay - The countdown module,

    @zdenek Even though I think it’s possible with a few changes to the code, I don’t think this would fit the scope of this module, which is to manually set a countdown to one specific event (noteven a few, right?) but not for a whole list of calendar dates.

    Even if the code ignores the year and just always shows the next event, does it make sense to have it display “364 days left” right the next day?

    Anyway, if you want to do that, I’d suggest adding:

        doomsDay: "2018-12-24 24:00:00",
        yearlyEvent: true,
        toWhat: "X-Mass"
    

    The most simple simple change to the code would be to add this at line 48:

    if (this.config.yearlyEvent && daysLeft < = 0) {
        var diff = now.getFullYear() - doomsday.getFullYear();
        // update doomsday:
        doomsDay.setFullYear(d.getFullYear() + diff);
        // calculate again:
        timeparser = Date.parse(doomsDay) - Date.parse(now);
        daysLeft = Math.floor(timeparser/(1000*60*60*24));
    }
    

    (remove the space between “< =” … )
    I didn’t test this, though, (and I don’t recommend it).

    posted in Utilities
    D
    doubleT
    Aug 8, 2018, 12:48 PM
  • RE: help developing an outofmilk.com module

    Uh, interesting topic. I like API calls. :D Back when I started, my main issue was understanding the node_helper.js – and that it was neccessary.
    I’m still struggling to make sense of your token complexity. Apart from that, your files would be something like this:

    MMM-OutOfMilk.js:

    Module.register("MMM-OutOfMilk",{
        defaults: {
            // your defaults
        },
    
        start: function() {
            var payload = "start"; // example
            this.sendSocketNotification("GetMyShoppingList", payload);
        },
    
        socketNotificationReceived: function(notification, shoppingList) {
            if (notification === "ShoppingListRecieved") {
                this.handeShoppingList(shoppingList);
            }
        },
    
        handleShoppingList: function(shoppingList) {
            // do something with your shopping list
        }
    }
    

    node_helper.js:

    var NodeHelper = require("node_helper");
    var request = require("request"); // needed? see below
    var fs = require("fs"); // needed? see below
    var timer = 0; // needed? see below "I added a timer"
    var token;
    
    module.exports = NodeHelper.create({
        start: function() {
        },
        socketNotificationReceived: function(notification, payload) {
            if (notification === "GetMyShoppingList") {
                // start the logic to recieve the shopping list
                // get token?
                // make call
                this.getShoppingList(payload);
            }
        },
        getToken: function(payload) {
            // however you get your token
            getShoppingList(payload);
        },
        getShoppingList: function(payload) {
            var self = this;
            var source = ; // your source URL
            if (token) {
            	request({
    	            url: source,
    	            json: true
    	        }, function (error, response, body) {
    	            if (!error && response.statusCode === 200) {
    	                self.sendSocketNotification("ShoppingListRecieved", body);
    	            }
    	            else {
    	            	// check error if it's a token issue
    	            	// if so, get new token
    	            	self.getToken(payload);
    	            }
    	        })
            }    
        }
    }
    

    From another project I know that sometimes a token can be used for a while. In that case I’d directly call the getShoppingList and only on an error that read “wrong token” or something like that, I’d call getToken which saves the token to a global variable and calls back getShoppingList to try again. That way you don’t have to get a new token for every call.

    Alternatively?

        getShoppingList: function(token) {
            var self = this;
            var source = ; // your source URL
            var rawdata = fs.readFileSync(source);
            var history =  JSON.parse(rawdata);
            self.sendSocketNotification("ShoppingListRecieved", history);
        }
    

    I’d also use a timer to request data on the first call and after that automatically only every full hour:
    So, in the node_helper.js, in the socketNotificationReceived I don’t forward the payload to this.updateTimer(payload) instead of getToken or getShoppingList to do this:

        updateTimer: function(payload) {
            var self = this;
            var d = new Date();
            var h = d.getHours();
            var min = d.getMinutes();
            var sec = d.getSeconds();
            if (timer === 0) {
                timer ++; // prevent unnecessary timer by double calls
                this.getShoppingList(payload);
    
                if((min == '00') && (sec == '00')){
    //              console.log(h + ":" + min + ":" + sec + " - update and wait 1 hour");
    //              console.log("restart timer");
                    setTimeout(() => {
                        this.clearTimer(payload);
                    }, 60*1000*60); // 60 sec * 1000 ms = 1 min * 60 = 1 hour
                } else {
    //              console.log(h + ":" + min + ":" + sec + " - update waits for " + (59-min) + " min and " + (60-sec) + "sec");
    //              console.log("restart timer");
                    setTimeout(() => {
                        this.clearTimer(payload);
                    }, ((60-sec)*1000)+(60*1000*(59-min)));
                }
            }
            else {
    //          console.log("timer already running, data displayed outside of timer run");
                this.getShoppingList(payload);
            }
        },
    
        clearTimer: function(payload) {
            timer --;
            this.updateTimer(payload);
        }
    

    For one of my modules I couldn’t use fs.readFile... or request because of CORS issues. In that case I had to use a php proxy.
    I’d strongly suggest trying to solve this with fs.readFile... or request but just for the sake of completeness and maybe to help you understand:

    In order to use PHP within nodeJS via Child Process Dependency you have to have PHP installed and in your PATH!
    You can read how I used it, here: https://forum.magicmirror.builders/topic/5830/call-api-no-cors-used-to-do-it-with-php-proxy/9

    posted in Development
    D
    doubleT
    Aug 7, 2018, 3:35 PM
  • RE: How to develop modules

    I’d second that.

    For a quick overview:

    The DOM (all visible elements) is based on HTML, styled with CSS and usually filled with content and function by Java Script. That’s all you need for basic modules.

    If you go further, you’ll need Python in case you have something connected to the Pi andnodeJS for advanced modules with some backend code, like API calls, though some nodeJS knowledge will help you a lot to understand the whole structure in the first place.

    jQuery can be a helpful Java Script library.
    API calls usually deliver JSON or – rarely – XML, but both should be familiar if you know JS objects and arrays and HTML.

    As Sean said, playing around and manipulating existing modules should help you a lot. Go through the code, see if you understand the connections and find out what happens if you manipulate it.

    Your most important tool when working in js-files is the browser console where you can print to with the js code console.log("show me the content of var x: " + x); MM code Log.info("show me the content of var x: " + x);

    posted in General Discussion
    D
    doubleT
    Aug 7, 2018, 12:23 PM
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 17
  • 18
  • 4 / 18
Enjoying MagicMirror? Please consider a donation!
MagicMirror created by Michael Teeuw.
Forum managed by Sam, technical setup by Karsten.
This forum is using NodeBB as its core | Contributors
Contact | Privacy Policy