JavaScript API

From MiOS
Revision as of 11:17, 10 October 2014 by Andreimios (Talk | contribs)

Jump to: navigation, search

Contents

Usage

"Tabs": [
       {
           "Label": {
               "lang_tag": "users",
               "text": "Users" 
           },
           "Position": "0",
           "TabType": "javascript",
           "ScriptName": "I_HomeCare.js",
           "Function": "showUsers"
       }, 

To generate a tab using your JavaScript functions you need to specify this by setting TabType to javascript. Then, you need to specify the script file's name and which function in this file will be used to draw the tab's content. That function will have one argument, which is the device number.

<functionName> (deviceNumber)

This is the tab rendering function. The set_panel_html function must be called at the end.

Input:

  • deviceNumber (number)

Output:

  • nothing


Variables

jsonp.ud

This is the user data.

  • Type: object
  • Members:
    • devices (array)
    • scenes (array)
    • users (array)
    • rooms (array)
    • eventList (array)
    • etc.


jsonp.ud.devices

  • Type: array
  • Members:
    • id (number)
    • device_type (string)
    • room (number)
    • name (string)
    • category_num (number)
    • etc.


jsonp.ud.scenes

  • Type: array
  • Members:
    • id (number)
    • name (string)
    • room (number)
    • Timer_ids (array)
    • Timer (object)
    • etc.


Functions

get_device_state (deviceId, serviceId, variable, dynamic)

Input:

  • deviceId (number)
  • serviceId (string)
  • variable (string)
  • dynamic (number): if 1, the variable's value is taken from lu_status, else, the variable's value is taken from user_data. user_data is read at Luup startup, so for variables that change their value frequently (like Watts, Temperature, etc.) dynamic should be 1.

Output:

  • variable value (string or undefined)


set_device_state (deviceId, serviceId, variable, value, dynamic)

Input:

  • deviceId (number)
  • serviceId (string)
  • variable (string)
  • value (string)
  • dynamic (number): if 1, the variable's value is saved to lu_status (the value is lost after Luup is restarted), else, the variable's value is saved to a copy of user_data; the real user_data is updated when LuaUPnP is restarted.

Output:

  • true if the operation succeeded, false otherwise


_console (str)

Input:

  • str (string): text to be written in the console. You need to have FireBug installed in order to have a console.

Output:

  • nothing


set_panel_html (html)

Used in the tab rendering functions.

Input:

  • html (string): The html to be used for generating the tab content.

Output:

  • nothing

JavaScript API for UI7

Introduction

One of the new features of UI7 is the Javascript API for writing plugins. This is a free programming interface which is robust, well documented and comes with a guarantee that it will be compatible with the following UI releases.

What is this “API” ?

Simply said: it is a layer between the UI and the plugin developer. This way, the developer can use the features available in the UI by interacting only with the API. By using the new features available in the API, the overall user experience can be visibly improved.

How does it work ?

The API comes in the form of a library which exposes to the developer the objects and methods/functions needed to implement functionality in their plugins.

How is this different from the previous way of writing plugins ?

The developers were writing Javascript code and they had full access to the core of the application. There were a couple of objects and functions written by the UI team which were easing the work for the developer. By using the new API, the developer can write code without interfering with the core of the application.

What is new ?

  • The developer can write the plugin without interfering with any other code except the API. This means there are a great bundle of methods like setters and getters which help writing good code.
  • UI team can make any changes to the core of the application, but as long as the API stays the same, the plugins will work. This way, the application can be improved and the developer won’t have to fix the code in order for it to work. New versions of the UI can be launched and the plugins will be compatible.
  • Event handling - the application will notify the plugin (via the API) about the events that happen inside. Consider, for example, the addition of a new device to the unit. The developer will know, by simply listening to an event, that a device was added and so, (s)he will write the code in such a way that it will take into account the event. The user experience will be greatly improved.
  • Asynchronous getters and setters - because most of the actions that happen inside the UI is asynchronous, so are the API’s method written. Most of them have a signature like this: function getXXX(obj, onSuccess, onFailure), where ‘onSuccess’ and ‘onFailure’ are callback functions which are called based on the result of the call.
  • No more global variables to manipulate. Everything is handled through getters/setters via API.
  • An API reference documentation: every method and its parameters is carefully documented so that the developer would know what the function does, how to call it and what it will return.
  • A couple of guidelines will be given to help developers write better code in such a way that two different plugins won’t “harm” each other. The module pattern will be used as a design pattern in order to put a plugin code inside a namespace. Also, this module helps in writing code which is easier to read and use.
  • It will be easier for the developers to write the code by using a new feature in the UI which generates the skeleton for the plugin.

What is the API reference documentation ?

This is the part which makes the API usable. Every aspect of the API, no matter how trivial, will be stated explicitly. It contains:

  • a description of all the data structures it depends upon
  • a description of all the function signatures:
    • function names
    • function parameters (names and types)
    • return type of the function
    • if it throws any exceptions or not

Where is the list of functions which were replaced ?

In the API reference documentation the developer can find out if a function replaces an old one.

Why should a developer write plugins using the API when it can do some “reverse engineering” and directly access any object/functionality of the application ?

It is not mandatory to write the code for the plugin this way. Probably the plugin will work as long as changes are not made in the core of the application, but the API comes also with a guarantee that after application changes, the plugins will continue to work. The UI team and plugin developers have the same goal: to deliver the best experience to the user. This is where the API comes into place - an interface between the two.

Will the API be rewritten with each new UI release ?

No. It will be improved. The goal of the API is to provide a stable interface to the developer so that when changing the core of the application it won’t be necessary to rewrite the plugins.

Is this API going to change in the near future ?

It can be changed. There will be parts of it which are going to be marked as ‘deprecated’. This means that the parts will be candidates for being removed, or modified in a backward incompatible way. The developers will be advised on how are they to change their code in order to use the features which replace the deprecated parts.

Is the API complete ?

Almost. Most of the functionality is there, but developers are encouraged to request new features from the API which will be added in future releases.

Guidelines on writing Javascript code for plugins in UI7

  • Use the module pattern to organize your code inside a namespace. Choose a well defined name for your namespace.
  • Generate an UUID for your plugin. This way you can use the events engine.
  • Use the provided API plugins to perform most of your stuff. If you can’t find an implemented method inside the API you can ASK for an implementation to it.
  • NEVER USE variables/functions which are not accessible through API ! They can be changed or removed at any time.
  • If you need to do a background job (ex: start a timer), use the events engine and register a ‘cleanup’ function in which you finish the job (clear the timer).
  • We encourage the use of try { … } catch { … } blocks everywhere in your functions so that errors don’t get propagated to the top of the application.
  • Start from the skeleton provided and expand it:
var MyPlugin = (function (api) {
// example of unique identifier for this plugin...
var uuid = 'B971F6C4-F315-4E2E-AD08-F029A9777517';
 
var myModule = {};
 
function doSomething() {
        // register to event ‘on_ui_cpanel_before_close’...
        api.registerEventHandler('on_ui_cpanel_before_close', myModule, ‘cleanUp’);
        // and do something... 
    }
 
    function cleanUp() {
        // perform clean up...
    }
 
    myModule = {
        uuid: uuid,
        doSomething: doSomething,
        cleanUp: cleanUp
    };
    return myModule;
})(api);

Your plugin functions will be accessible via MyPlugin.doSomething() construction. When the user will leave the cpanel, your plugin will be noticed via event ‘on_ui_cpanel_before_close’; this way you can perform the necessary cleanup.

JavaScript API

Defined in: api.js

Class Summary


API(config, application, ui)

- API class for plugins

Parameters:

  • {object} config - holds configuration data
  • {object} application - application layer
  • {object} ui - interface

Method Summary


{Object} cloneObject(obj)

- Clones a given object

- Replaces: cloneObject()

Parameters:

  • {object} obj - object to be cloned

Returns:

  • {Object}

{string} getCpanelContent()

- Retrieves cpanel content

- Replaces: get_panel_html()

Returns:

  • {string} HTML code set in cpanel

{number} getCpanelDeviceId()

- Returns device id for current opened cpanel or 0 if not found

Returns:

  • {number} - device ID

getCurrentHouseMode(onSuccess, onFailure, context)

- Performs a data request to retrieve the current house mode

Parameters:

  • {*} onSuccess Optional - function to be called if the call is successfull
  • {*} onFailure Optional - function to be called if the call fails
  • {object} context Optional - context in which to execute the functions of success and/or failure

{number} getDeviceIndex(deviceId)

- Retrieves device index for given device id

- Replaces: get_device_index()

Parameters:

  • {number} deviceId - id of the device

Returns:

  • {number}

{*} getDeviceObject(deviceId)

- Retrieves device object given its id

- Replaces: get_device_obj()

Parameters:

  • {number} deviceId - id of the device

Returns:

  • {number}

{object} getDeviceState(deviceId, service, variable, options)

- Retrieves device state for a device (it can be either read from user data or lu status, depending on the options set)

Parameters:

  • {number} deviceId - id of the device
  • {string} service - name of the service
  • {string} variable - name of the variable
  • {object} options Optional - list of options like: 'dynamic': (true - lu_status will be used [default], false - user_data will be used)

Returns:

  • {object} value for a given variable

{Object|Boolean} getDeviceTemplate(deviceId)

- Returns device template for a given device id

Parameters:

  • {number} deviceId - id of the device

Returns:

  • {Object|Boolean}

{*} getDisplayedDeviceName(deviceId)

- Retrieves displayed device name or 'unnamed device' if device doesn't have a name or undefined if device not found

Parameters:

  • {number} deviceId - id of the device

Returns:

  • {*} if device is found a string which contains the device name or 'Unnamed device' if device name is not set, or undefined if device wasn't found

{*} getEventDefinition(deviceType)

- Retrieves event list for a given device type

- Replaces: get_event_definition()

Parameters:

  • {string} deviceType - type of device

Returns:

  • {*}

{*} getListOfDevices()

- Returns the list of devices from userdata

Returns:

  • {*}

getLuSdata(onSuccess, onFailure, context)

- Performs a data request to retrieve lu_sdata

Parameters:

  • {*} onSuccess Optional - function to be called if the call is successfull
  • {*} onFailure Optional - function to be called if the call fails
  • {object} context Optional - context in which to execute the functions of success and/or failure

{*|Object} getRoomObject(roomId)

- Returns room object given a room id

- Replaces: get_room_by_id()

Parameters:

  • {number} roomId - id of the room

Returns:

  • {*|Object}

{*} getUserData()

- Retrieves userData or null if error

- Replaces: jsonp.ud

Returns:

  • {*} object containing userdata

registerEventHandler(eventName, object, functionName)

- Register an event handler.

Parameters:

  • {string} eventName - name of the event to register to
  • {object} object - the object which registers to the event
  • {string} functionName - the name of the function to be executed if event triggers

runUpnpCode(code, options, onSuccess, onFailure, context)

- Runs given Upnp code

Parameters:

  • {string} code - code to execute
  • {object} options Optional - optionally options to be supplied (will be documented later)
  • {*} onSuccess Optional - function to be called if the call is successfull
  • {*} onFailure Optional - function to be called if the call fails
  • {object} context Optional - context in which to execute the functions of success and/or failure

setCpanelContent(html)

- Sets content for the cpanel

- Replaces: set_panel_html()

Parameters:

  • {string} html - the new content of the cpanel

setCurrentHouseMode(modeValue, onSuccess, onFailure, context)

- Sets current house mode

Parameters:

  • {number} modeValue - new value for the house mode
  • {*} onSuccess Optional - function to be called if the call is successfull
  • {*} onFailure Optional - function to be called if the call fails
  • {object} context Optional - context in which to execute the functions of success and/or failure

setDeviceStateVariable(deviceId, service, variable, value, onSuccess, onFailure, context)

- Sets state for a device variable using variableset request.

- Replaces: set_device_state()

Parameters:

  • {number} deviceId - id of the device
  • {string} service - name of the service
  • {string} variable - name of the variable
  • {*} value - new value for the variable
  • {*} onSuccess Optional - function to be called if the call is successfull
  • {*} onFailure Optional - function to be called if the call fails
  • {object} context Optional - context in which to execute the functions of success and/or failure


Events


The list of available events can be obtained with the following command:

api.getListOfSupportedEvents()

  • on_startup_showModalLoading
    • triggered before loading resources in the browser
  • on_startup_luStatusLoaded
    • triggered after luStatus was successfully parsed
    • parameter: luStatusObject
  • on_startup_show2gInterface
    • triggered after requesting account devices only if UI is not in ‘local mode’ and ‘slowConnection’ flag is set
  • on_ui_requireSave
    • triggered if user data was changed and save wasn’t issued
  • on_ui_userDataFirstLoaded
    • fired if user data was loaded for the first time
  • on_ui_staticDataAdded
    • fired if static_data was added to user data
    • parameter: staticDataObject
  • on_ui_staticDataChanged
    • fired if static_data was changed after parsing user data
    • parameter: changedStaticDataObject
  • on_ui_staticDataRemoved
    • fired if static_data was removed after parsing user data
    • parameter: idForRemovedStaticDataObject
  • on_ui_setupDeviceAdded
    • fired if new setup device (menu item) is added
    • parameter: setupDeviceObject
  • on_ui_setupDeviceChanged
    • fired if setup device (menu item) is changed
    • parameter: changedSetupDeviceObject
  • on_ui_setupDeviceRemoved
    • fired if setup device (menu item) is removed
    • parameter: idForRemovedSetupDeviceObject
  • on_ui_sectionAdded
    • triggered when new section is added
    • parameter: sectionObject
  • on_ui_sectionChanged
    • fired after section was changed
    • parameter: changedSectionObject
  • on_ui_sectionRemoved
    • fired after section was removed
    • parameter: idForRemovedSectionObject
  • on_ui_roomAdded
    • fired when new room was added to user data
    • parameter: roomObject
  • on_ui_roomChanged
    • fired after room was changed
    • parameter: changedRoomObject
  • on_ui_roomRemoved
    • fired after room was removed from user data
    • parameter: idForRemovedRoomObject
  • on_ui_deviceAdded
    • fired after device was added to user data
    • parameter: deviceObject
      • wrapper object for
        • device: this is the actual object representing the device
        • deviceTemplate: object with the static data associated to this device type
  • on_ui_deviceChanged
    • fired after device was found changed in user data
    • parameter: changedDeviceObject
      • wrapper object for
        • device: this is the actual object representing the device
        • deviceTemplate: object with the static data associated to this device type
  • on_ui_deviceRemoved
    • fired after device was found removed from user data
    • parameter: idForRemovedDeviceObject
  • on_ui_deviceJobsReceived
    • fired when jobs are found for a device in lu_status
    • parameter: deviceObjectFromLuStatus
  • on_ui_sceneAdded
    • fired after scene was added
    • parameter: sceneObject
  • on_ui_sceneChanged
    • fired after scene was changed
    • parameter: changedSceneObject
  • on_ui_sceneChanged
    • fired when scene is removed
    • parameter: idForRemovedSceneObject
  • on_ui_pluginAdded
    • triggered when plugin is added to user data
    • parameter: pluginObject
  • on_ui_pluginChanged
    • triggered when plugin is changed
    • parameter: changedPluginObject
  • on_ui_pluginRemoved
    • triggered when plugin is removed
    • parameter: idForRemovedPluginObject
  • on_ui_extraSubmenuItemAdded
    • triggered when extra submenu item is added
    • parameter: extraSubmenuItemObject
      • wrapper for:
        • submenuItem: object containing submenu item
        • deviceType: string which contains the type of device for which the submenu item is added
  • on_ui_extraSubmenuItemChanged
    • triggered when extra submenu item is changed
    • parameter: changedExtraSubmenuItemObject
      • wrapper for:
        • oldObj: contains previous submenu item
        • newObj: wrapper for:
          • submenuItem: object containing submenu item
          • deviceType: string which contains the type of device for which the submenu item is added
  • on_ui_extraSubmenuItemRemoved:
    • triggered when an extra submenu item is removed
    • parameter: idForRemovedExtraSubmenuItemObject
  • on_ui_cardAdded
    • triggered when card is added to user data
    • parameter: cardObject
  • on_ui_cardChanged
    • triggered when card is found changed in user data
    • parameter: changedCardObject
  • on_ui_cardRemoved
    • triggered when card is removed from user data
    • parameter: idForRemovedCardObject
  • on_ui_jobsUpdated
    • triggered when job is updated in lu_status
    • parameter: luStatusJobsObject
  • on_ui_deviceStatusChanged
    • triggered when device status is changed
    • parameter: deviceObjectFromLuStatus
  • on_ui_syncClock
    • triggered after lu_status is parsed
    • parameter: luStatusLocalTime
  • on_ui_initFinished
    • fired when init has finished (UI should be ready now)
  • on_ui_setUserAuthenticated
    • fired after login is successful
  • on_ui_saveFinished
    • fired after save is finished
  • on_ui_initNotLogged
    • triggered if user is not logged in
  • on_ui_alertsUpdated
    • fired after alert list was updated
  • on_ui_refreshDashboardCards
    • triggered when dashboard cards are refreshed
  • on_ui_engineAvailable
    • triggered if engine is not busy
  • on_ui_2GEnabled
    • triggered when parsing lu_status if 2G is enabled
  • on_ui_userDataSetTemperatureFormat
    • triggered after temperature format is set in user data
    • parameter: userDataObject
  • on_ui_userDataLoaded
    • triggered after user data parsing is completed
  • on_parseUserData
    • triggered when user data parsing is started
  • on_ui_accountUnitsLoaded
    • fired after account lis from MMS was successfully loaded
  • accountInformationLoaded
    • triggered after account information is loaded
    • parameter: accountInfoObject
  • on_ui_finishDrawingMenu
    • triggered after parsing of user data setup devices has finished
  • on_ui_deviceTypeChanged
    • triggered if device type for a device has changed
    • parameter: deviceObject
      • wrapper object for
        • device: this is the actual object representing the device
        • deviceTemplate: object with the static data associated to this device type
  • on_ui_hideModalLoading
    • triggered each time a time consuming job finishes (so that UI can hide modal loading)
  • on_ui_showUserDataSaveFailure
    • triggered if user data save has failed
  • on_ui_showErrorMessage
    • fired if application has error message to send to the UI
  • on_ui_cpanel_before_close
    • fired before closing the cpanel to allow plugins to cleanup their data
    • parameters: idForDeviceWhichOpenedTheCpanel


HomeCare Plugin - updated for UI7

We use the HomeCare plugin as example for what need to be added/updated for UI7. Below you can download plugin files:

File:HomeCare.zip

This is the published version of HomeCare plugin that can be downloaded from our appstore. This version is compatible with both UI5 and UI7.

Personal tools