A New Chapter for MagicMirror: The Community Takes the Lead
Read the statement by Michael Teeuw here.
  • Meross

    4
    1 Votes
    4 Posts
    1k Views
    lavolp3L
    @thetobyde for the DOM I have created the following elements: var label = document.createElement("label"); label.className = "tasmota-switch"; label.id = "switch-" + topic; var input = document.createElement("input"); input.type = "checkbox"; input.id = "checkbox-" + topic; input.checked = this.setSwitch(topic); var span = document.createElement("span"); span.className = "slider round"; span.id = "slider-" + topic; span.onclick = function() { self.toggleSwitch(topic); }; label.appendChild(input); label.appendChild(span); there is a label (as wrapper), a (hidden) checkbox, and a span that is the actual slider. The onclick function for the slider looks like this: toggleSwitch: function(topic) { this.sendSocketNotification("TOGGLE_SWITCH", topic); console.log("Switch toggled: " + topic); }, So, rather generic. There you need to tell the api that you have toggled the switch. Also, at every DOM update you need to check the api for the switch state (see the this.setSwitch-function above). It may have been switched from another endpoint or app. The result sets the “checked” state of the hidden input. setSwitch: function(topic) { this.log("Setting switch for " + topic); var powerState = this.tasmotaData.tele[topic].STATE.POWER; return (powerState === "ON") ? true : false; }, The rest is css: /*** SWITCHES ***/ .MMM-Tasmota .tasmota-switch { float: right; position: relative; display: inline-block; width: 90px; height: 34px; } /* Hide default HTML checkbox */ .MMM-Tasmota .tasmota-switch input { opacity: 0; width: 0px; height: 0px; } /* The slider */ .MMM-Tasmota .slider { position: absolute; cursor: pointer; top: 0; left: 30px; right: 0; bottom: 0; background-color: #f00; border: 3px solid white; -webkit-transition: .2s; transition: .2s; } .MMM-Tasmota .slider:before { position: absolute; content: ""; height: 26px; width: 26px; left: 3px; bottom: 1px; background-color: white; -webkit-transition: .2s; transition: .2s; } .MMM-Tasmota input:checked + .slider { background-color: #0f0; } .MMM-Tasmota input:checked + .slider:before { -webkit-transform: translateX(24px); -ms-transform: translateX(24px); transform: translateX(24px); } /* Rounded sliders */ .MMM-Tasmota .slider.round { border-radius: 34px; } .MMM-Tasmota .slider.round:before { border-radius: 50%; } I will publish all of that with my MMM-Tasmota module.
  • AirPlay AirportExpress

    1
    0 Votes
    1 Posts
    314 Views
    E
    Is there any module to read AirPlay Infos from Airport Express like the MMM-Sonos Module? Any suggestions? Greats Gregor
  • SenseHat data on MM?

    10
    0 Votes
    10 Posts
    6k Views
    framboise-piF
    @lavolp3 :face_savouring_delicious_food: just had the idea of a tamagotchi-like (using sensors and MagicMirror to display life stats etc.) : MMM-MySenseHatTamagotchi im searching too for 8x8 ideas, and wrote some on the module page (MMM-MySenseHat), in issues section. Maybe you’ll find ideas there, to help you find other ideas ! let’s 8x8 ! :vulcan_salute_light_skin_tone:
  • Return to first page after a delimited time

    4
    0 Votes
    4 Posts
    718 Views
    B
    i solved my case. probably not the better way but here is the js modified : Module.register('MMM-pages', { // We require the older style of function declaration for compatibility // reasons. /** * By default, we have don't pseudo-paginate any modules. We also exclude * the page indicator by default, in case people actually want to use the * sister module. We also don't rotate out modules by default. */ defaults: { modules: [], excludes: [], // Keep for compatibility fixed: ['MMM-page-indicator'], animationTime: 1000, rotationTime: 0, rotationFirstpage:0, rotationDelay: 10000 }, /** * Apply any styles, if we have any. */ getStyles: function () { return ['pages.css']; }, /** * Modulo that also works with negative numbers. * * @param {number} x The dividend * @param {number} n The divisor */ mod: function (x, n) { return ((x % n) + n) % n; }, /** * Pseudo-constructor for our module. Makes sure that values aren't negative, * and sets the default current page to 0. */ start: function () { this.curPage = 0; this.rotationPaused = false; // Compatibility if (this.config.excludes.length) { Log.warn('[Pages]: The config option "excludes" is deprecated. Please use "fixed" instead.'); this.config.fixed = this.config.excludes; } // Disable rotation if an invalid input is given this.config.rotationTime = Math.max(this.config.rotationTime, 0); this.config.rotationDelay = Math.max(this.config.rotationDelay, 0); this.config.rotationFirstpage = Math.max(this.config.rotationFirstpage, 0); }, /** * Handles incoming notifications. Responds to the following: * 'PAGE_CHANGED' - Set the page to the specified payload page. * 'PAGE_INCREMENT' - Move to the next page. * 'PAGE_DECREMENT' - Move to the previous page. * 'DOM_OBJECTS_CREATED' - Starts the module. * 'QUERY_PAGE_NUMBER' - Requests the current page number * * @param {string} notification the notification ID * @param {number} payload the page to change to/by */ notificationReceived: function (notification, payload) { switch (notification) { case 'PAGE_CHANGED': Log.log('[Pages]: received a notification ' + `to change to page ${payload} of type ${typeof payload}`); this.curPage = payload; this.updatePages(); break; case 'PAGE_INCREMENT': Log.log('[Pages]: received a notification to increment pages!'); this.changePageBy(payload, 1); this.updatePages(); break; case 'PAGE_DECREMENT': Log.log('[Pages]: received a notification to decrement pages!'); // We can't just pass in -payload for situations where payload is null // JS will coerce -payload to -0. this.changePageBy(payload ? -payload : payload, -1); this.updatePages(); break; case 'DOM_OBJECTS_CREATED': Log.log('[Pages]: received that all objects are created;' + 'will now hide things!'); this.sendNotification('MAX_PAGES_CHANGED', this.config.modules.length); this.animatePageChange(); this.resetTimerWithDelay(0); break; case 'QUERY_PAGE_NUMBER': this.sendNotification('PAGE_NUMBER_IS', this.curPage); break; case 'PAUSE_ROTATION': if (!this.rotationPaused) { Log.log('[Pages]: pausing rotation due to notification'); clearInterval(this.timer); clearInterval(this.delayTimer); this.rotationPaused = true; } else { Log.warn('[Pages]: Was asked to paused but rotation was already paused!'); } break; case 'RESUME_ROTATION': if (this.rotationPaused) { Log.log('[Pages]: resuming rotation due to notification'); this.resetTimerWithDelay(this.rotationDelay); this.rotationPaused = false; } else { Log.warn('[Pages]: Was asked to resume but rotation was not paused!'); } break; default: // Do nothing } }, /** * Changes the internal page number by the specified amount. If the provided * amount is invalid, use the fallback amount. If the fallback amount is * missing or invalid, do nothing. * * @param {number} amt the amount of pages to move forward by. Accepts * negative numbers. * @param {number} fallback the fallback value to use. Accepts negative * numbers. */ changePageBy: function (amt, fallback) { if (typeof amt !== 'number') { Log.warn(`[Pages]: ${amt} is not a number!`); } if (typeof amt === 'number' && !Number.isNaN(amt)) { this.curPage = this.mod( this.curPage + amt, this.config.modules.length ); } else if (typeof fallback === 'number') { this.curPage = this.mod( this.curPage + fallback, this.config.modules.length ); } }, /** * Handles hiding the current page's elements and showing the next page's * elements. */ updatePages: function () { // Update iff there's at least one page. if (this.config.modules.length !== 0) { this.animatePageChange(); if (!this.rotationPaused) { this.resetTimerWithDelay(this.config.rotationDelay); } this.sendNotification('NEW_PAGE', this.curPage); } else { Log.error("[Pages]: Pages aren't properly defined!"); } }, /** * Animates the page change from the previous page to the current one. This * assumes that there is a discrepancy between the page currently being shown * and the page that is meant to be shown. */ animatePageChange: function () { const self = this; // Hides all modules not on the current page. This hides any module not // meant to be shown. MM.getModules() .exceptWithClass(this.config.fixed) .exceptWithClass(this.config.modules[this.curPage]) .enumerate(module => module.hide( self.config.animationTime / 2, { lockString: self.identifier } )); // Shows all modules meant to be on the current page, after a small delay. setTimeout(() => { MM.getModules() .withClass(self.config.modules[self.curPage]) .enumerate((module) => { module.show( self.config.animationTime / 2, { lockString: self.identifier } ); }); }, this.config.animationTime / 2); }, /** * Resets the page changing timer with a delay. * * @param {number} delay the delay, in milliseconds. */ resetTimerWithDelay: function (delay) { if (this.config.rotationTime > 0) { // This timer is the auto rotate function. clearInterval(this.timer); // This is delay timer after manually updating. clearInterval(this.delayTimer); const self = this; this.delayTimer = setTimeout(() => { self.timer = setInterval(() => { self.sendNotification('PAGE_INCREMENT'); self.changePageBy(1); self.updatePages(); }, self.config.rotationTime); }, delay); }if (this.config.rotationFirstpage > 0) { // This timer is the auto rotate function. clearInterval(this.timer); // This is delay timer after manually updating. clearInterval(this.delayTimer); const self = this; this.delayTimer = setTimeout(() => { self.timer = setInterval(() => { self.sendNotification('PAGE_CHANGED', 0); self.changePageBy(-this.curPage); self.updatePages(); }, self.config.rotationFirstpage); }, delay); } }, });
  • Pi-hole API presenter

    8
    0 Votes
    8 Posts
    8k Views
    H
    I was also having this issue where magic mirror was not showing status. i made silly mistake of copying the url which i access in browser but later i noticed that we need to copy the url with “api.php” in end of the address which fix the issue for me.
  • OpenSprinkler 3.0 irrigation Times on MM

    Unsolved
    3
    0 Votes
    3 Posts
    1k Views
    M
    does this module support the opensprinkler pi version - all I get is Loading Thanks Myk
  • Saint of the day module

    2
    0 Votes
    2 Posts
    496 Views
    bheplerB
    The first step is to see if someone has a web API you can use to find out the Saint of the Day. Do you know of one?
  • Euromillions display on MagicMirror

    24
    0 Votes
    24 Posts
    10k Views
    cowboysdudeC
    @lavolp3 10 is impossible… You’d need closer to at least 30… I agree with you.
  • Calendar aggregation by date rather than quantity

    2
    0 Votes
    2 Posts
    2k Views
    evroomE
    @jerbookins Hi, I suppose that when you play around with those 2 parameters, you will get want you want: maximumNumberOfDays: 7, maximumEntries: 100, Where maximumEntries is limited to the range 0 to 100, so if you are a very busy person … Good luck.
  • Voice Assistant that works with a calendar

    2
    0 Votes
    2 Posts
    366 Views
    O
    MMM-AssistantMk2 works for me. When it’s asked to add reminder, it will work and sync with my google calendar.
  • Solar Edge Module

    1
    0 Votes
    1 Posts
    512 Views
    D
    Re: SolarEdge Module So I am trying to set up this module and it says it needs the following: User ID API Key Site ID So I got my API Key from their help desk but I’m unclear on how to identify User ID and Site ID. When I go to the monitoring portal website on the right side above my name is an ID #…is that site or user? And how do I identify the other one? Any help would be greatly appreciated. Chris
  • ASUS Router App Info

    3
    0 Votes
    3 Posts
    906 Views
    D
    would this ()link text help, it’s not the same router as mine but same idea I guess…
  • MagicMirror Authenticator

    8
    0 Votes
    8 Posts
    2k Views
    bheplerB
    Hmm. Interesting idea. Work has given me an RSA security fob which provides a 2FA code all the time. For my personal use, I use the Yubico Authenticator both on PC and mobile, but I’ve used Google’s and Microsoft’s mobile app before. There’s not really a practical difference between displaying the rolling code on a mirror and having the app taking up space on my desktop. I know nothing about how the 2FA apps are implemented so I don’t know where to begin on making a module for it. Sounds like a neat project.
  • Smart Devices and sensors

    xiaomi aqara programming job sensors
    7
    0 Votes
    7 Posts
    2k Views
    J
    @duxnobis Yes checkout HomeAssistant, it supports Hue and Aqara, and then you can use MMM-HomeAssistant-sensors (snille fork)to pull that information into MagicMirror if you want
  • Hourly weather forecast

    13
    0 Votes
    13 Posts
    4k Views
    B
    @hango thank you so much :)
  • Out of Milk

    out of milk bring programming job
    1
    0 Votes
    1 Posts
    1k Views
    D
    Hi, could anyone build a „out of Milk“ Module? I am talking about the food shopping app. Similar to bring!. I would like to see in a module, what I have on list for my upcoming shopping. Happy to discuss
  • News ticker module

    11
    0 Votes
    11 Posts
    8k Views
    BKeyportB
    @Chrisflex post the error(s), and we can guide you.
  • Amcrest IP Camera Support

    Unsolved
    2
    0 Votes
    2 Posts
    1k Views
    Mitch1138M
    Has anyone had any success with this? I have been able to use MMM-RTSPStream to display one camera using RTSP, but another Amcrest (IP4M) will not work. Thanks, Mitch
  • MMM-AVStock ISIN instead of symbol

    3
    0 Votes
    3 Posts
    775 Views
    K
    Hi @sdetweil, thanks for your reply. Daniel
  • How to create custom questions for Google Assistant using IFTTT

    1
    0 Votes
    1 Posts
    249 Views
    P
    Does anyone have a good tutorial or resource to use to create a module that uses IFTTT to create your own custom questions? I’ve seen a few examples but nothing that explains the process.