MagicMirror Forum
    • Recent
    • Tags
    • Unsolved
    • Solved
    • MagicMirror² Repository
    • Documentation
    • 3rd-Party-Modules
    • Donate
    • Discord
    • Register
    • Login
    A New Chapter for MagicMirror: The Community Takes the Lead
    Read the statement by Michael Teeuw here.

    DIY Module Displays Nothing

    Scheduled Pinned Locked Moved Solved Troubleshooting
    14 Posts 3 Posters 1.2k Views 2 Watching
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • S Offline
      sdetweil @chrisfr1976
      last edited by

      @chrisfr1976 there are no module reloads, one time per page load

      Sam

      How to add modules

      learning how to use browser developers window for css changes

      1 Reply Last reply Reply Quote 0
      • S Offline
        sdetweil @sdetweil
        last edited by sdetweil

        @hokie-bird as chris mentioned you only need to call setInterval once.

        but to minimize your code change, you can change them to
        setTimeout

        in either case, when your module is hidden, you should stop the timer, and restart it when shown again

        suspend() and resume() functions will advise when those events happen ( MMM-pages would do those on a cycle to test against )

        Sam

        How to add modules

        learning how to use browser developers window for css changes

        S 1 Reply Last reply Reply Quote 0
        • S Offline
          sdetweil @sdetweil
          last edited by sdetweil

          @hokie-bird

          this test
          this.isPlaying = (this.nowPlaying.artist && this.nowPlaying.song) ? true : false;

          will always evaluate to true
          if artist and song are “”, as strings those will evaluate to true

          null is a non-true value, but also not a string

          Sam

          How to add modules

          learning how to use browser developers window for css changes

          1 Reply Last reply Reply Quote 0
          • H Offline
            hokie-bird
            last edited by

            Thanks to all for the suggestions. Ive attempted to incorporate them all, which has yeilded a small bit of progress: now 'No song is playing" appears bottom_center at MM startup for a second or 2, then vanishes nothing displaying again regardless of whether music starts, stops, etc. Browser console still reports data being received, and I cant figure how else to use the Developer Tools to troubleshoot. Here’s the latest code:

            MMM-LyrionNowPlaying.js

            /* MagicMirror² Module: MMM-LyrionNowPlaying */
            
            Module.register("MMM-LyrionNowPlaying", {
            
                // Default module config.
                defaults: {
                    updateInterval: 1000,
                    retryDelay: 2500,
                    lyrionServer: 'http://localhost:9000',
                    playerName: 'livingroom-mm',
                    showCoverArt: true,
                    coverArtSize: 150,
                    fadeSpeed: 4000,
                },
            
                getStyles: function () {
                    return ["MMM-LyrionNowPlaying.css"];
                },
            
                start: function () {
                    Log.info("Starting module: " + this.name);
                    this.nowPlaying = {
                        artist: "",
                        song: "",
                        timeRemaining: "",
                        coverArt: ""
                    };
                    this.isPlaying = false;
                    this.updateTimer = null; // Initialize updateTimer
            
                    this.updateDom(0);
                    this.scheduleUpdate();
                },
            
                notificationReceived: function (notification, payload, sender) {
                    if (notification === "ALL_MODULES_STARTED" || notification === "DOM_OBJECTS_CREATED") {
                        this.sendSocketNotification('GET_LYRION_NOW_PLAYING', {
                            lyrionServer: this.config.lyrionServer,
                            playerName: this.config.playerName
                        });
                    }
                },
            
                getDom: function () {
                    const wrapper = document.createElement("div");
                    wrapper.classList.add("wrapper");
            
                    if (this.isPlaying) {
                        if (this.nowPlaying.coverArt && this.config.showCoverArt) {
                            const coverArtImg = document.createElement("img");
                            coverArtImg.src = this.nowPlaying.coverArt;
                            coverArtImg.width = this.config.coverArtSize;
                            coverArtImg.height = this.config.coverArtSize;
                            coverArtImg.classList.add("coverArt");
                            wrapper.appendChild(coverArtImg);
                        }
            
                        const infoContainer = document.createElement("div");
                        infoContainer.classList.add("infoContainer");
            
                        if (this.nowPlaying.artist && this.nowPlaying.song) {
                            const songInfo = document.createElement("div");
                            songInfo.classList.add("songInfo");
                            songInfo.innerHTML =
                                this.nowPlaying.artist + " - " +
                                this.nowPlaying.song;
                            infoContainer.appendChild(songInfo);
                        }
            
                        if (this.nowPlaying.timeRemaining) {
                            const timeRemaining = document.createElement("div");
                            timeRemaining.classList.add("timeRemaining");
                            timeRemaining.innerHTML = "Time Remaining: " + this.nowPlaying.timeRemaining;
                            infoContainer.appendChild(timeRemaining);
                        }
            
                        wrapper.appendChild(infoContainer);
                    } else {
                        wrapper.innerHTML = "No song is currently playing.";
                    }
            
                    console.log("Generated HTML:", wrapper.innerHTML);
                    return wrapper;
                },
            
                scheduleUpdate: function () {
                    if (this.updateTimer) {
                        clearInterval(this.updateTimer);
                    }
            
                    this.updateTimer = setInterval(() => {
                        this.getLyrionNowPlaying();
                    }, this.config.updateInterval);
                },
            
                getLyrionNowPlaying: function () {
                    this.sendSocketNotification('GET_LYRION_NOW_PLAYING', {
                        lyrionServer: this.config.lyrionServer,
                        playerName: this.config.playerName
                    });
                },
            
                socketNotificationReceived: function (notification, payload) {
                    if (notification === 'LYRION_NOW_PLAYING_RESULT') {
                        if (payload.error) {
                            Log.error(`MMM-LyrionNowPlaying: ${payload.error}`);
                        } else {
                            this.nowPlaying = payload;
                            console.log("Received data:", this.nowPlaying);
                            console.log("this.nowPlaying after update:", this.nowPlaying);
            
                            // Corrected isPlaying check:
                            this.isPlaying = (this.nowPlaying.artist && this.nowPlaying.artist !== "" && this.nowPlaying.song && this.nowPlaying.song !== "") ? true : false;
            
                            const duration = Number(this.nowPlaying.duration);
                            const position = Number(this.nowPlaying.position);
            
                            if (!isNaN(duration) && !isNaN(position) && duration > 0 && position >= 0) {
                                this.nowPlaying.timeRemaining = this.formatTime(duration - position);
                            } else {
                                this.nowPlaying.timeRemaining = "";
                            }
            
                            this.updateDom(this.config.fadeSpeed);
                        }
                    }
                },
            
                formatTime: function (seconds) {
                    const minutes = Math.floor(seconds / 60);
                    const remainingSeconds = seconds % 60;
                    return `${minutes}:${remainingSeconds.toString().padStart(2, '0')}`;
                }
            });
            
            

            Suggestions welcome and again a huge thank you to the community.

            S 1 Reply Last reply Reply Quote 0
            • S Offline
              sdetweil @hokie-bird
              last edited by

              @hokie-bird

              I built it and fixed minor things…
              created a dummy node_helper and a dummy album art png.

              so save yours out of the way,(rename the folder)
              cd ~/MagicMirror/modules
              git clone https://github.com/sdetweil/MMM-LyrionNowPlaying

              test
              copy your node helper over mine

              be careful on your update frequency asking the node_helper all the time…

              once per second is probably too fast…
              i made mine ignore socketNotifications() til a response was sent (after 5 second delay) from the 1st time.
              the duration is just number that changes…, duration just a fixed number

              Sam

              How to add modules

              learning how to use browser developers window for css changes

              1 Reply Last reply Reply Quote 0
              • H Offline
                hokie-bird
                last edited by

                @sdetweil cant thank you enough for taking the time to do that, WOW!

                Here’s what I’ve learned. I subbed your LyrionNowPlaying.js in for mine, and results were exactly the same: “No song currently playing” at startup for a second or two, vanishes and never returns despite music starting/stopping. Then I subbed your node_helper.js for mine (with your module.js file and .png) and BOOM! your data and image appeared! Granted, it would appear for 4 seconds or so, disappear for 1-2, then re-appear but progress! So, safe to assume its somehow something in my node_helper? Here’s the latest, and again wildly grateful for your help.

                node_helper.js

                const NodeHelper = require('node_helper');
                const request = require('request');
                
                module.exports = NodeHelper.create({
                
                    start: function() {
                        console.log("Starting node_helper for: " + this.name);
                        this.nowPlaying = { 
                            artist: "", 
                            song: "",
                            timeRemaining: "",
                            duration: 0, 
                            position: 0,
                            coverArt: "" 
                        }; 
                        this.sendSocketNotification('LYRION_NOW_PLAYING_RESULT', this.nowPlaying); // Send initial empty state
                    },
                
                    socketNotificationReceived: function(notification, payload) {
                        if (notification === 'GET_LYRION_NOW_PLAYING') {
                            this.getLyrionNowPlaying(payload);
                        }
                    },
                
                    getLyrionNowPlaying: function(payload) {
                        const { lyrionServer, playerName } = payload;
                        const options = {
                            url: `${lyrionServer}/jsonrpc.js`,
                            method: 'POST',
                            headers: {
                                'Content-Type': 'application/json'
                            },
                            body: JSON.stringify({
                                "id": 1,
                                "method": "slim.request",
                                "params": [playerName, ["status", "-", 1, "tags:artist"]] 
                            })
                        };
                
                        request(options, (error, response, body) => {
                            if (error) {
                                console.error(`MMM-LyrionNowPlaying: Error connecting to Lyrion server: ${error}`);
                                this.sendSocketNotification('LYRION_NOW_PLAYING_RESULT', { error: `Error connecting to Lyrion server: ${error}` });
                                return;
                            }
                
                            if (response.statusCode !== 200) {
                                console.error(`MMM-LyrionNowPlaying: Received unexpected status code from Lyrion server: ${response.statusCode}`);
                                this.sendSocketNotification('LYRION_NOW_PLAYING_RESULT', { error: `Received unexpected status code from Lyrion server: ${response.statusCode}` });
                                return;
                            }
                
                            try {
                                const data = JSON.parse(body);
                                console.log("Raw Data:", data); 
                
                                if (!data.result) {
                                    console.error(`MMM-LyrionNowPlaying: Invalid response from Lyrion server: Missing 'result' in response`);
                                    this.sendSocketNotification('LYRION_NOW_PLAYING_RESULT', { error: `Invalid response from Lyrion server: Missing 'result' in response` });
                                    return;
                                }
                
                                if (!data.result.mode || data.result.mode !== 'play') { 
                                    this.nowPlaying = { 
                                        artist: "", 
                                        song: "",
                                        timeRemaining: "",
                                        duration: 0, 
                                        position: 0,
                                        coverArt: "" 
                                    }; 
                                    this.sendSocketNotification('LYRION_NOW_PLAYING_RESULT', this.nowPlaying); // Send "no song" notification immediately
                                    return; 
                                }
                
                                // Handle cases where playlist_loop might be missing or empty
                                let artist = "Unknown Artist";
                                let song = "Unknown Song";
                
                                if (data.result.playlist_loop && data.result.playlist_loop[0]) {
                                    artist = data.result.playlist_loop[0].artist || "Unknown Artist";
                                    song = data.result.playlist_loop[0].title || "Unknown Song"; 
                                }
                
                                this.nowPlaying = {
                                    artist: artist,
                                    song: song,
                                    duration: data.result.duration || 0, 
                                    position: data.result.time || 0,
                                    coverArt: `${lyrionServer}/music/current/cover.jpg?player=${playerName}` 
                                }; 
                
                                this.nowPlaying.timeRemaining = this.formatTime(this.nowPlaying.duration - this.nowPlaying.position);
                
                                this.sendSocketNotification('LYRION_NOW_PLAYING_RESULT', this.nowPlaying); 
                
                            } catch (err) {
                                console.error(`MMM-LyrionNowPlaying: Error parsing Lyrion API response: ${err}`);
                                this.sendSocketNotification('LYRION_NOW_PLAYING_RESULT', { error: `Error parsing Lyrion API response: ${err}` });
                            }
                        });
                    },
                
                    formatTime: function(seconds) {
                        const minutes = Math.floor(seconds / 60);
                        const remainingSeconds = seconds % 60;
                        return `${minutes}:${remainingSeconds.toString().padStart(2, '0')}`;
                    }
                });
                
                
                S 1 Reply Last reply Reply Quote 0
                • S Offline
                  sdetweil @hokie-bird
                  last edited by sdetweil

                  @hokie-bird not sure, but two things

                  1. the sendSocketNotification() in start should be removed , the browser side is not up yet.

                  2. you are sending requests for playing info 1/second,
                    can the server handle multiple concurrently?
                    how long is the response time ?

                  i would change that to 5 seconds to test,
                  you can change it in config.js

                  Sam

                  How to add modules

                  learning how to use browser developers window for css changes

                  1 Reply Last reply Reply Quote 0
                  • H Offline
                    hokie-bird
                    last edited by

                    Thank you again @sdetweil

                    I implemented both of your changes (removing sendSocketNotification() in start and 5 second refresh interval) and it seems the refresh interval is what is impacting the display. At 1 second, basically nothing, but at 5 seconds I get a 5 second display, then maybe a 2 second disappearance and then a 5 second display repeating pattern. (Which is somewhat interesting as the browser console is reporting accurate data every 1 second, despite nothing being displayed.) Not sure how to get a constant/non-disappearing display (when music is playing) while still getting an accurate reflection/countdown of the time remain, but I’ll experiment with that.

                    Of course, suggestions welcome. And thanks again.

                    S 1 Reply Last reply Reply Quote 0
                    • S Offline
                      sdetweil @hokie-bird
                      last edited by sdetweil

                      @hokie-bird you are also asking for a 4 second transition on the changes w updateDom(…)

                      so 2 seconds fade out and 2 seconds fade in

                      this.updateDom(this.config.fadeSpeed);
                      and you are interrupting the fade with another updateDom

                      Sam

                      How to add modules

                      learning how to use browser developers window for css changes

                      1 Reply Last reply Reply Quote 0
                      • H Offline
                        hokie-bird
                        last edited by

                        It was the fade! when I switch the fade to 0, even the refresh of 1 seconds works and displays perfectly. @sdetweil you are brilliant!

                        Thank you!

                        1 Reply Last reply Reply Quote 0
                        • S sdetweil has marked this topic as solved on
                        • 1
                        • 2
                        • 1 / 2
                        • First post
                          Last post
                        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