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

    Posts

    Recent Best Controversial
    • RE: MMM-FroniusSolar family modules

      Hi,

      i found a small bug. At this moment you need to change your inverter-IP in the node_helper.js file.

      I‘ll fix this to a config entry this weekend.

      posted in Utilities
      C
      chrisfr1976
    • MMM-FroniusSolar family modules

      Hi,

      i was working the last days on a module to get rid of the last iframes on my mirror. These modules can all visualize solar energy data from a Fronius solar system using SVG magic :)

      • MMM-FroniusSolar: Best for simple setups prioritizing clarity and minimalism.
      • MMM-FroniusSolar2: Suitable for scenarios requiring visual feedback on power flows (e.g., monitoring dynamic energy consumption).
      • MMM-FroniusSolar3: Ideal for larger or customizable displays where scalability is important.

      If you do not have a FroniusPV but your system has an API it should be not much work to adjust the node_helper file.

      All in a column:
      MMM-FroniusSolar

      posted in Utilities
      C
      chrisfr1976
    • MMM-Temp2IOT

      Hi,

      I have created a quick module to visualize outside temperatures from the Temp2IOT Sensor:

      MMM-Temp2IOT

      Screenshot MMM-Temp2IOT

      Get your own Sensor: Temp2IOT

      -1 iFrame on my mirror :)

      posted in Utilities
      C
      chrisfr1976
    • RE: MM-Watcher - MagicMirror Config.js Auto-Refresh Script

      @sdetweil thats why I made the module. The Pi is completely headless. So I’m in the kitchen with my laptop and enjoy this autorefresh now. Before that I’ve used a Script on my Smartphone. Also manual and annoying :-)
      And sure, also the xdotool command is just pressing “ctrl+r” for me.

      posted in System
      C
      chrisfr1976
    • MM-Watcher - MagicMirror Config.js Auto-Refresh Script

      Hi,

      I’m currently working on a new module. I had a lot of updates to do in my code to adjust the layout. After saving changes, I had to manually refresh the MagicMirror application every time. This process is tedious, especially if you’re frequently experimenting with configurations.

      That’s where this script comes in. By monitoring your config.js file (or a module.js file) for changes, it automates the refresh process. Now, every time I save my config.js, the Mirror refreshes itself instantly.

      It’s seamless, efficient, and saves you from the hassle of restarting the application manually.

      Perfect for developers and tinkerers alike, this script ensures your MagicMirror reflects your updates in real-time, letting you focus on creativity instead of logistics.

      https://github.com/ChrisF1976/MM-Watcher

      Give it a try…

      Regards,
      Chris.

      posted in System
      C
      chrisfr1976
    • RE: MMM-Fireworks

      @sdetweil no, the start time is relevant. If the start time is in the past and the effect time may be stll okay like 3652460601000, the effect does not start. This could be the problem here. So you really need to wait for the defined time in the config.
      I‘ve spent several minutes with waiting….

      posted in Entertainment
      C
      chrisfr1976
    • RE: MMM-Fireworks

      @com1cedric see my answer on GitHub. It only starts if the start time is exactly now or in the future.

      posted in Entertainment
      C
      chrisfr1976
    • RE: MMM-Fireworks

      Hello,

      unfortunately even more optimizations were necessary. So I update the repository.

      New:

      • hides all modules during animation
      • suspends all modules during animation

      Reduced effects:

      createExplosion(x, y) {
              const particleCount = 25; // was 50
      
      this.particles.forEach((p) => {
                  p.x += p.vx;
                  p.y += p.vy;
                  p.vy += 0.01; // less gravity
                  p.alpha -= 0.01;
              });
      
      
          setup() {
              this.canvas.width = this.width*0.95 //reduced width 
              this.canvas.height = this.height*0.95 //reduced height
              window.addEventListener("resize", () => this.resize());
          }
      
      • And updated CSS to be in the middle of the screen again.

      Hopefully you’ll celebrate this, too!

      posted in Entertainment
      C
      chrisfr1976
    • RE: MMM-Fireworks

      Hello,

      a short update since time is running out :)

      I’ve modified the code a little. In my set up I had some performance problems with the animation.

      So I put all other modules in the “Hide” during the animation is running. Afterwards everything will come back (so the plan).

      I don’t know if everybody likes or needs this. So I show the modified code just here.

      Replace the complete code in “MMM-Fireworks.js” with this:

      Module.register("MMM-Fireworks", {
          defaults: {
              startDateTime: "2024-12-31T23:59:00", // ISO format
              duration: 60000, // Duration in milliseconds
          },
      
          start: function () {
              this.fireworksActive = false;
          },
      
          getDom: function () {
              const wrapper = document.createElement("div");
              wrapper.id = "fireworksContainer";
              return wrapper;
          },
      
          notificationReceived: function (notification, payload, sender) {
              if (notification === "DOM_OBJECTS_CREATED") {
                  this.scheduleFireworks();
              }
          },
      
          scheduleFireworks: function () {
              const startTime = new Date(this.config.startDateTime).getTime();
              const currentTime = Date.now();
              const delay = startTime - currentTime;
      
              if (delay > 0) {
                  setTimeout(() => this.startFireworks(), delay);
              } else {
                  console.warn("Fireworks start time has already passed.");
              }
          },
      
          startFireworks: function () {
              this.fireworksActive = true;
              const container = document.getElementById("fireworksContainer");
              container.classList.add("fullscreen");
      
              const canvas = document.createElement("canvas");
              canvas.id = "fireworksCanvas";
              container.appendChild(canvas);
      
              this.sendNotificationToModules("HIDE"); // Module ausblenden
      
              const fireworks = new Fireworks(canvas);
              fireworks.start();
      
              setTimeout(() => {
                  this.stopFireworks(fireworks, container);
              }, this.config.duration);
          },
      
          stopFireworks: function (fireworks, container) {
              fireworks.stop();
              container.innerHTML = ""; // Clear the canvas
              this.fireworksActive = false;
              this.sendNotificationToModules("SHOW"); // Module wieder einblenden
          },
      
          sendNotificationToModules: function (action) {
              MM.getModules().enumerate((module) => {
                  if (module.name !== "MMM-Fireworks") {
                      if (action === "HIDE") {
                          module.hide(500); // Mit Animation ausblenden
                      } else if (action === "SHOW") {
                          module.show(500); // Mit Animation einblenden
                      }
                  }
              });
          },
      
          getStyles: function () {
              return ["MMM-Fireworks.css"];
          },
      
          getScripts: function () {
              return ["fireworks.js"];
          }
      });
      
      

      Party on!

      Cheers Chris.

      posted in Entertainment
      C
      chrisfr1976
    • MMM-Fireworks

      Hi,

      I’ve created a quick module for New Year’s Eve or other events you’d like to highlight on your mirror.

      The MMM-Fireworks module brings a visually stunning fireworks display to your MagicMirror, designed to celebrate special occasions. The fireworks animation runs best in the fullscreen_above region, creating an immersive experience. The start time and duration of the display are configurable via the config.js file.

      MMM-Fireworks

      MMM-Fireworks

      Have fun and take care :-)
      Chris.

      posted in Entertainment
      C
      chrisfr1976
    • MMM-EventSearch - show events in your city from google

      Hi guys,

      I’ve created a new module. My motivation was to see what’s up around me in my city. I’ve missed so many events in my life, so I was searching for an event reminder. But I didn’t find anything that fits to my belongings. So I decided to create something on my own:

      MMM-EventSearch

      The MMM-EventSearch module for MagicMirror fetches and displays event information using the SerpAPI to search for events based on a given query, location, and other parameters. It uses in this case google (see SerpApi for other options) and displays the list results from google which everyone has seen already.

      To find a suitable query go to goolge and try a little for your city or surrounding city/provice/state.
      The results are currently limited to the the results that google initally shows. So the “mode results” button does not work or is not accessible with this API!

      The module dynamically generates a table with event details, displaying:

      • Date/Time: Event’s date and time.
      • Title: The title of the event.
      • Image: A thumbnail image of the event, if available, which links to the event’s page.

      Event Fetching:
      Events are refreshed periodically based on the updateInterval. On the free plan from SerpAPI 100 calls are free per month. So be careful.

      CSS Styling is a little acc. to Google results.

      Bild Text

      Have fun!

      Cheers
      Chris.

      posted in Entertainment
      C
      chrisfr1976
    • RE: MMM-Adventskalender

      Hello,

      I’ve added one nice interactions to the module now. This took me some days to get it fully running. But now I’m quite happy with the result, so I also share it here again:

      • CSS animations for door opening and closing effects.
      • Manual Door Interaction:
        • Click to Open/Close: Clicking a closed door opens it with an animated rotation.
      • Door Opening Animation:
        • 3D rotation animation from the right edge when opening.
        • Reverse animation when closing.

      The state is written in the state.json file. So now your kids can “really” open a door in the morning and if you shut down your mirror in the night it has the same state after a reboot.

      If you’re already running the module delete the state.json file if you feel that something does not work correct (I deleted it quite often during development so I can’t say if there could be an issue).

      The update sounds easy but believe me for me it was not ;-)

      MMM-Adventskalender

      posted in Fun & Games
      C
      chrisfr1976
    • RE: MMM-Adventskalender

      @KristjanESPERANTO Done. I’m not yet completely happy with the style. I’ll work on it next Summer :)

      posted in Fun & Games
      C
      chrisfr1976
    • MMM-Adventskalender

      Hello,

      I’ve created a quick module for an advent calendar. Is is customizable and the images can be chosen individual.

      I’ve made this module quite quick after I got the ideas yesterday morning. I’ll refine it a little but I did’t want to let you wait any longer g

      It could contain some bugs and may not be perfect at this time. Let me know what you notice, and I will try to improve it.

      MMM-Adventskalender

      Example

      posted in Fun & Games
      C
      chrisfr1976
    • RE: ShellyPV mit Shelly 2.5

      @visionmaster Danke für die Antwort. Die Module sind in GitHub aktualisiert.

      So, issue closed until new devices pop up ;-)

      posted in Utilities
      C
      chrisfr1976
    • RE: ShellyPV mit Shelly 2.5

      @visionmaster
      Vielleicht einfacher als gedacht. Wieder als node_helper.js übernehmen:

      const NodeHelper = require("node_helper");
      const axios = require("axios");
      
      module.exports = NodeHelper.create({
          start: function () {
              this.config = {};
      
              setTimeout(() => {
                  console.log("MagicMirror is ready. Fetching ShellyPV status...");
                  this.fetchShellyPVStatus();
              }, 15000); // Delay to ensure MagicMirror is fully loaded
          },
      
          socketNotificationReceived: function (notification, payload) {
              if (notification === "CONFIG") {
                  this.config = payload;
      
                  if (this.config.shellysPV && Array.isArray(this.config.shellysPV)) {
                      console.log("Configuration received, fetching ShellyPV status...");
                      this.fetchShellyPVStatus();
                  }
              } else if (notification === "GET_SHELLYPV_STATUS") {
                  this.fetchShellyPVStatus();
              }
          },
      
          fetchShellyPVStatus: async function () {
              const results = [];
      
              if (!this.config.shellysPV || !Array.isArray(this.config.shellysPV)) {
                  console.error("No valid shellysPV configuration found or 'shellysPV' is not an array.");
                  return;
              }
      
              for (const shellyPV of this.config.shellysPV) {
                  try {
                      const response = await axios.post(
                          `${this.config.serverUri}/device/status`,
                          `id=${shellyPV.id}&auth_key=${this.config.authKey}`
                      );
      
                      const data = response.data?.data?.device_status;
      
                      if (data) {
                          let isOn = false;
                          let power = null;
      
                          // Check for Gen 1/2 structure (relay-based devices)
                          if (data.relays) {
                              const channel = parseInt(shellyPV.ch || 0, 10);
                              isOn = data.relays[channel]?.ison || false;
                              power = data.meters?.[channel]?.power || null;
                          }
                          // Check for Gen 3 structure (pm1:0 devices)
                          else if (data["pm1:0"]) {
                              isOn = true; // Assume true if data exists for the device
                              power = data["pm1:0"].apower; // Use 'apower' from pm1:0
                          }
                          // Check for "switch:0" structure
                          else if (data["switch:0"]) {
                              isOn = data["switch:0"].output; // Use 'output' for on/off status
                              power = data["switch:0"].apower; // Use 'apower' for power
                          }
                          // Check for RGB Shelly structure (lights array)
                          else if (data.lights) {
                              const light = data.lights[0]; // Assume single channel for RGB device
                              isOn = light?.ison || false;
                              power = light?.power || null;
                          }
      
                          results.push({
                              name: shellyPV.name,
                              isOn: isOn,
                              power: power !== undefined ? power : null,
                              statusClass: isOn ? 'on' : 'off', // Dynamically set status class
                          });
                      } else {
                          results.push({
                              name: shellyPV.name,
                              isOn: false,
                              power: null,
                              statusClass: 'off', // Default to off if no data found
                          });
                      }
                  } catch (error) {
                      console.error(`Error fetching status for ${shellyPV.name}:`, error);
                      results.push({
                          name: shellyPV.name,
                          isOn: false,
                          power: null,
                          statusClass: 'off', // Default to off on error
                      });
                  }
              }
      
              this.sendSocketNotification("SHELLYPV_STATUS_UPDATE", results);
          },
      });
      
      

      In der config wieder wie üblich einrichten.

      posted in Utilities
      C
      chrisfr1976
    • RE: ShellyPV mit Shelly 2.5

      @visionmaster
      Perfekt. Freut mich! Morgen probiere mich an der RGB Shelly. Kann es aber noch nicht versprechen. Wenn das läuft aktualisiere ich die Module für Table und PV bei Github.

      posted in Utilities
      C
      chrisfr1976
    • RE: ShellyPV mit Shelly 2.5

      @visionmaster

      Hi,

      please replace the node_helper.js in the module MMM-ShellyPV with the following code. If you receive an error, please describe what you see or what error messages you get. Since I do not have such a device yet it is not possible for me to test it.

      At first I start with the Shelly 2.5 device. The “shellyrgbw2” is then the next step!

      The config must be like this for these specific 2.5 devices:

      shellysPV: [
          { name: "Kueche 1", id: "dcda0cb93bb8", ch: "1" }, // Channel 1 (relay[0])
          { name: "Kueche 2", id: "dcda0cb93bb8", ch: "2" }  // Channel 2 (relay[1])
      ]
      

      I’ve used 1 and 2 instead of 0 and 1. It is easier for my head :-)

      And next the updated node_helper.js file:

      const NodeHelper = require("node_helper");
      const axios = require("axios");
      
      module.exports = NodeHelper.create({
          start: function () {
              this.config = {};
      
              setTimeout(() => {
                  console.log("MagicMirror is ready. Fetching ShellyPV status...");
                  this.fetchShellyPVStatus();
              }, 15000); // Delay to ensure MagicMirror is fully loaded
          },
      
          socketNotificationReceived: function (notification, payload) {
              if (notification === "CONFIG") {
                  this.config = payload;
      
                  if (this.config.shellysPV && Array.isArray(this.config.shellysPV)) {
                      console.log("Configuration received, fetching ShellyPV status...");
                      this.fetchShellyPVStatus();
                  }
              } else if (notification === "GET_SHELLYPV_STATUS") {
                  this.fetchShellyPVStatus();
              }
          },
      
          fetchShellyPVStatus: async function () {
              const results = [];
      
              if (!this.config.shellysPV || !Array.isArray(this.config.shellysPV)) {
                  console.error("No valid shellysPV configuration found or 'shellysPV' is not an array.");
                  return;
              }
      
              for (const shellyPV of this.config.shellysPV) {
                  try {
                      const response = await axios.post(
                          `${this.config.serverUri}/device/status`,
                          `id=${shellyPV.id}&auth_key=${this.config.authKey}`
                      );
      
                      const data = response.data?.data?.device_status;
      
                      if (data) {
                          let isOn = false;
                          let power = null;
      
                          // Handle multi-channel devices
                          if (data.relays && shellyPV.ch) {
                              const channelIndex = parseInt(shellyPV.ch, 10) - 1; // Convert to zero-based index
                              if (channelIndex >= 0 && channelIndex < data.relays.length) {
                                  const relay = data.relays[channelIndex];
                                  const meter = data.meters?.[channelIndex];
      
                                  isOn = relay.ison;
                                  power = meter?.power || 0;
                              } else {
                                  console.error(`Invalid channel index for ${shellyPV.name}: ${shellyPV.ch}`);
                              }
                          }
                          // Handle single-channel devices (or default behavior for Gen 1/2)
                          else if (data.relays) {
                              isOn = data.relays[0].ison;
                              power = data.meters ? data.meters[0].power : null;
                          }
                          // Handle Gen 3 devices (pm1:0 structure)
                          else if (data["pm1:0"]) {
                              isOn = true; // Assume true if data exists
                              power = data["pm1:0"].apower;
                          }
                          // Handle switch:0 structure
                          else if (data["switch:0"]) {
                              isOn = data["switch:0"].output;
                              power = data["switch:0"].apower;
                          }
      
                          results.push({
                              name: shellyPV.name,
                              isOn: isOn,
                              power: power !== undefined ? power : null,
                              statusClass: isOn ? 'on' : 'off', // Dynamically set status class
                          });
                      } else {
                          results.push({
                              name: shellyPV.name,
                              isOn: false,
                              power: null,
                              statusClass: 'off', // Default to off if no data found
                          });
                      }
                  } catch (error) {
                      console.error(`Error fetching status for ${shellyPV.name}:`, error);
                      results.push({
                          name: shellyPV.name,
                          isOn: false,
                          power: null,
                          statusClass: 'off', // Default to off on error
                      });
                  }
              }
      
              this.sendSocketNotification("SHELLYPV_STATUS_UPDATE", results);
          },
      });
      
      

      For devices without a ch parameter, the logic defaults to using the first relay and meter (relays[0], meters[0]), ensuring compatibility with single-channel or older devices.
      If a ch parameter is specified in the config, the code now accesses the corresponding relays and meters arrays for the specific channel.

      posted in Utilities
      C
      chrisfr1976
    • RE: ShellyPV mit Shelly 2.5

      @visionmaster Hi, werde es mir morgen anschauen. Danke für die Infos.

      posted in Utilities
      C
      chrisfr1976
    • RE: ShellyPV mit Shelly 2.5

      @visionmaster Hi, sehe ich mir an. Solche Geräte habe ich im Moment noch nicht im Einsatz. Schicke in der Console mal diesen Befehl an die entsprechende Shelly und poste mir die Antwort:

      curl -X POST https://<server_uri>/device/status -d "id=<device_id>&auth_key=<auth_key>"
      

      In der Antwort Deinen Auth-key löschen!

      Vielleicht werden hier mehrere Infos zurückgeschickt.

      posted in Utilities
      C
      chrisfr1976
    • 1 / 1