Skip to content

Widget development

Nicolas HILAIRE edited this page Jul 29, 2016 · 26 revisions

Develop a widget is relatively easy.

There is no need of special tools like IDE or compilers. You just need a text editor like notepad++.

Widget is the link between user and yadoms using web interface. Using widget you can drive some devices, read others, etc.

Widget representation is based on knock MVVM pattern. You have to develop view and viewmodel and Yadoms finish the job!

A widget has following architecture:

  • package.json: This file describe your widget,
  • view.html: This file represents the view of your widget using knock out syntax,
  • viewModel.js: This file represent the viewmodel of your widget using knock out syntax,
  • widget.css: This file contains all stylesheet information,
  • preview.png: This file contains a little preview image of your widget,
  • locales: This folder contains all i18n files.

API

This API help you to develop your widget. The widget API is accessible from "this.widgetApi" member. Here is the list of all method avalable in the API

find(selector)

This method is equivalent to jquery find() method (https://api.jquery.com/find/) but look only in your widget instance. The query is faster and only matching selector in the current instance of your widget will be returned.

getKeywordInformation(keywordId)

This method asks for all information about the keyword. The method returns a promise.

    //we get the unit of the keyword
    self.widgetApi.getKeywordInformation(self.widget.configuration.device.keywordId)
    .done(function (keyword) {
        self.unit($.t(keyword.units));
    });

registerKeywordAcquisitions(keywordIds)

This method sets all keywords you want your widget will be notified for. the parameter could be an int or an array of int for many keywords. This method must be used in configurationChanged() method because the keywords to listen may have changed after the user change the configuration. So, before entering this method, the keywords to listen for this widget instance are cleared.

    self.widgetApi.registerKeywordAcquisitions(device.content.source.keywordId);

loadLibrary(libraryNames)

This method allow you to load any javascript library file. Library files could be "standard" libraries (see in www/libs) directory of self embedded libraries in your widget directory.

     /**
      * Initialization method
      * @param widget widget class object
      */
    this.initialize = function () {
        var self = this;
        var d = new $.Deferred();

        self.widgetApi.loadLibrary([
            "widgets/counter-display/lib/odometer-0.4.6/odometer.js"
        ]).done(function () {
                //we configure the toolbar
                self.widgetApi.toolbar({
                    activated: true,
                    displayTitle: true,
                    batteryItem: true
                });
                d.resolve();
        });
        return d.promise();
    };

loadCss(cssFiles)

This method allow you to load any style css file. Css files must be embedded into your widget directory.

     /**
      * Initialization method
      * @param widget widget class object
      */
    this.initialize = function () {
        var self = this;
        var d = new $.Deferred();

        self.widgetApi.loadCss([
            ""widgets/counter-display/lib/odometer-0.4.6/themes/odometer-theme-car.css""
        ]).done(function () {
                //we configure the toolbar
                self.widgetApi.toolbar({
                    activated: true,
                    displayTitle: true,
                    batteryItem: true
                });
                d.resolve();
        });
        return d.promise();
    };

toolbar(options)

This method configure the toolbar of your widget. options is a json field that have following structure:

var options = {
    activated: true,
    displayTitle: true,
    items: [....],
    batteryItem: true
};

All fields are optionnals.

field data type description default value
activated boolean Indicates if the toolbar is visible or not false
displayTitle boolean Indicates if the title is displayed or not true
items array Contains the list of items to display in the toolbar []
batteryItem boolean Indicates if the standard battery icon is displayed or not (You must call configureBatteryIcon() method in your configurationChanged() method implementation false

Items

This array contains whole items you want to see in your toolbar. There is two kinds of items: custom or separator. Separator item has no parameters and indicate the you just want to add a vertical separation between many other items. Custom item takes in parameter the html code you want to insert. To keep homogeneous widgets, you can use following css classes:

  • widget-toolbar-button and widget-toolbar-pressed-button for buttons
  • widget-toolbar-element for text elements
self.widgetApi.toolbar({
                   activated: true,
                   displayTitle: true,
                   items: [
                   { custom: "<div class=\"widget-toolbar-button range-btn\" interval=\"HOUR\"><span data-i18n=\"widgets/chart:navigator.hour\"/></div>" },
                   { custom: "<div class=\"widget-toolbar-button range-btn\" interval=\"DAY\"><span data-i18n=\"widgets/chart:navigator.day\"/></div>"},
                   { custom: "<div class=\"widget-toolbar-button range-btn\" interval=\"WEEK\"><span data-i18n=\"widgets/chart:navigator.week\"/></div>"},
                   { custom: "<div class=\"widget-toolbar-button range-btn\" interval=\"MONTH\"><span data-i18n=\"widgets/chart:navigator.month\"/></div>"},
                   { custom: "<div class=\"widget-toolbar-button range-btn\" interval=\"HALF_YEAR\"><span data-i18n=\"widgets/chart:navigator.half_year\"/></div>"},
                   { custom: "<div class=\"widget-toolbar-button range-btn\" interval=\"YEAR\"><span data-i18n=\"widgets/chart:navigator.year\"/></div>" },
                   { separator: ""},
                   { custom: "<div class=\"widget-toolbar-button export-btn dropdown\">" +
                                "<a id=\"chartExportMenu" + self.widget.id + "\" data-target=\"#\" class=\"widget-toolbar-button export-btn dropdown\" role=\"button\" data-toggle=\"dropdown\" aria-haspopup=\"true\" aria-expanded=\"false\">" +
                                    "<span class=\"fa fa-bars\"/>" +
                                "</a>" +
                                "<ul class=\"dropdown-menu\" aria-labelledby=\"chartExportMenu" + self.widget.id + "\">" +
                                    "<li><span class=\"print-command\" data-i18n=\"widgets/chart:export.print\"></span></li>" +
                                    "<li role=\"separator\" class=\"divider\"></li>" +
                                    "<li><span class=\"export-command\" data-i18n=\"widgets/chart:export.png\" mime-type=\"image/png\"></span></li>" +
                                    "<li><span class=\"export-command\" data-i18n=\"widgets/chart:export.jpeg\" mime-type=\"image/jpeg\"></span></li>" +
                                    "<li><span class=\"export-command\" data-i18n=\"widgets/chart:export.svg\" mime-type=\"image/svg+xml\"></span></li>" +
                                    "<li><span class=\"export-command\" data-i18n=\"widgets/chart:export.csv\" mime-type=\"text/csv\"></span></li>" +
                                    "<li><span class=\"export-command\" data-i18n=\"widgets/chart:export.xls\" mime-type=\"application/vnd.ms-excel\"></span></li>" +
                                "</ul>" +
                             "</div>"
                       }
                   ]
               });

This code sample will generate following result

configureBatteryIcon(deviceId)

This method must be used in configurationChanged() method It is used to tell which device could maybe contain a "battery" capacity. If this device has it, the widget Api will automatically grab it and display a battery icon of the top left of the toolbar. the battery icon depends on the real battery keyword value.

fitText()

This method ask to the widget Api to re-compute the font size of each text element in your widget. This is done on each major changes of your widget, but if you have any timer or something else that could change text in your widget, you can call it manually using this method.

notify(message, gravity, timeout)

This method is used to show a yadoms notification. A message is displayed with a gravity during a certain amount of time. Yadoms is using noty engine. More information about a noty can be found here: http://ned.im/noty *message: Text of the notification (mandatory). It could contains some html code in case of more complex noty

*gravity: Gravity of the message (default: information). Values: "information", "alert", "success", "error", "warning", "confirm"

*timeout: Timeout in ms of your notification. (default: 4s). It will automatically disappear after timeout. Use -1 to prevent timeout

The method returns a noty object that you could use as is.

Packaging your widget

When your development has reached a high level of testing, you are ready to push your first Beta version.

Set your version number and release type following Versioning section in your package.json

Put all your files in a zip file named "{widgetName}{version}{releaseType}".zip (ie : "clock_1.0_beta.zip")

Submit your package to the Yadoms team using our forum and wait for the team test up your new version and submit it onto the official repository.

Clone this wiki locally