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
Action
NodeAdjust the getWeather
Action
node 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
Action
node to ensure the proper execution order of the scenario. -
Add a
Module
NodeInsert a
Module
node between theAction
node and theend
node. -
Add the JavaScript Code to Play Music
Add JavaScript code in the
Module
node that plays music.
While you could use anAction
node to call a plugin (if available), for this example, we will use aModule
node with a simple piece of code that plays all the.mp3
files from a directory.Important:
- Make sure to copy some
.mp3
files into a directory if you don't already have one. - Modify the music library directory on line 29.
Copy the following code into the
Module
node: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