Skip to content

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

  1. Modify the getWeather Action Node

    Adjust the getWeather Action node so that the execution order is maintained.
    Check the configuration for this step

    Important

    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.

  2. Add a Module Node

    Insert a Module node between the Action node and the end node. Screenshot

  3. Add the JavaScript Code to Play Music

    Add JavaScript code in the Module node that plays music.
    While you could use an Action node to call a plugin (if available), for this example, we will use a Module 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 :

    Screenshot


Next Step