Skip to content

Nodes

Common Actions

  1. In the top-left Actions tab, click on any action to insert that type of node into the editor.
  2. Hover over a node and double-click (left mouse button) to open its configuration window.
  3. You can return to a node’s configuration at any time by double-clicking it.
  4. To move a node, simply hover over it and drag it using the left mouse button.
  5. To create a connection (edge) between two nodes, click on the edge of the first (parent) node and then on the second (child) node; a connecting edge will be automatically created between them.

Node Actions

Save Button

Clicking Save stores the information from the node’s configuration window into the editor.

Warning

Warning: This action does not save the scenario!
To save the scenario, use the main Save button.

Close Button

Closes the configuration window without saving any changes.

Delete Button

Removes the node from the editor, including any connection edges to its parent (preceding nodes) and child (subsequent nodes).

To delete a connection edge without removing the connected nodes, click on the edge with the left mouse button to reveal a Delete button.


Start Node

The Start node is unique and always present in every scenario. It marks the beginning of the scenario and is always connected to at least one Calendar node. It also allows you to assign a mandatory name to the scenario:

  1. In the top-left Actions tab, click on Start.
  2. A pair of nodes—Start and Calendar—will be inserted into the editor.

  3. Open the configuration window for the node.

  4. Enter a name for your scenario.

  5. Click the Save button.
  6. Click the Close button to exit the configuration window.
Important

If you click on the Start action again in the Actions tab, a new Calendar node will be added to the scenario and automatically linked to the existing Start node to create a new branch.

In rare cases, if the new Calendar node isn’t automatically connected to the existing Start node, simply link them manually by clicking on the Start node and then the Calendar node.


Calendar Node

The Calendar node defines the type of scenario execution:

  • Scheduled (Programmed)
  • Triggered by a Rule

Both execution types can be enabled simultaneously—a scenario can be scheduled and triggered by a voice command.

  • Enable the schedule at A.V.A.T.A.R startup:
    Toggle this option to activate or deactivate the scheduled trigger at application startup. This way, you can define a schedule that isn’t necessarily triggered immediately.

  • Enable the rule:
    Toggle this option to activate the voice command trigger at application startup. This lets you set up a rule that isn’t automatically active until you choose to enable it.

By Rule

Enter the voice commands in English that will trigger the scenario.

The editor here is identical to the one in Plugin Studio. For more details on how to use it, refer to the Adding a property section of the documentation.

For additional guidance on writing a rule, see the Plugin rules section.

There’s even an icon available to translate a sentence into English!

By Scheduling

Enter the schedule that will trigger the scenario into each field.

Note

Note: Our cron scheduling supports an enhanced six-field format, allowing for second-level precision. Tools like crontab.guru can help you construct patterns, but remember to account for the seconds field.

Some Examples:

  1. Every 15 Minutes:

    • Seconds: 0 (at 0 seconds; do not use '*' which would mean every second)
    • Minutes: */15 (every 15 minutes)
    • Other Fields: * (every hour, every day)
  2. Every 15 Minutes on Weekdays Only:

    • Seconds: 0
    • Minutes: */15
    • Other Fields: 1-5 (Monday to Friday)
  3. At 2:15 on Weekends in March:

    • Seconds: 0
    • Minutes: 15
    • Hour: 2
    • Day (of month): * (any day)
    • Month: 3 (March)
    • Day (of week): 6-7 (Saturday and Sunday)

Action Node

The Action node lets you trigger a plugin function by supplying the required parameters for its execution.

Tip

Use the Test... button to try the action and ensure it works as expected.

Clients Tab

This tab lets you select the connected clients that are necessary for executing the plugin.

When you select a client from the list, it is automatically formatted and added to the parameters sent to the plugin and its function.

A.V.A.T.A.R handles the breakdown of sending and execution. This means that the client issuing the voice rule (which must be a real client) can be different from the client on which the rule is executed (which may be virtual).
For example, imagine a music plugin with a play function. You might say, “Play music in the Bedroom” from a client in the Living Room. Here, the rule is sent from the Living Room client, but executed on the Bedroom client. In such cases, the confirmation message “It’s done” will be delivered on the Living Room client, while the music plays in the Bedroom. It’s important to understand the plugin and its function and to assign clients accordingly.

Note
  • The Defined by rule client selection is automatically replaced by the client from which you dictated the rule. For scheduled scenarios, since no client triggers the scenario, the default client (set by Config.default.client) is used.
  • If no client is selected for the execution of the task, the task will be executed on the same client that sent it.

Execution Tab

This tab allows you to select the plugin to execute along with its parameters.

Parameters

Language (Required): Replace <language used (e.g. en)> with the two-letter code of your chosen language. For example, use en for English (or fr for French).

Example:

const parameters = {
  command: "<action to call>",
  language: "en",
  client: "Living Room",
  toClient: "Living Room"  
};

command (Optional): The command parameter is often used as the entry point for plugins but is not mandatory. Depending on the plugin, you can either keep it and replace <action to call> with the function to execute, or remove this parameter.

Other Parameters (Optional): You can add any additional parameters necessary for its execution.

For example:

const parameters = {
  command: "set",
  language: "en",
  client: "Salon",
  toClient: "Salon",
  value: "On",
  periph: "25698785"   
}; 

Wait for the action to complete

Waiting for the action to complete requires a clear understanding of how this feature is interpreted.

If you do not check this option, the scenario does not wait for the callback returned by the plugin.
Conversely, the scenario waits for the callback to be returned.
This means that the timing of when the callback is returned in the plugin is extremely important.

Let's consider this classic example of an action() function in a plugin:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
export async function action(data, callback) {
    try {
        // Table of actions
        const tblActions = {
            // test (see rules table in the property file)
            musicScenario : () => musicScenario(data.client),
            stopMusicScenario : () => stopMusicScenario(data.client)    
        }

        tblActions[data.action.command]()
        info("musicScenario");
    } catch (err) {
        if (data.client) Avatar.Speech.end(data.client);
        if (err.message) error(err.message);
    }   

    // Returns callback
    callback();
}

Explanation:
As you can see, the callback is returned at the end of the action() function and does not wait for any of the commands to complete. This means that the callback is returned almost instantaneously, and the scenario will proceed before the Action node has fully executed.

Let's consider another example of an action() function:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
export async function action(data, callback) {

    try {
        // Table of actions
        const tblActions = {
            getWeather : () => getWeather(data.client, data.action?.byScenario, callback)                   
        }

        info("meteomatics:", data.action.command, L.get("plugin.from"), data.client);

        tblActions[data.action.command]();
    } catch (err) {
        if (data.client) Avatar.Speech.end(data.client);
        if (err.message) error(err.message);
    }   

    //Test if the command is sent by a scenario or by a voice rule.
    if (!data.action?.byScenario) callback();
}

Explanation:
The scenario sends a parameter data.action.byScenario to the plugin. A check is performed on this parameter, and the callback is executed only if the command is triggered by a voice rule. The callback is also passed as a parameter to the command getWeather.

The getWeather function is defined as follows:

 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
async function getWeather(client, byScenario, callback) {

    // Some stuffs
    //...

    // Execute a http request
    axios.get(url, {
        auth: {
          username: username,
          password: password
        }
      })
      .then(response => {
        const sentence = createWeatherSentence(city, results);

        Avatar.speak(sentence, client, () => {
            // Execute the callback at the end of the speak
            if (byScenario) callback();
        });
      })
      .catch(err => {
        // If an error appears
        Avatar.Speech.end(data.client);
        // Execute the callback in an error appears
        if (byScenario) callback();
      });
}

Explanation:
The callback is executed within the callback of the speak function, at the very end of the plugin's execution, and the scenario will indeed wait until the plugin's function has finished executing before proceeding to the next node.

The parameters for the Action node in the scenario are defined as follows:

1
2
3
4
5
6
const parameters = {
  command: "getWeather",
  language: "fr",
  client: "Living room",
  byScenario: true
};

Explanation:
The parameter byScenario is set to true to indicate that the command is sent by the scenario.

In conclusion:
Check how the plugin works. Some plugins do not require a strict execution order. For others, it is important to verify where the callback is returned so that the execution order of the scenario is maintained.

Node Javascript

The Javascript node allows you to execute a JavaScript function.

Important: The name my_function must always be replaced with a unique function name within the scenario.

my_function(payload, state) - Async function called by the scenario.

  • @param {string} payload - Payload sent by a payload node.
  • @param {object} state
    • By rule: The state object containing the parameters defined by the rule.
    • By program: client and toClient only.
  • @returns {Promise<object>} or @returns {Promise<string>}
    • A promise that resolves the function
    • Examples:
    • return { payload: payload, state };
    • return { payload: payload, state, value1, value2 };
    • return payload; (state is automatically retrieved)
Note

Find examples of using the Javascript node in the scenario creation examples sections.


Node Module

The Module node allows you to add a JavaScript module to be executed.

The Module node behaves like a JavaScript file (.js), where you can include imports or functions just like in a normal JS file.

Important: The action function is the entry point of the module. It must always be present and its name must never be changed.

action(payload, state) - Main async function of the module called by the scenario.

  • @param {string} payload - Payload sent by a payload node.
  • @param {object} state
    • By rule: The state object containing the parameters defined by the rule.
    • By program: client and toClient only.
  • @returns {Promise<object>} or @returns {Promise<string>}
    • A promise that resolves the function
    • Examples:
    • return { payload: payload, state };
    • return { payload: payload, state, value1, value2 };
    • return payload; (state is automatically retrieved)
Note

Find examples of using the Module node in the scenario creation examples sections.


Node Payload

The Payload node acts as a choice selector to direct the scenario toward a specific branch. It is used with Javascript and Module nodes that return a value of type string. If the returned value matches the one defined in the payload, that branch is selected and the other branches are ignored.

For example, consider a very simple scenario with a Javascript node that returns a value which can be either "Yes" or "No":

  1. Node Javascript :

    async function myChoice(payload, state){
    
    const value = Math.random() < 0.5 ? "Yes" : "No";
    
    // Returns the payload
    return { payload: value, state };
    }
    

  2. Two Payload nodes must be created to handle the two possible choices:

    • A Payload node for "Yes":

    • A Payload node for "No":

  3. The scenario will then be defined as follows:


Node Speak

This node allows you to vocalize a text on a client.

  1. Enter the text to be vocalized.
  2. Select the client to which the TTS will be delivered.
  3. Choose whether listening should resume after the text is spoken on the client.
  4. Choose whether the scenario waits for the TTS to finish before executing the next node.
Note
  • The client selection Defined by rule is automatically replaced by the client from which you dictated the rule. For scheduled scenarios, since there is no triggering client, the default client is used (parameter Config.default.client).

Node Timer

The Timer node allows you to create a delay of a few seconds between a parent node and its child—for example, between two Action nodes.

Possible delay range: from 0 to 600 seconds maximum (10 minutes).

Warning!: If you need a longer delay, it is advisable to create a new branch that will be scheduled at a different time.


Node End

The End node is mandatory and always terminates a branch of the scenario.
If the scenario has multiple branches, the same End node can be used for all branches.