Read the statement by Michael Teeuw here.
triggering a module
-
hello all im still new to all this and trying to work my way through all this, I created a chores module that when all chores were marked done it would trigger the MMM-Fireworks module. but since the fireworks module updated it no longer triggers the fireworks and now im at a loss on how to get it to work. any help is greatly appreciated.
here is my chores module:
Module.register("MMM-DailyChoreGridColor", { defaults: { updateInterval: 60000, // 1 minute }, start: function() { this.choreList = { MONDAY: [ { chore: "Wash dishes", done: false }, { chore: "Take Out Trash", done: false }, { chore: "Wipe Down Counters", done: false }, { chore: "Pick Up Poop", done: false }, { chore: "Feed Pets", done: false }, { chore: "Play With Petey", done: false }, { chore: "Read", done: false }], TUESDAY: [ { chore: "Wash dishes", done: false }, { chore: "Take Out Trash", done: false }, { chore: "Wipe Down Counters", done: false }, { chore: "Pick Up Poop", done: false }, { chore: "Feed Pets", done: false }, { chore: "Play With Petey", done: false }, { chore: "Read", done: false }], WEDNESDAY: [ { chore: "Wash dishes", done: false }, { chore: "Take Out Trash", done: false }, { chore: "Wipe Down Counters", done: false }, { chore: "Pick Up Poop", done: false }, { chore: "Feed Pets", done: false }, { chore: "Play With Petey", done: false }, { chore: "Read", done: false }], THURSDAY: [ { chore: "Wash dishes", done: false }, { chore: "Take Out Trash", done: false }, { chore: "Wipe Down Counters", done: false }, { chore: "Pick Up Poop", done: false }, { chore: "Feed Pets", done: false }, { chore: "Play With Petey", done: false }, { chore: "Read", done: false }], FRIDAY: [ { chore: "Wash dishes", done: false }, { chore: "Take Out Trash", done: false }, { chore: "Wipe Down Counters", done: false }, { chore: "Pick Up Poop", done: false }, { chore: "Feed Pets", done: false }, { chore: "Play With Petey", done: false }, { chore: "Read", done: false }], SATURDAY: [ { chore: "Wash dishes", done: false }, { chore: "Take Out Trash", done: false }, { chore: "Wipe Down Counters", done: false }, { chore: "Pick Up Poop", done: false }, { chore: "Feed Pets", done: false }, { chore: "Play With Petey", done: false }], SUNDAY: [ { chore: "Wash dishes", done: false }, { chore: "Take Out Trash", done: false }, { chore: "Wipe Down Counters", done: false }, { chore: "Pick Up Poop", done: false }, { chore: "Feed Pets", done: false }, { chore: "Play With Petey", done: false }, { chore: "Clean Room", done: false }, { chore: "Clean Bathroom", done: false }, { chore: "Laundry", done: false }], }; }, getDom: function() { const wrapper = document.createElement("div"); wrapper.innerHTML = "<h2>Daily Chore List</h2>"; const table = document.createElement("table"); table.style.width = "100%"; table.style.margin = "auto"; table.style.borderCollapse = "collapse"; const headerRow = document.createElement("tr"); const daysOfWeek = ["MONDAY", "TUESDAY", "WEDNESDAY", "THURSDAY", "FRIDAY", "SATURDAY", "SUNDAY"]; daysOfWeek.forEach(day => { const dayHeader = document.createElement("th"); dayHeader.innerHTML = day; dayHeader.style.border = "1px solid black"; dayHeader.style.padding = "10px"; dayHeader.style.backgroundColor = "#f2f2f2"; dayHeader.style.textAlign = "center"; headerRow.appendChild(dayHeader); }); table.appendChild(headerRow); const maxChores = Math.max(...Object.values(this.choreList).map(day => day.length)); for (let i = 0; i < maxChores; i++) { const choreRow = document.createElement("tr"); daysOfWeek.forEach(day => { const choreCell = document.createElement("td"); const taskDiv = document.createElement("div"); const task = this.choreList[day][i]; if (task) { const taskText = document.createElement("span"); taskText.innerHTML = task.chore; const dropdown = document.createElement("select"); dropdown.options.add(new Option("X", "false")); dropdown.options.add(new Option("\u2713", "true")); dropdown.value = task.done ? "true" : "false"; this.updateDropdownColor(dropdown, task.done); dropdown.style.float = "right"; // Align dropdown to the right dropdown.onchange = () => { task.done = dropdown.value === "true"; this.updateDropdownColor(dropdown, task.done); console.log(`Task updated: ${task.chore}, Done: ${task.done}`); if (this.allChoresDone()) { console.log("All chores done, sending notification"); this.sendNotification("ALL_CHORES_DONE"); } else { console.log("Not all chores are done yet."); } }; taskDiv.appendChild(taskText); taskDiv.appendChild(dropdown); } choreCell.appendChild(taskDiv); choreCell.style.border = "1px solid black"; choreCell.style.padding = "10px"; choreCell.style.textAlign = "center"; choreRow.appendChild(choreCell); }); table.appendChild(choreRow); } const clearButton = document.createElement("button"); clearButton.innerHTML = "Clear All"; clearButton.style.marginTop = "20px"; clearButton.onclick = () => { Object.keys(this.choreList).forEach(day => { this.choreList[day].forEach(task => { task.done = false; }); }); this.updateDom(); console.log("All chores have been cleared."); }; wrapper.appendChild(clearButton); wrapper.appendChild(table); return wrapper; }, updateDropdownColor: function(dropdown, done) { if (done) { dropdown.style.backgroundColor = "green"; dropdown.style.color = "white"; } else { dropdown.style.backgroundColor = "red"; dropdown.style.color = "white"; } }, allChoresDone: function() { for (const day in this.choreList) { for (const task of this.choreList[day]) { if (!task.done) { console.log(`Task not done: ${task.chore}`); return false; } } } console.log("All chores done: true"); this.sendNotification("ALL_CHORES_DONE"); return true; } });and here is the Fireworks module:
Module.register("MMM-Fireworks", { defaults: { startDateTime: "", // ISO format start time duration: 36000, // Duration in milliseconds (6 hours) // p5 Fireworks settings: fireworkSpawnChance: 0.5, // Chance each frame to spawn a new firework explosionParticleCount: 40, // Number of particles per explosion // Display settings: fullscreen: true, // If false, use the defined width/height. width: "400px", height: "500px", // Velocity settings for rocket particles: magnitude_high: -19, magnitude_low: -8, // Trailing effect transparency (alpha value for background): transparency: 10, // New canvas opacity (0.0 = fully transparent, 1.0 = fully opaque) canvasOpacity: 0.5, // Module management settings: disableAllModules: true, // Set to false so other modules remain visible. keepModules: [], // Array of module names to keep active. // Text overlay: text: "Good Job Buddy" }, start: function () { this.fireworksActive = false; this.disabledModules = []; this._p5Instance = null; }, // Create the module's container. // If fullscreen is true, force full screen; otherwise use the defined width/height. getDom: function () { const wrapper = document.createElement("div"); wrapper.id = "fireworksContainer"; if (this.config.fullscreen) { wrapper.style.position = "fixed"; wrapper.style.top = "0"; wrapper.style.left = "0"; wrapper.style.width = "100vw"; wrapper.style.height = "100vh"; wrapper.style.zIndex = "9999"; wrapper.style.background = "transparent"; } else { wrapper.style.position = "relative"; wrapper.style.width = this.config.width; wrapper.style.height = this.config.height; } // Create and append the text overlay element (initially hidden). if (this.config.text) { const textDiv = document.createElement("div"); textDiv.id = "fireworksText"; textDiv.className = "fireworks-text"; textDiv.innerHTML = this.config.text; textDiv.style.display = "none"; // Hidden by default; shown during fireworks. wrapper.appendChild(textDiv); } return wrapper; }, notificationReceived: function (notification, payload, sender) { console.log("Notification received: " + notification); if (notification === "ALL_CHORES_DONE") { this.startFireworks(); } else if (notification === "DOM_OBJECTS_CREATED") { this.scheduleFireworks(); } }, scheduleFireworks: function () { const MAX_DELAY = 2147483647; // Maximum delay in ms (~24.8 days) const startTime = new Date(this.config.startDateTime).getTime(); const currentTime = Date.now(); const duration = this.config.duration; if (currentTime < startTime) { let delay = startTime - currentTime; if (delay > MAX_DELAY) { setTimeout(() => this.scheduleFireworks(), MAX_DELAY); } else { setTimeout(() => this.startFireworks(), delay); } } else if (currentTime < startTime + duration) { this.startFireworks(); } else { console.warn("Fireworks time window has already passed."); } }, startFireworks: function () { this.fireworksActive = true; const container = document.getElementById("fireworksContainer"); container.classList.add("fullscreen"); // Show the text overlay during the fireworks period. const textDiv = document.getElementById("fireworksText"); if (textDiv) { textDiv.style.display = "block"; } // Do not hide other modules if disableAllModules is false. if (this.config.disableAllModules) { this.deactivateAndHideModules(); } this.initializeP5(); // Play fireworks sound const audio = new Audio("MagicMirror/Modules/MMM-Fireworks/fireworks-sound.mp3"); audio.play(); setTimeout(() => { this.stopFireworks(); }, this.config.duration); }, stopFireworks: function () { if (this._p5Instance) { this._p5Instance.remove(); this._p5Instance = null; } const container = document.getElementById("fireworksContainer"); container.innerHTML = ""; this.fireworksActive = false; if (this.config.disableAllModules) { this.reactivateAndShowModules(); } }, deactivateAndHideModules: function () { const self = this; MM.getModules().enumerate(function (module) { if ( module.name !== "MMM-Fireworks" && self.config.keepModules.indexOf(module.name) === -1 ) { console.log("Hiding module: " + module.name); module.hide(500, () => {}); if (module.suspend) { module.suspend(); } self.disabledModules.push(module); } }); }, reactivateAndShowModules: function () { const self = this; this.disabledModules.forEach(function (module) { console.log("Showing module: " + module.name); module.show(500, () => {}); if (module.resume) { module.resume(); } }); this.disabledModules = []; }, // Integrated p5.js fireworks sketch. initializeP5: function () { if (this._p5Instance) return; const self = this; const config = this.config; this._p5Instance = new p5(function (p) { let fireworks = []; let gravity; // Optional: clear the canvas fully every 2 minutes to remove ghost trails. setInterval(function () { console.log("Performing full redraw (clear) every 2 minutes."); p.clear(); }, 2 * 60 * 1000); p.setup = function () { const container = document.getElementById("fireworksContainer"); p.createCanvas(container.offsetWidth, container.offsetHeight); // Set the canvas opacity to the configured value. p.canvas.style.opacity = config.canvasOpacity; p.colorMode(p.HSB, 255); gravity = p.createVector(0, 0.2); p.background(0); }; p.draw = function () { // Use a semi-transparent background for the trailing effect. p.background(0, 0, 0, config.transparency); // Spawn a new firework with the specified probability. if (p.random(1) < config.fireworkSpawnChance) { fireworks.push(new Firework(p, gravity, config.explosionParticleCount)); } // Update and render fireworks. for (let i = fireworks.length - 1; i >= 0; i--) { fireworks[i].update(); fireworks[i].show(); if (fireworks[i].done()) { fireworks.splice(i, 1); } } }; // --- Particle Class --- class Particle { constructor(p, x, y, hu, isFirework) { this.p = p; this.pos = p.createVector(x, y); this.isFirework = isFirework; if (this.isFirework) { // Rocket's upward velocity based on config values. this.vel = p.createVector(0, p.random(config.magnitude_high, config.magnitude_low)); } else { this.vel = p5.Vector.random2D(); this.vel.mult(p.random(2, 10)); } this.acc = p.createVector(0, 0); this.lifespan = 255; this.hu = hu; } applyForce(force) { this.acc.add(force); } update() { if (!this.isFirework) { this.vel.mult(0.9); this.lifespan -= 4; } this.vel.add(this.acc); this.pos.add(this.vel); this.acc.mult(0); } done() { return this.lifespan < 0; } show() { this.p.strokeWeight(this.isFirework ? 4 : 2); this.p.stroke(this.hu, 255, 255, this.lifespan); this.p.point(this.pos.x, this.pos.y); } } // --- Firework Class --- class Firework { constructor(p, gravity, explosionCount) { this.p = p; this.hu = p.random(255); this.firework = new Particle(p, p.random(p.width), p.height, this.hu, true); this.exploded = false; this.particles = []; this.gravity = gravity; this.explosionCount = explosionCount; } -
@chrisfr1976 yes! it definitely helps! my kid is going to love it. i linked it to a chore list so when he successfully completes all his chores through out the week the fireworks will set off and give him a little party.
-
@lucifer6669 i would use the developers window sources tab
to put stop on send and receive code
-
@sdetweil i apologize but i have no idea what that means
-
@lucifer6669 ctrl-shift-i
select the sources tabfind your source in the left nav
-
@sdetweil gotcha thank you, i dont know all the terminology. but upon completing all tasks i does send the notification but nothing happens after that
-
@lucifer6669 ok, you can step into his code too
-
@lucifer6669 Hi,
See my latest update:https://forum.magicmirror.builders/post/123879
You can use a notification now to start a fireworks. You can also send a specific text message to display. I think this solves your issue :)
-
@chrisfr1976 yes! it definitely helps! my kid is going to love it. i linked it to a chore list so when he successfully completes all his chores through out the week the fireworks will set off and give him a little party.
-
S sdetweil has marked this topic as solved on
Hello! It looks like you're interested in this conversation, but you don't have an account yet.
Getting fed up of having to scroll through the same posts each visit? When you register for an account, you'll always come back to exactly where you were before, and choose to be notified of new replies (either via email, or push notification). You'll also be able to save bookmarks and upvote posts to show your appreciation to other community members.
With your input, this post could be even better 💗
Register Login