Modifying the Scenario
Scenario Objective
Enhance your scenario by adding a music-playing feature. After the weather information is provided by the getWeather Action node, the scenario will use a module node to play music. This module node will run JavaScript code that reads all .mp3 files from a specified directory and plays them.
Steps to Modify the Scenario
-
Modify the getWeather
ActionNodeAdjust the getWeather
Actionnode so that the execution order is maintained.
Check the configuration for this stepImportant
Please refer to the Wait for the action to complete chapter to understand why you need to modify the getWeather
Actionnode to ensure the proper execution order of the scenario. -
Add a
ModuleNodeInsert a
Modulenode between theActionnode and theendnode.
-
Add the JavaScript Code to Play Music
Add JavaScript code in the
Modulenode that plays music.
While you could use anActionnode to call a plugin (if available), for this example, we will use aModulenode with a simple piece of code that plays all the.mp3files from a directory.Important:
- Make sure to copy some
.mp3files into a directory if you don't already have one. - Modify the music library directory on line 29.
Copy the following code into the
Modulenode:1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74
import * as path from 'node:path'; import fs from 'fs-extra'; import * as url from 'url'; // The error on the left appears because CodeMirror (the editor) does not accept this type of import but it works ! // The app is in esversion 11. const __dirname = url.fileURLToPath(new URL('.', import.meta.url)); // Main function export async function action(payload, state) { // Play music playMusic(state.client); // Return the payload return { payload: payload, state }; } function playMusic(client) { // WARNING: The module runs in the app/tmp directory of the application. // Define an absolute path or a path relative to app/tmp. // Examples: // var musicDirectory = path.resolve(__dirname, '..', '..', '..', 'music'); // or // var musicDirectory = 'C:/music' || '/music'; var musicDirectory = 'ENTER YOUR MUSIC REPOSITORY !'; Avatar.static.set(musicDirectory, () => { fs.readdir(musicDirectory, (err, files) => { if (err) { info("Error reading directory:", err); return; } // Filter to keep only files with a .mp3 extension const mp3Files = files.filter(file => file.endsWith('.mp3')); if (mp3Files.length === 0) { info("No mp3 files found in the directory."); return; } let currentIndex = 0; // Recursive function that plays the next song function playNext() { if (currentIndex >= mp3Files.length) { info("End of the playlist."); return; } // Construct the full URL to the mp3 file const music = `http://${Config.http.ip}:${Config.http.port}/${mp3Files[currentIndex]}`; info('Playing mp3:', music); currentIndex++; // Call the Avatar.play function with a callback Avatar.play(music, client, 'url', () => { // Callback called at the end of each song only if playback has not been stopped if (Config.scenarios["alarm clock"].enable) playNext(); }); } // Start playback playNext(); }); }); }Expected result :

- Make sure to copy some