English Asema.com Portlets Programmers' Manual
Asema.com Portlets : Programmers' Manual Asema Electronics Ltd Copyright 2011-2013 No part of this publication may be reproduced, published, stored in an electronic database, or transmitted, in any form or by any means, electronic, mechanical, recording, or otherwise, for any purpose, without the prior written permission from Asema Electronics Ltd. Asema E is a registered trademark of Asema Electronics Ltd.
Table of Contents 1. Introduction... 1 2. The anatomy of a portlet... 2 2.1. Private and public functions... 2 2.2. Getting references to markup items... 3 2.3. Buttons... 3 3. Function API... 4 3.1. Calling portlet functions... 4 3.2. Calling the Control Desktop API... 4 3.3. onload()... 4 3.4. Using YUI (version 3)... 5 4. Adding controls to a portlet... 6 4.1. Using the control library... 6 4.2. Adding your own controls... 6 4.2.1. Parsing data from callbacks... 6 4.2.2. Listening to notifications... 7 5. API methods... 8 6. Other examples... 10 Asema.com Portlets iii / 11
List of Examples 2.1. 2.2. 2.3. 3.1. 3.2. 3.3. 3.4. 3.5. Simple portlet markup... Defining a private and a public function... Referring to an element in a portlet... Calling portlet functions... Calling the API using a wrapper function... Directly calling an API function... Using the onload function to render an element inside an anchor... Accessing YUI... Asema.com Portlets 2 2 3 4 4 4 4 5 iv / 11
1. Introduction Asema Control Desktop (later in this document just simply "CD") is a Javascript-based portal interface that allows you to easily create small custom widgets ("portlets") that can offer the user of an Asema device a web based service portfolio for energy management and remote management of home. The underlying idea is that the end user can freely create a desktop of his or her choice that best suits the particular needs of that user. For service providers the portlets also offer an easy way to access the powerful energy management API and embed or link custom services they want to offer. As the name "portlet" implies, the software on the portal comprises small Javascript applications that can be freely placed on a common portal interface. When the user has access to a portlet, the portlet appears on the interface in a list from where it can be dragged to the main desktop interface for use. The portal interface itself takes care of managing and publishing these portlets and offers uniform ways to enable and disable portlets. The interface also transparently handles namespace management so that although everything runs in one single Javascript application, each portlet can be programmed independently and can use the same variable names. The same portlet can even be placed on the desktop multiple times. Introduction 1 / 11
2. The anatomy of a portlet Each portlet comprises markup Javascript code Portlets are created using the portlet editor of the CD. Here you can insert the code of the portlet into appropriate boxes and test the portlet by adding it to your personal portlets. The portlet editor will appear on asema.com Control Desktop when you activate the developer tools in your user information. User information can be edited either in the main setup or Web View of Asema E. Markup is standard HTML markup that defines the content of your portlet. Functions to add, drag, minimize and maximize the portlet are added automatically to the topbar of the portlet. Also note that the stylesheet of the desktop applies automatically so that all portlets have a common look and feel. Example 2.1. Simple portlet markup <h2>this is my first portlet</h2> Hello <b>world!</b> Code is the real beef of the portlet and defines how it behaves. You use standard Javascript to code a portlet and may access various features of Asema's system using the Control Desktop API. What's more, the portal is programmed with the Yahoo User Interface toolkit (YUI) and you can use functions from the YUI to e.g. add animation to your portlets. The following YUI modules are enabled on the portal node anim io dd json 2.1. Private and public functions Portlets can have internal and external functions. Private functions can only be called from within the functions of the portlet. Public functions can be attached to for instance a link in your markup. A private function is assigned to a variable whereas a public function has a standard function declaration. Example 2.2. Defining a private and a public function var private_function = function() { alert("you can call me only from within the portlet"); function public_function() { alert("assign me for instance to an onclick."); function private_function_public_wrapper() { private_function(); Note that your portlet code, if used, should always have at least one public function. The anatomy of a portlet 2 / 11
The anatomy of a portlet 2.2. Getting references to markup items In most cases you portlet will want to display something in the portlet. To do this, you need to create markup that defines an anchor for this content and then render the content to this markup. To find an element in your markup, you use the special function YUI.Jarvis.getPortletElementById("area_to_add"); Note that you cannot use a standard JavaScript getelementbyid. Replace these with the function above. Example 2.3. Referring to an element in a portlet <h1>add content</h1> <a href="#" onclick="add_element();"> Click here to add content</a> <div id="area_to_add"></div> function add_element() { var anchor = YUI.Jarvis.getPortletElementById( "area_to_add"); var content = YUI.Jarvis.create("<div>Some new text you did not see before.</div>"); anchor.appendchild(content); 2.3. Buttons The most common way to add user interaction is to create buttons. Buttons in the CD are always links (<a>). To create a link, remember to point the link to an empty section (#) and then add the function you'd like to use into the "onclick" attribute (see below). The anatomy of a portlet 3 / 11
3. Function API 3.1. Calling portlet functions To call a function in your own portlet code, assign a button to the onclick attribute. This will find the function in the namespace of your portlet and execute the code. Example 3.1. Calling portlet functions <a href="#" onclick="alertme();">click here!</a> function alertme() { alert("alert!"); 3.2. Calling the Control Desktop API To call the CD API you can either create a wrapper function in your portlet code and call the API function from there assign the function to an 'onclick' attribute and call the API directly The following examples have equal functionality Example 3.2. Calling the API using a wrapper function <a href="#" onclick="getversion();">click here!</a> function getversion() { alert(getapiversion()); Example 3.3. Directly calling an API function <a href="#" onclick="displayapiversion();">click here!</a> 3.3. onload() onload() is a special function that will be executed when your portlet loads. The loading happens as follows if the portlet has already been dragged onto the desktop -> when the desktop loads if the portlet has not been dragged -> when the dragging begins Example 3.4. Using the onload function to render an element inside an anchor <div id="graph"></div> function onload() { var anchor = YUI.Jarvis.getPortletElementById("graph"); drawconsumptiongraph(anchor, "Fridge", "2010-10-12 15:00:00", "2010-12-10 15:00:00", "daily"); Function API 4 / 11
Function API 3.4. Using YUI (version 3) If you want to use YUI in your portlet, first obtain a handle to the YUI instance with YUI.Jarvis.getYUI(); and then use its functions like you would in any YUI based application. You find more information on YUI at http://developer.yahoo.com/yui/3/ Example 3.5. Accessing YUI <h1>yui demo</h1> <a href="#" onclick="add_yui_element();"> Click here to add a YUI node below</a> <div id="area_to_add"></div> function add_yui_element() { var anchor = YUI.Jarvis.getPortletElementById( "area_to_add"); var Y = YUI.Jarvis.getYUI(); var content = Y.Node.create("<div><b>This is a node created using YUI!</b></div>"); anchor.appendchild(content); Function API 5 / 11
4. Adding controls to a portlet 4.1. Using the control library The portlet API offers you a set of ready made controls for adding power monitoring and remote control methods to a portlet. They hide the details of parsing and updating information under the hood, making it fast and easy to embed powerful controls. The API currently offers the following controls list of appliances, with buttons to control them list of actions, with buttons to activate them instant power monitor for central power and each appliance separately instant power monitor with just central power graph of electricity consumption (history of momentary power values) graph of electricity prices at NordPool market status display for home technical status display of controller system analog clock digital clock To add an element, you must create one empty HTML element to act as an anchor. This anchor is then passed to the corresponding API element, which renders its content inside th anchor. This way you can fully control where the control is placed and when. The rendering of the element (i.e. call to the API function) can be done at onload() function, making it render automatically or at some user action. 4.2. Adding your own controls In addition to readily available controls, you can author your own. This requires some more effort in understanding how the system actually works. There are two critical components here: asynchronous callbacks that give you the actual core data and notifications that inform you whenever something changes. 4.2.1. Parsing data from callbacks There are two key functions for getting data for controlling appliances and actions in the system. These are YUI.Jarvis.getActions(callback) and YUI.Jarvis.getAppliances(callback). These contact the Asema E device that controls the appliances and returns values to the callback function defined. The callback will receive the data asynchronously once ready. Data is naturally dependent on the call. In the case of appliances and actions it has a standard form where data is grouped as rooms or actiongroups on the first level, then as individual appliances or actions on the seconds level. The example below shows an example on how to parse the data for appliances. var appliance_callback = function(appliance_data) { for (room in appliance_data) { Adding controls to a portlet 6 / 11
Adding controls to a portlet for (var i=0; i < data[room].length; i++) { var appliance = data[room][i]; var gid = appliance.gid; var appliance_is_on = appliance.is_on; var name = appliance.name; var on_capability_gid = appliance.switch_on_gid; var off_capability_gid = appliance.switch_off_gid; // do something like draw a control YUI.getAppliances(appliance_callback); 4.2.2. Listening to notifications To make the user interface interact in real-time with events in the control system, interfaces use extensively various signals that are seen in the HTML/Javascript API's as notifications. Notifications are pushed to the interface with HTTP push, or Comet calls to be more exact. The Comet library is loaded automatically to the interface when it loads. What you need to do is listen to the notifications it sends. To do this, you register a callback function to the appropriate notification. No polling of data is required. The notification can additionally carry an object that contains your custom data. This custom data is passed to the callback function so that you can for instance update a particular user interface element when the event takes place. The following example shows an example on hooking a callback to the listener that notifies of changes in appliance state and then extracting data from it. var mycallback = function(callbackdata, newappliancestate) { var number = callbackdata['mynumber']; var string = callbackdata['mystring']; var newstate = newappliancestate; // do something with data here... mycustomdata = { 'mynumber' : 1, 'mystring' : 'some value' ; YUI.Jarvis.register_appliance_state_listener( appliance_gid, mycustomdata, mycallback); Adding controls to a portlet 7 / 11
5. API methods getapiversion() Return the version string of the API. displayapiversion() Display the API version (uses an alert box). getdevicestatusdata(callback) Fetches data on the status of the Asema E from the device itself and calls the callback with it. getappliancelist(callback) Gets a list of appliances currently in the system, returns value to given callback. getactionlist(callback) Gets a list of actions currently in the system, returns result to given callback. drawactionlist(anchor) Draws a list of actions (with buttons) to the element designated by anchor. drawinstantpowermonitor(anchor) Draws instant power monitor to the element designated by anchor. drawcentralpowermonitor(anchor) Draws central power monitor to the element designated by anchor. drawconsumptiongraph(anchor, title, _start_time, _end_time, type) Draws a flash or javascript chart (depending on browser capabilities) to the element designated by anchor. Type can be "column" or "line", title is added on top. The graph covers timespan from start time to end time. drawelspotpricegraph(anchor, title, area_code, currency, year, month, day) Draws a line graph of electricity prices in the NordPool Elspot market on a particular day. Current NordPool area code, desired currency, year, month and day must be defined. drawelspotpricegraphfortoday(anchor, title, area_code, currency) Shortcut of drawelspotpricegraph to draw the graph for today. drawanalogclock(anchor) Draws a flash analog clock to the element designated by anchor. drawdigitalclock(anchor) Draws Javascript digital clock to the element designated by anchor. drawhomestatusinfo(anchor) Draws an information box in status information for the home the Asema E is in. drawdevicetechnicaldata(anchor) API methods 8 / 11
API methods Draws a box of technical data (e.g. firmware version). usecapability(appliancegid, capabilitygid) Use a capability on an appliance. If you choose to create your own appliance control panel instead of using the predefined one that the portal draws, you need to use the capability framework. Each appliance has a set of capabilities it supports, not all appliances support all capabilities. A basic capability is switching the appliance on. Each capability is designated by a gid and type. Type tells you what that capability can do, the gid gives reference to that capability. So for example if the GID of the appliance is ABCD and it can be switched on with capability that has GID 1234 and off with capability that has GID 5678, then you feed these values to the API function. usecapability("abcd", "1234") would turn it on and usecapability("abcd", "5678") turns it off. When you load appliance data, the capabilities supported by the appliance can be found in the datastructure that you receive as a result. runaction(action_gid) Activates and action designated by action_gid. connecttoscreenlet(screenlet_uid, command, args, callback) Run a command in a screenlet. This is the main method for communicating between portlets and screenlets. The screenlet will receive the command with arguments as a signal you can then process. Once the command has passed, the callback will get a notification. To address a particular screenlet, you must know its unique ID (UID). Note that this ID is different from the GID. The UID is the id assigned to the screenlet by asema.com. The reason for using two different id's is that the GID uniquely identifies each instance of a screenlet. It is assigned by each Asema E separately when an installation is made. So the same screenlet in two different Asema E's will have different GID's. Using GIDs would mean that your portlet works only with a single screenlet installation of a particular device. The UID on the other hand is assigned by asema.com and is the same for all screenlets with one uploaded set of code on all devices. When you author a screenlet and submit it to asema.com for installation to a device, you will see after submission the ID number in the submission form. This is the screenlet_uid you should use to communicate. When you run connecttoscreenlet, asema.com will automatically find the correct Asema E device that desktop is logged in to. This is why you do not need to specify any identified for the Asema E. That is done automatically. Once the correct device is found, asema.com makes a connection to the device using whatever tunneling connection method is chosen and sends the command. Asema E will route the command to the correct screenlet by using the UID you provide. opendesktoppopup() Show an predefined Javascript popup window on top of the Desktop. The popup features close button and styles that fit the overall look and feel. You can use this for instance for error messages. closedesktoppopup() Close the predefined desktop popup. setdesktoppopupcontent(content) Set the content of the desktop popup. API methods 9 / 11
6. Other examples ** HTML markup: <ul> <li>entry 1</li> <li>entry 2</li> <li>entry 3</li> <li>entry 4</li> </ul> <select> <option value="1">one</option> <option value="2">two</option> </select> ** Consumption graph: <div id="graph"></div> function onload() { var anchor = YUI.Jarvis.getPortletElementById("graph"); drawconsumptiongraph(anchor, "My Graph", "2010-10-12 15:00:00", "2010-12-10 15:00:00", "daily"); ** Device <a href="#" connect <a href="#" test connections: func="connecttoscreenlet();"> Test with callback</a><br/> func="getdevicedata();">test json</a> function getdevicedata() { devicedata = YUI.Jarvis.getDeviceData(); alert(devicedata.name); var alertme = function(data) { alert(data.load); function connecttoscreenlet() { YUI.Jarvis.connectToScreenlet('mycommand', 'myarg', alertme); ** Appliance list with on-off buttons (requires device backend): <div id="list">list appears here</div> function onload() { drawappliancelist(yui.jarvis.getportletelementbyid ("list")); Other examples 10 / 11
Colophon Colophon 11 / 11