Skip to content

Create a button widget

Weather forecast plugin (part 1)

In this example, you'll learn step-by-step how to develop a widget button by the creation of a plugin which retreives the weather forecast.

Note that this example is the part 1 of a complet plugin in three parts which ultimately displays the weather forecast in a window.
The first part deals with adding a widget button to the interface.

  • Step 1: Creating a plugin
  • Step 2: Adding a widget button

Warning

This plugin is part of the A.V.A.T.A.R. plugin library.
If you've already installed it, please remove it or save it before continuing !!

Create the plugin

  1. Start the server in a terminal
  2. Create the plugin with Plugin Studio

    • Nom : weather
    • Affiché: Weather forecast
    • Rules: No

      no-voice-rule

    • Script methods:

      • Language localization methods
      • Methods for creating and managing widget buttons (onClose() and init() methods are added automatically)

      pak-widget

    • Add an image

      • Select image <A.V.A.T.A.R>/resources/app/assets/images/PluginCreation/weather.png

      weather-select-image

    • No documentation

    meteo-plugin

Plugin modification

The Plugin Studio automatically creates a complete application core with files and methods that may be required depending on the type of button and the complexity of the plugin.
The weather plugin is a simple plugin that doesn't require specific methods to update information, so first, we will do a bit of clean-up.

  1. Delete the lib folder and its contents.

    • Open a terminal and navigate to the plugin folder
      cd <A.V.A..T.A.R>/resources/app/cores/plugin/weather
      
    • Delete the lib folder
    Note

    The lib directory is automatically created with a js file including methods for getting, modifying and setting information of home automation devices in order to create button widgets of list of values or float types.

    The list of values and float types are automatically created in Widget Studio according to the type of home automation device.

    The Button type is the only possible type that can be initialized in a plugin.

    In our example, we create a Buttons type to execute an action, the lib directory is not needed.

  2. Edit the plugin script file in Visual Studio (or another text editor)

    • Open the <A.V.A.T.A.R>/resources/app/core/plugins/weather/weather.js file
    • The plugin has no voice rules, we will take this opportunity to move the getpak() method from the action() method to the init() method.
      • Warning: Change data.language to Config.language, the language code is now linked to the application and not to a client language
    • Delete all comments and unnecessary imports added during plugin creation (you can keep the comments you like)


    The result should look like this:

    weather.js
    import * as path from 'node:path';
    import * as url from 'url';
    const __dirname = url.fileURLToPath(new URL('.', import.meta.url));
    
    // Internal module, mandatory to manage widgets
    import * as widgetLib from '../../../widgetLibrairy.js';
    const Widget = await widgetLib.init();
    
    // devices table
    let periphInfo = [];
    //language pak
    let Locale;
    
    const widgetFolder = path.resolve(__dirname, 'assets/widget');
    const widgetImgFolder = path.resolve(__dirname, 'assets/images/widget');
    
    export async function onClose (widgets) {
        // Save widget positions
        if (Config.modules.weather.widget.display === true) {
            await Widget.initVar(widgetFolder, widgetImgFolder, null, Config.modules.weather);
            if (widgets) await Widget.saveWidgets(widgets);
        }
    }
    
    
    export async function init () {
        if (!await Avatar.lang.addPluginPak("weather")) {
            return error('weather: unable to load language pak files');
        }
    
        Locale = await Avatar.lang.getPak("weather", Config.language);
        if (!Locale) {
            return error (`weather: Unable to find '${Config.language}' language pak.`);
        }
    }
    
    
    export async function getWidgetsOnLoad () {
        if (Config.modules.weather.widget.display === true) {
            await Widget.initVar(widgetFolder, widgetImgFolder, null, Config.modules.weather);
            let widgets = await Widget.getWidgets();
            return {plugin: "weather", widgets: widgets, Config: Config.modules.weather};
        } 
    }
    
    
    export async function readyToShow () {
    
    }
    
    
    export async function getNewButtonState (arg) {
        return;
    }
    
    
    export async function getPeriphInfo () {
        return periphInfo;
    }
    
    
    export async function widgetAction (even) {
    
        infoConsole(even.value);
    
    }
    
    
    export async function action(data, callback) {
        callback();
    }
    
  3. Restart A.V.A.T.A.R

    • Press Ctrl +C in the terminal to stop the server
    • Get the last command npm start . to restart the server
  4. Test the plugin

    • No errors should appear in the terminal or in the A.V.A.T.A.R. console

Add a widget button

Initialization

The 1st step is to initialize the button by adding a Button widget to the periphInfo variable.

Below is a description of the possible keys to a Button widget:

Key Format Mandatory Description
name string yes Widget name
value_type string yes Bouton type.
Must always be Button
usage_name string yes The name of a directory in <plugin>/assets/images/widget where image files for widget states will be used
periph_id string yes A random value. This value must be unique for all widgets (including other plugins).
notes string no A widget information note
  1. Add the following lines to the init() method

    weather.js
    export async function init () {
        if (!await Avatar.lang.addPluginPak("weather")) {
            return error('weather: unable to load language pak files');
        }
    
        Locale = await Avatar.lang.getPak("weather", Config.language);
        if (!Locale) {
            return error(`weather: Unable to find the '${Config.language}' language pak.`);
        }
    
        periphInfo.push({
            Buttons: [
                {
                    name: "Weather",
                    value_type: "button",
                    usage_name: "Button",
                    periph_id: "808221",
                    notes: "Open weather forecast"
                }
            ]
        });
    }
    
  2. Add a currentwidgetState global variable to save the button's current state

    weather.js
    // devices table
    let periphInfo = [];
    //language pak
    let Locale;
    // button state
    let currentwidgetState; 
    
    const widgetFolder = path.resolve(__dirname, 'assets/widget');
    
  3. Add calls to currentwidgetState like in the 2 methods below

    weather.js
    export async function getNewButtonState (arg) {
        return currentwidgetState === true ? "Off" : "On";
    }
    
    export async function getPeriphInfo () {
        return periphInfo;
    }
    
    export async function widgetAction (even) {
        currentwidgetState = even.value.action === 'On' ? true : false;
        infoConsole(even.value);
    }
    
  4. Restart A.V.A.T.A.R and get the last command npm start . to restart the server

Settings

Once the widget has been initialized, it needs to be configured to appear in the A.V.A.T.A.R. interface.

  1. Open Widget Studio
  2. Click on Plugins tab and click on Weather forecast plugin
  3. Scroll down Buttons and click on Weather

    Widget Studio

  4. Action On:

    • Select Weather forecast plugin
    • Add an Off parameter
  5. Action Off:

    • Select Weather forecast plugin
    • Add an On parameter

    Widget Studio

  6. Click on the Images tab

  7. Click on the image On
    • Select image <A.V.A.T.A.R>/resources/app/assets/images/PluginCreation/weather.png
    • Select Customized for the device
  8. Click on the image Off

    • Select image <A.V.A.T.A.R>/resources/app/assets/images/PluginCreation/weather-icon.png
    • Select Customized for the device

    Widget Studio

  9. Click on the Create button

    • The button appears in the A.V.A.T.A.R. interface
    • You can test it by clicking on it
  10. Click on the Settings tab
  11. Set the Opacity slider to 0
  12. Click on the Modify button
    • The button's border is now transparent in the A.V.A.T.A.R. interface
  13. Click on close to exit the Widget Studio window
  14. In the A.V.A.T.A.R interface, move the button by selecting its (transparent) border
  15. To save its location, exit A.V.A.T.A.R via the node server menu.

    Warning

    Do not Ctrl +C in the terminal, otherwise the Onclose() method will not be executed and the location will not be saved.

  16. In the terminal, retrieve the last command npm start . to restart the server.

Success

We now have a Weather button in the A.V.A.T.A.R. interface!

Add button actions

The widgetAction method executes a infoConsole, you can check the actions On and Off by opening A.V.A.T.A.R's Chromium console.

export async function widgetAction (even) {
    currentwidgetState = even.value.action === 'On' ? true : false;
    infoConsole(even.value);
    // Returns: 
    // {
    //    action: "On"
    //    description: "Off"
    //    plugin: "Weather forecast"
    // }
}

Widget Studio

In the following example, we will display the weather forecast in a window.



IntroductionCreate a window - Part 2