UI Notes

From MiOS
(Difference between revisions)
Jump to: navigation, search
(Building a control-only UI for Vera)
(lu_status)
 
(19 intermediate revisions by 6 users not shown)
Line 1: Line 1:
 +
[[Category:Development]]
 
Here is some general information about getting information to display in a user interface:
 
Here is some general information about getting information to display in a user interface:
  
Line 5: Line 6:
 
Vera uses UPnP for all the messaging, such as turning lights on and off.  So Vera translates Z-Wave, Insteon, infrared codes, etc., into UPnP actions. If you have already implemented a UPnP stack and can send properly formated UPnP SOAP/XML requests, you can control everything using standard UPnP action invocation. If you did not, Vera provides a simple HTTP GET interface as well, which is discussed below.
 
Vera uses UPnP for all the messaging, such as turning lights on and off.  So Vera translates Z-Wave, Insteon, infrared codes, etc., into UPnP actions. If you have already implemented a UPnP stack and can send properly formated UPnP SOAP/XML requests, you can control everything using standard UPnP action invocation. If you did not, Vera provides a simple HTTP GET interface as well, which is discussed below.
  
To test UPnP calls you can use the Intel Device Spy utility available [http://www.intel.com/cd/ids/developer/asmo-na/eng/downloads/upnp/tools/218896.htm?desturl=http://softwarecommunity.intel.com/isn/downloads/zips/IntelToolsForUPnPTechnology_v2.zip here].
+
In a nutshell UPnP works like this: You have UPnP devices, which are things that can be controlled and can report their state, like a light switch.  And you have UPnP Control Points, which are the things that let a user control UPnP devices, like a touch-screen web pad. The Control Point does this by a) reading the device and descriptions for the UPnP device to see what it can do, and b) invoking actions on the UPnP device (ie telling it to do something), and c) reading and setting variables for the device which describe the current state and/or configuration settings for the device.
  
== JSON vs. XML ==
+
A UPnP device is defined in an XML document called a device description document. To see one, in Vera's setup UI, go to Devices, Luup plugins, Luup Files, and click 'view' file next to D_BinaryLight1.xml.  Use Firefox since it has a built-in XML viewer.  Notice the tag: <deviceType>urn:schemas-upnp-org:device:BinaryLight:1</deviceType>.  This defines the type of device, namely an on/off light switch, which is what you use to know how to represent this device to a user.  A device optionally implements one or more services.  In this case the services: urn:upnp-org:serviceId:SwitchPower1, urn:micasaverde-com:serviceId:EnergyMetering1 and urn:micasaverde-com:serviceId:HaDevice1.
  
The native UPnP protocol uses XML/SOAP.  But there are also several times you will request data from Vera that has nothing to do with the UPnP spec.  These will be done with data_request's as explained below, such as user_data, lu_status, etcInternally Vera uses JSON as the native format, but Vera can convert to XML (details follow)In general when you want to view data in a human readable format, such as the device list, it's easiest to use the Firefox browser, and request Vera convert the data to XML.  Firefox has a nice browser to display XML in human readable format.  If you want to make the JSON data nicely formatted, you can use the web site jsonlint.comIn a UI application which will request data regularly from Vera we recommend retrieving everything in JSON format, not XML, because Vera's CPU is not that powerful and so continuous requests of data in XML format will cause a lot of CPU time to be devoted to converting JSON into XML.
+
A service is a collection of actions which a device implement and which you can invoke from a UPnP Control Point, as well as a collection of variables which always have a current valueThe variables describe the current state of the device and/or configuration settingsView the file S_SwitchPower1.xml to see a service.  For example, the device urn:schemas-upnp-org:device:BinaryLight:1 implements the service urn:upnp-org:serviceId:SwitchPower1, which has the action SetTarget, which is how you turn the light on and offThe action takes a single argument newTargetValue which can be 0 to turn the light off and 1 to turn it on.  The service also has the variable Status which is 0 or 1 depending on whether the light is currently on or off.
  
== Finding Vera on the local network  ==
+
If you open the device description for a dimmable light D_DimmableLight1.xml you'll see that it implements the same service S_SwitchPower1.xml, since you can still turn it on and off, and it also implements the service urn:upnp-org:serviceId:Dimming1, which has an action to set the dim level (SetLoadLevelTarget).
  
You can find Vera by using the traditional UPnP discovery process, or you can retrieve this URL:<br>'''http://findvera.com/locator.php'''
+
To test UPnP calls you can use the Intel Device Spy utility available [http://www.intel.com/cd/ids/developer/asmo-na/eng/downloads/upnp/tools/218896.htm?desturl=http://softwarecommunity.intel.com/isn/downloads/zips/IntelToolsForUPnPTechnology_v2.zip here].  It should pick up Vera, show you all the devices, like light switches, thermostats, etc., let you expand the services and see the actions and variables.  Click an action, like SetTarget, to specify the arguments and click 'Invoke' to run the action, such as turning on and off the light.
  
Each Vera, when it boots up, reports its internal IP address to the central findvera.com server, which tracks this along with the external IP address. '''locator.php''' shows all serial numbers and internal network IP addresses on the same external IP. For example, if '''http://findvera.com/locator.php''' returns the following:
+
== JSON vs. XML ==
  
<br>
+
The native UPnP protocol uses XML/SOAP.  But there are also several times you will request data from Vera that has nothing to do with the UPnP spec.  These will be done with data_request's as explained below, such as user_data, lu_status, etc.  Internally Vera uses JSON as the native format, but Vera can convert to XML (details follow).  In general when you want to view data in a human readable format, such as the device list, it's easiest to use the Firefox browser, and request Vera convert the data to XML.  Firefox has a nice browser to display XML in human readable format.  If you want to make the JSON data nicely formatted, you can use the web site jsonlint.com.  In a UI application which will request data regularly from Vera we recommend retrieving everything in JSON format, not XML, because Vera's CPU is not that powerful and so continuous requests of data in XML format will cause a lot of CPU time to be devoted to converting JSON into XML.
  
7300 192.168.1.114
+
== Finding Vera on the local network ==
6907 192.168.1.102
+
7618 192.168.1.117
+
 
+
Then there are 3 Vera's on the same internal network (i.e. sharing the same external IP as your browser), with serial numbers 7300, 6907 and 7618, with the 3 IP internal (LAN)&nbsp;addresses shown.
+
  
You can also pass a FindVera username to '''locator.php''' and it will return the serial number and IP associated with it, such as:
+
You can find Vera by using the traditional UPnP discovery process, or you can retrieve this URL:<br>'''https://sta1.mios.com/locator_json.php?username=xxx''' where the username=xxx is optional, but, if specified, it will report all systems that mios.com user xxx can report whether local or remote, and without the username=xxx it only shows the Vera's on the user's local home network.
  
http://findvera.com/locator.php?username=demovera
+
Each Vera, when it boots up, reports its internal IP address to the central mios.com server, which tracks this along with the external IP address. '''locator.php''' shows all serial numbers and internal network IP addresses on the same external IP. For example, if '''https://sta1.mios.com/locator_json.php?username=xxx'''.
  
 
== The HTTP interface  ==
 
== The HTTP interface  ==
  
Vera listens on port 49451. Vera responds to UPnP actions the normal way, or by making simple HTTP requests. For example, to turn on a light you can either send the UPnP action "SetTarget" to the device using the normal UPnP mechanism, or you can simply put this URL in your web browser, or with wget, or similar:  
+
Vera listens on port 3480. Vera responds to UPnP actions the normal way, or by making simple HTTP requests. For example, to turn on a light you can either send the UPnP action "SetTarget" to the device using the normal UPnP mechanism, or you can simply put this URL in your web browser, or with wget, or similar:  
  
http://[ipadress]:49451/data_request?id=lu_action&amp;output_format=xml&amp;DeviceNum=10&amp;serviceId=urn:upnp-org:serviceId:SwitchPower1&amp;action=SetTarget&amp;newTargetValue=1  
+
http://[ipadress]:3480/data_request?id=lu_action&amp;output_format=xml&amp;DeviceNum=10&amp;serviceId=urn:upnp-org:serviceId:SwitchPower1&amp;action=SetTarget&amp;newTargetValue=1  
  
 
That URL will return the same results of the action as using the normal UPnP architecture. The '''output_format=xml''' on the URL means the data returned should be in XML format. You can instead use '''output_format=json'''
 
That URL will return the same results of the action as using the normal UPnP architecture. The '''output_format=xml''' on the URL means the data returned should be in XML format. You can instead use '''output_format=json'''
Line 45: Line 42:
 
or use the built-in request:  
 
or use the built-in request:  
  
'''http://ipaddress:49451/data_request?id=user_data&amp;output_format=json''' (or xml)  
+
'''http://ipaddress:3480/data_request?id=user_data2&amp;output_format=json''' (or xml)  
  
 
This returns the system configuration file for Vera. It's assumed you understand the way Vera categorizes devices with Rooms, Devices, Scenes, etc. When creating a user interface for controlling Vera only, like on a mobile phone, most of the tags can be ignored, since usually you just need the list of rooms and devices.
 
This returns the system configuration file for Vera. It's assumed you understand the way Vera categorizes devices with Rooms, Devices, Scenes, etc. When creating a user interface for controlling Vera only, like on a mobile phone, most of the tags can be ignored, since usually you just need the list of rooms and devices.
  
== Accessing Vera remotely through the findvera server ==
+
== Accessing Vera remotely through the mios server ==
  
Native UPnP only works on a local area home network, and cannot be used over the Internet.  The FindVera server provides a secure way to remotely access and control your Vera system using the HTTP interface without having to make any substantial changes to the UI.  Everything you can do locally with Vera on port 49451, you can do remotely with findvera using the exact same syntax.  You only need to ask the user for his username and password and pass them on the URL to the remote access server.  For example, the above user_data is the syntax for local access on a home network.  To retrieve the same URL over the internet with findvera use:
+
Native UPnP only works on a local area home network, and cannot be used over the Internet.  The mios server provides a secure way to remotely access and control your Vera system using the HTTP interface without having to make any substantial changes to the UI.  Everything you can do locally with Vera on port 3480, you can do remotely with mios using the exact same syntax.  You only need to ask the user for his username and password and pass them on the URL to the remote access server, along with the serial number of the unit (ie like 12345).  For example, the above user_data is the syntax for local access on a home network.  To retrieve the same URL over the internet with mios use:
  
https://ra1.findvera.com/demovera/myvera123/49451/data_request?id=lu_status&output_format=json
+
https://fwd2.mios.com/demovera/myvera123/12345/data_request?id=lu_status&output_format=json (or use fwd1.mios.com)
  
assuming demovera is the username and myvera123 is the password that the user chose on the 'findvera' tab in his Vera setup page.  Note that since the request is https, the username and password are encrypted because https encrypts the URL's as well as the contents of the page.
+
assuming demovera is the username and myvera123 is the password that the user chose setting up his mios.com account.  Note that since the request is https, the username and password are encrypted because https encrypts the URL's as well as the contents of the page.
  
 
== Building a control-only UI for Vera  ==
 
== Building a control-only UI for Vera  ==
Line 61: Line 58:
 
If you just want to control Vera, and not modify the configuration, such as with a cell phone interface or web pad, the flow might possibly work like this:  
 
If you just want to control Vera, and not modify the configuration, such as with a cell phone interface or web pad, the flow might possibly work like this:  
  
1. For the initial setup, you need to ask whether the user wants to (a)&nbsp;access Vera remotely with the FindVera service, and if so, get the user's username/password; or (b) access Vera directly on the home network. You can use locator.php to show the Vera on the home network. You might want to do an auto-detect. For example, you could use locator.php to see if Vera exists locally, and if not, prompt the user for a FindVera username and password. You can use locator.php and pass the username to get the serial number and internal IP, and then automatically switch to direct access if locator.php (without the username) indicates that serial number is found on the local network. This would allow the user to automatically switch between local access with Wi-Fi (which is much faster of course) and remote access with FindVera and the mobile phone network.  
+
'''1)''' For the initial setup, you need to ask whether the user wants to (a)&nbsp;access Vera remotely with the mios service, and if so, get the user's username/password; or (b) access Vera directly on the home network. You can use locator.php to show the Vera on the home network. You might want to do an auto-detect. For example, you could use locator.php to see if Vera exists locally, and if not, prompt the user for a mios username and password. You can use locator.php and pass the username to get the serial number and internal IP, and then automatically switch to direct access if locator.php (without the username) indicates that serial number is found on the local network. This would allow the user to automatically switch between local access with Wi-Fi (which is much faster of course) and remote access with mios and the mobile phone network.  Or just ask for his mios username and show him all the Vera's he can control, either local or remote.
  
2. Once the connection is established, retrieve the '''user_data''' to get the list of rooms, scenes, devices, and remotes. You can cache this data locally so you don't need to retrieve it and continually parse it. If you do, store the contents of the 'DataVersion' tag and pass it on the URL as &amp;DataVersion=x. You will receive a page with the text NO_CHANGES if the user_data has not changed. You should still check periodically so that if the data changes you can refresh your copy. For rooms and scenes, you only need the room/scene ID, which is the number after Room_Num_/scene_ in the tag, and the description. For devices, you need the device number, the description and the category.  
+
'''2)''' Once the connection is established, retrieve the list of rooms, scenes, and devices from Vera (see '''user_data''' below). You can cache this data locally so you don't need to retrieve it and parse it over and over.
  
3. Present the user with the rooms, scenes, devices and remotes. Generally we show first the rooms and then let the user pick a device, scene or remote in the room.  
+
'''3)''' Present the user with the rooms, scenes, devices. In Vera's UI's we show first the rooms and then let the user pick a device or scene in the room.  However this data could be presented graphically, such as on a floorplan.  Your UI can have Vera store extra tags and data in the configuration database (ie user_data) to store things like coordinates for icons, outlines or rooms and so on.
  
4. If the user picks a scene you can run the scene with the following URL, passing the scene number as '''x''', and it will return an OK if it went okay:  
+
'''4)''' If the user picks a scene you can run the scene with the following URL, passing the scene number as '''x''', and it will return an OK if it went okay:  
  
http://127.0.0.1:49451/data_request?id=lu_action&amp;serviceId=urn:micasaverde-com:serviceId:HomeAutomationGateway1&amp;action=RunScene&amp;SceneNum=x  
+
http://127.0.0.1:3480/data_request?id=lu_action&amp;serviceId=urn:micasaverde-com:serviceId:HomeAutomationGateway1&amp;action=RunScene&amp;SceneNum=x  
  
5. If the user picks a device, you use the category to determine what type of controls to present the user. (See [[Luup UPNP Files]] for a list of the categories.) When the user chooses an action, you can send it like this:  
+
'''5)''' If the user picks a device, you use the category which is contained in the user_data to determine what type of controls to present the user. (See [[Luup UPNP Files]] for a list of the categories.) When the user chooses an action, you can send it like this:  
  
http://ipadress:49451/data_request?id=lu_action&amp;output_format=xml&amp;DeviceNum=10&amp;serviceId=urn:upnp-org:serviceId:SwitchPower1&amp;action=SetTarget&amp;newTargetValue=1  
+
http://ipadress:3480/data_request?id=lu_action&amp;output_format=xml&amp;DeviceNum=10&amp;serviceId=urn:upnp-org:serviceId:SwitchPower1&amp;action=SetTarget&amp;newTargetValue=1  
  
 
For a list of common actions and device types see: [[Luup CP Mandatory Types]]  
 
For a list of common actions and device types see: [[Luup CP Mandatory Types]]  
  
Some actions return immediately with an 'OK'. Other jobs may take time to complete. For these you will get a job ID back. There are several ways to present this to the user. One possibility is to do what Vera does in the UI, namely to use '''lu_status '''(explained next) to find all active jobs and to put a 'job' icon next to each device to indicate the progress of the job. In this way the user isn't tracking a particular job ''per se'', but just has visual feedback that a device is busy, and if the job icon(s) turn green, that everything went through okay. You could instead track the action individually using the job number that is returned.  
+
Some actions return immediately with an 'OK'. Other jobs may take time to complete and are processed asynchronously. For these asynchronous jobs you will get a job ID back. There are several ways to present this to the user. One possibility is to do what Vera does in the UI, namely to use '''lu_status '''(explained next) to find all active jobs and to put a 'job' icon next to each device to indicate the progress of the job. In this way the user isn't tracking a particular job ''per se'', but just has visual feedback that a device is busy, and if the job icon(s) turn green, that everything went through okay. You could instead track the action individually using the job number that is returned, or use some other method, like making the icon for the device appear animated while it's busy, and turn green or red if the last command succeeded or failed.
  
6. Periodically poll the system with '''lu_status''', like this:  
+
'''6)''' Periodically poll the system with '''lu_status''' (explained below), like this:  
  
http://ipaddress:49451/data_request?id=lu_status&amp;output_format=json  
+
http://ipaddress:3480/data_request?id=lu_status&amp;output_format=json  
  
 
That returns the current values of the UPnP variables, which you can use to show the user current status. For example, if the variable Status is 1 for a switch, you can show the 'on' button in a selected state, while 0 shows it in an 'off' state. '''lu_status''' also shows any active jobs for a device.
 
That returns the current values of the UPnP variables, which you can use to show the user current status. For example, if the variable Status is 1 for a switch, you can show the 'on' button in a selected state, while 0 shows it in an 'off' state. '''lu_status''' also shows any active jobs for a device.
  
== Building a replacement UI for Vera  ==
+
==user_data==
  
  Here are some notes on other tags that might be of interest, particularly
+
The user_data is the main configuration file that Vera uses to store all the rooms, devices, scenes, timers, events, users, and any other data about the system. You should request the user_data to get whatever data you need to present to the user, at a minimum, for example, you'll need the list of devices, their descriptions, and the categories (light switch, thermostat, etc.).  You'll also want the list of scenes to present the user. To fetch the current user_data from Vera use the user_data request, like this:
  when creating a full replacement for Vera's built-in web user interface.
+
  
The unassigned devices and automation devices in the '''user_data''' JSON request are just counters. You can probably ignore them. Automation devices is just the count of all the devices that are children of 'zwave' (i.e. the count of your light switches, thermostats, etc.). Unassigned devices is the count of devices that haven't yet been assigned a room (i.e. FK_Room=0). It's your responsibility, in the UI, to be sure that every device which does *NOT* have the tag "Hidden"=1 or the variable '''urn:micasaverde-com:serviceId:HaDevice1/IgnoreRoom''' set to 1. You don't have to, actually; the devices work fine if they're not in a room. It's just a convention in our user paradigm that all devices have to be put in rooms as a way of cataloging. And our web developer said that since JavaScript is slow, rather than him parsing the whole device tree in order to figure out if there are any devices not yet assigned to a room, he asked us to put a counter in the JSON (UnassignedDevices). If it's 0, he doesn't need to display the popup "Tell me what rooms these new devices are in". If it's &gt;0, then he goes ahead and parses the device tree to figure out what devices are already assigned to rooms and displays the popup for those that are not yet in a room.
+
Returns JSON (preferred native format):
  
He also wanted an 'automation devices' counter, again, so he doesn't need to parse the JSON tree unnecessarily. If the counter is 0, then the user has no Z-Wave devices and he doesn't bother rendering the devices tab.
+
http://[ip address]:3480/data_request?id=user_data
  
The counters and data in the '''user_data''' are the 'master database' of all the devices in the home and their parameters. The database is updated whenever the list of devices changes, or the user makes changes to the configuration.
+
Returns XML:
  
The way our UI works is there's a background thread that polls '''user_data''' every 60 seconds or so. Each time it polls '''user_data''', it passes in the DataVersion from the last '''user_data''' it got. This way if there are no changes, rather than returning an identical JSON tree for you to parse all over again, you just get back an empty tree meaning "that DataVersion is still current". When the '''user_data''' changes, the UI needs to update all the devices/trees/etc. because that means something has changed.
+
http://[ip address]:3480/data_request?id=user_data&output_format=xml
  
Separately, there's another background poll of '''lu_status''' (explained later) to get the realtime info on the devices. This is used to determine which action button to highlight (on/off/etc.), what color code to use for the config cog wheel, what job icons to display, and so on. The way we implemented it is that when the user does something in the UI, we start polling '''zwave_status''' every 2 seconds. This is because things are changing quickly (i.e. the job may be succeeding/failing/etc.). Then after 15 seconds, the polling is reduced to once every 15 seconds. Then after 1 minute, the polling is reduced to 1 minute intervals. This way, when the UI is idle, and the user turns off a light, you won't see the change immediately in the UI because it can be 1 minute before the next '''zwave_status '''poll. But, you're not generating constant network traffic to keep polling the devices over and over again when there's nothing going on.
+
You can also add a 'DataVersion=TimeStamp' parameter to the URL. It the data has changed since the TimeStamp, all the data is returned. If the data has not changed since the TimeStamp, Vera will return a page with the text 'NO_CHANGES':
  
If you use the binary socket layer, you don't need to poll since you can register to receive events when things change. But for web based UI's and engines like JavaScript, implementing raw socket transfers isn't as easy as simple HTTP GETs, so it just uses polling of the HTTP GETs.
+
http://[ip address]:3480/data_request?id=user_data&DataVersion=315587159
  
== Saving configuration settings ==
+
The user_data contains the state for all the devices.  For example this indicates that the device id #17, called "Switch" is turned off (ie service SwitchPower1, variable Status is 0)
  
This doesn't apply when creating a UI for control only, like a cell phone.
 
 
All the configuration data is stored in the user_data json file.  The UI should allow the user to modify this data, set configuration parameters, and so on.  Refer to the user_data request on [[Data_Provider_Catalog_Plugin_Requests]] for instructions on how to submit the user's changes to the json files.  You can add your own tags to the JSON file to store your own information about devices.  Vera will simply ignore json tags that it doesn't recognize.
 
 
== Current state of devices ==
 
 
The state variables in user_data are not necessarily up to date.  They are just what was last saved in the database.  To get the up to date values, along with a list of the active jobs for a device, use the UPnP action GetStatus, or call: http://ipaddress:49451/data_request?id=lu_status&output_format=xml
 
 
The job status will be one of the following:
 
 
job_None=-1,  // no icon
 
job_WaitingToStart=0,  // gray icon
 
job_InProgress=1,  // blue icon
 
job_Error=2,  // red icon
 
job_Aborted=3,  // red icon
 
job_Done=4,  // green icon
 
job_WaitingForCallback=5  // blue icon - Special case used in certain derived classes
 
 
== Configuration parameters for devices ==
 
 
--- this section is not current ---
 
 
Here are configuration settings the UI should prompt the user for and store in the "DeviceData" section. 
 
 
'''Global'''
 
 
'''DEVICEDATA_Manage_Associations_CONST 300:'''  Some Z-Wave devices report information about their state (ie fire events), such as motion sensors, remote controls which fire 'button pressed' events, and so on.  Generally you tell the device where to send the events by assigning them 'associations'.  For example, a motion sensor can be associated with a light switch and it will turn the light on/off automatically, or it can be associated with Vera so Vera gets 'sensor tripped' events.  If this is the sort of device that Vera would normally want to set associations for, Vera adds this configuration parameter to the device, with an empty value.  If the UI sees this parameter in "DeviceData", display a check box that says something like "Allow Vera to manage associations" and, if checked, store a 1, otherwise a 0.
 
 
'''DEVICEDATA_Scenes_As_Events_CONST 298:''' Normally ZWave handheld remote controls work with light switches only, and you can't receive events in Vera to allow them to execute Vera's scenes, which can do anything.  If this is a handheld remote control that Vera can "trick" into sending scene commands to Vera, which Vera can in turn translate into events, Vera will add this configuration parameter to the device, with an empty value.  If the UI sees this parameter in "DeviceData", display a check box that says something like "Treat Scenes as events" and, if checked, store a 1, otherwise a 0.  See: [[ZWave_Add_Controller]] method #2
 
 
'''DEVICEDATA_Wakeup_Interval_CONST 299:''' If this is a battery operated device, that is not a FLiRS (see Zensys definition), it is normally 'sleeping' and cannot be communicated with except when it periodically wakes up and broadcasts a wakeup message.  If Vera detects this type of device, Vera will add this configuration parameter to the device, with an empty value.  If the UI sees this parameter in "DeviceData", prompt the user for the wakeup interval and store the value, as # of seconds, in this parameter.
 
 
'''DEVICEDATA_Manufacturer_Desc_CONST 294/DEVICEDATA_Model_Desc_CONST 295:''' This is a read-only setting with the name of the manufacturer/name of the model of the device, if known.  Do not overwrite these values.
 
 
'''DEVICEDATA_Battery_Level_CONST 292:''' This is a read-only setting with the percentage of battery life left, from 0-100.
 
 
'''DEVICEDATA_Battery_Alarm_CONST 293:''' If DEVICEDATA_Battery_Level_CONST 292 is specified, you can display an input box asking the user for the minimum battery life before firing an event (0-99) and store it in this setting.  When the battery level drops below this level an event will be fire, which can be attached to a scene to notify a user.
 
 
'''DEVICEDATA_Capabilities_CONST 207:''' This may be of interest to more advanced users.  It has the device classes followed by a | and the supported command classes.  An S at the end means its a 'secure' command class.
 
 
'''DEVICEDATA_PortChannel_Number_CONST 12:''' This is read-only, and it's the ZWave Node id.
 
 
'''DEVICEDATA_Multi_Channel_End_Point_CONST 296/DEVICEDATA_Multi_Channel_Capabilities_CONST 297/#define DEVICEDATA_Model_CONST 233/DEVICEDATA_Configuration_CONST 59/DEVICEDATA_Update_Name_CONST 41/DEVICEDATA_Only_One_Per_PC_CONST 162/DEVICEDATA_Energy_Log_CONST 286:''' Internal use only.  Do not modify or present to the user.
 
 
'''DEVICEDATA_LastUpdate_CONST 234:''' This is the unix time stamp indicating when the device was successfully configured.  Vera sets this when configuration is done.  If this is not empty or 0, Vera will not attempt to configure the device.  Whenever the user makes any change to a device, such as changing the settings in the UI, the UI must reset this to 0 when saving so Vera will re-configurate the device.
 
 
'''DEVICEDATA_Polling_Settings_CONST 283:''' This is the maximum frequency, in seconds, to poll the device.  If set to empty, the default values will be used.  0 means the device will not be pulled.  60, for example, means poll the device at most once per 60 seconds.
 
 
'''DEVICEDATA_PK_FloorplanObjectType_CONST 11:''' Vera has no use for this value, but it is traditionally used to indicate which type of icon the user wants to see this device represented with on the floorplan.  It is made available to any controllers.
 
 
'''DEVICEDATA_InputOrOutput_CONST 18/DEVICEDATA_Default_State_CONST 19/DEVICEDATA_EK_AlertType_CONST 45:'''  These are for sensors indicating if they are input/output, normally open/close, and what type of alert they fire.  You should not need to modify these because the default values pulled from template_data.json, which are set when the device is created, should be correct.
 
 
'''DEVICEDATA_Wattage_CONST 285:'''  This is how many watts the device uses at full power.  The user should be allowed to edit this so the estimated energy usage is accurate.
 
 
'''Device specific notes:'''
 
 
'''Light switches/lamp & appliance modules/Sensors:''' There are no special settings.  Just follow the general settings above.
 
 
'''Thermostats:''' Note the syntax of Wattage here: [[Watts]]  Otherwise no special settings.
 
 
'''IP Cameras:''' There are special json tags for the IP address and MAC address.  Store the username/password for http authentication in: DEVICEDATA_AuthUser_CONST 114/DEVICEDATA_AuthPassword_CONST 115 and the URL to retrieve a JPEG image in DEVICEDATA_Path_CONST 2.  Store information about archiving images and association with lights/motion sensors in DEVICEDATA_sPK_Device_Relations_For_Creat_CONST 184,DEVICEDATA_Video_settings_CONST 89.
 
 
DEVICEDATA_sPK_Device_Relations_For_Creat_CONST 184 = comma separated list of associated lights, dash, comma separated list of associated sensors.
 
 
DEVICEDATA_Video_settings_CONST 89 = comma separated values: # of seconds to archive, # of minutes/seconds to take automatic picture as a # followed by m or s, # of days to keep archives, [1|0] for 'turn on lights when viewing camera', [1|0] for 'turn on lights when the sensors are tripped and armed', [1|0] for 'turn on lights when the sensors are tripped and not armed', [1|0] for 'turn on lights for automatic picture'.  So, the following is data is stored for the following configuration:
 
 
"FK_DeviceData_184": "13,14,17-20"<br>
 
"FK_DeviceData_89": "98,97m,96,1,1,0,0"
 
 
Archive a photo whenever the following sensors are tripped:<br>
 
(20) <br>
 
And after the sensor(s) are tripped archive the video for 98 seconds.<br>
 
Which lights should be turned on when viewing this camera:<br>
 
(13,14,17)<br>
 
For archival purposes, take a picture from the camera every  97 minutes, and keep the pictures 96 days.<br>
 
Turn on the lights:<br>
 
[x] When I view the camera from the web or phone.<br>
 
[x] When the sensor(s) above are tripped and they are armed<br>
 
[ ] When the sensors above are tripped and they are *not* armed<br>
 
[ ] When you take an automatic picture for the archive<br>
 
 
== Configuration parameters for the Z-Wave device ==
 
 
-- this section is not current --
 
 
The Z-Wave device, the parent of all Z-Wave nodes, has configuration parameters as well:
 
 
'''DEVICEDATA_COM_Port_on_PC_CONST 37:'''  The com port/linux device for the Z-Wave dongle.
 
 
'''DEVICEDATA_Polling_Settings_CONST 283:''' The default poll settings, comma separated: [0|1] polling enabled, seconds to wait after startup before polling, seconds of idle time on the network before doing a poll, how many seconds to wait between polling nodes, seconds to wait between polling each node.<br>
 
So, "FK_DeviceData_283": "1,20,10,10,60" is displayed as:<br>
 
[x] Poll nodes<br>
 
Wait 20 seconds to start polling.<br>
 
Only poll a node if the Z-Wave network is idle at least 10 seconds.<br>
 
Poll a node every 10 seconds.<br>
 
Unless specified otherwise, poll each node at most once every 60 seconds.<br>
 
 
'''DEVICEDATA_Configuration_CONST 59:''' Firmware version of the dongle.  Read only
 
 
'''DEVICEDATA_PortChannel_Number_CONST 12:''' House code and node id of the dongle.  Read only.
 
 
'''DEVICEDATA_Capabilities_CONST 207:''' Read only status if the device is SUC/SIS and primary or not, such as: "Suc SIS:YES PRI:YES"
 
 
== Creating scenes in the user_data.json ==
 
 
--this section is not current--
 
 
A scene is just a list of commands to send to various devices.  The Scenes section of user_data contains the pre-defined scenes.  For example:
 
 
{
 
{
     "scenes": {
+
     "devices": [
         "scene_10": {
+
         {
             "Description": "leave home",
+
             "id": 17,
             "FK_Room": "5",
+
             "category": 3,
             "commands_ids": [
+
             "room": 1,
                1,
+
             "name": "Switch",
                2,
+
            "ip": "",
                3,
+
            "mac": "",
                4,
+
                 {
                5
+
                     "service": "urn:upnp-org:serviceId:SwitchPower1",
            ],
+
                     "variable": "Status",
             "commands": {
+
                     "value": "0"  
                "command_1": {
+
                 }
                    "Device_To": 5,
+
         }
                    "FK_Command": "972",
+
    ]
                    "params": {
+
                        "FK_CommandParameter_2": 24,
+
                        "FK_CommandParameter_5": "ARMED"
+
                    }
+
                 },
+
                "command_2": {
+
                     "Device_To": 14,
+
                    "FK_Command": "184",
+
                    "params": {
+
                        "FK_CommandParameter_76": 75
+
                    }
+
                },
+
                "command_3": {
+
                    "Device_To": 14,
+
                     "FK_Command": "193",
+
                     "Delay": 60
+
                },
+
                "command_4": {
+
                    "Device_To": 21,
+
                    "FK_Command": "280",
+
                    "params": {
+
                        "FK_CommandParameter_8": "C"
+
                    }
+
                 },
+
                "command_5": {
+
                    "Device_To": 21,
+
                    "FK_Command": "278",
+
                    "params": {
+
                        "FK_CommandParameter_5": 20
+
                    }
+
                }
+
            }  
+
         }  
+
    }
+
 
}
 
}
  
This defines a scene called "leave home" which is in room.  It sets a thermostat (device #21) to 'cool' mode (command #280) and to 20 degrees celsius (command #278).  It also arms a motion detector (command #972).  As explained below, ZWave motion detectors themselves don't have an arm/disarm command.  It's just a flag which the security plugin keeps so that when a sensor is tripped, it knows if it's an "armed sensor tripped event" or a normal "sensor tripped event".  So the command goes to device #5 (the security plugin), and the device id of the motion sensor (24) is a parameter to it.  It also sets device #14 (a light) to 75% (command #184) and after 60 seconds turns it off (command #193).  The list of device #'s is found in user_data Devices section.  The command and parameters and how to use them are explained below.
+
{{Warning|On UI7 build lu_sdata and lu_status have been deprecated, and you should use "status" instead.}}
  
To add this scene, you would submit the following JSON in the POST data for the user_data request. Note that if you do a POST with an existing scene ID, the entire scene is replaced.  Changes are not merged.  For example, if you want to add a timer to an existing scene, send the entire scene again, with command, and include the timer.  We did this because it was difficult in the java script UI to keep track of all the changes and was easier to have the UI just re-send the whole scene each time. See: [[Data_Provider_Catalog_Plugin_Requests]]
+
==lu_status==
 +
The UPnP variables describe the state of the devices according to the UPnP specs. When the variables change that information needs to be shown to the user, eg change a Switch icon from off to on. If you are interfacing with Vera using the UPnP stack, you can subscribe to the device's events to receive notifications automatically when a device's state changes. However if you're using the web interface you will need to poll using status request.
  
{
+
Call lu_status request like so:
    "scenes": {
+
        "scene_1000010": {
+
            "Description": "leave home",
+
            "FK_Room": "5",
+
            "commands_ids": [
+
                1,
+
                2,
+
                3,
+
                4,
+
                5
+
            ],
+
            "commands": {
+
                "command_1": {
+
                    "Device_To": 5,
+
                    "FK_Command": "972",
+
                    "params": {
+
                        "FK_CommandParameter_2": 24,
+
                        "FK_CommandParameter_5": "ARMED"
+
                    }
+
                },
+
                "command_2": {
+
                    "Device_To": 14,
+
                    "FK_Command": "184",
+
                    "params": {
+
                        "FK_CommandParameter_76": 75
+
                    }
+
                },
+
                "command_3": {
+
                    "Device_To": 14,
+
                    "FK_Command": "193",
+
                    "Delay": 60
+
                },
+
                "command_4": {
+
                    "Device_To": 21,
+
                    "FK_Command": "280",
+
                    "params": {
+
                        "FK_CommandParameter_8": "C"
+
                    }
+
                },
+
                "command_5": {
+
                    "Device_To": 21,
+
                    "FK_Command": "278",
+
                    "params": {
+
                        "FK_CommandParameter_5": 80
+
                    }
+
                }
+
            },
+
            "json_action": "add"
+
        }
+
    }
+
}
+
  
 +
:http://[ip address]:3480/data_request?id=status
  
Note the tag "json_action": "add" within the scene.  This tells the data provider handler to add this scene.  Also note that the scene id number is 1000010.  The convention is that when adding new devices, scenes, rooms, sections or users you should use an id number > 1,000,000.  When the data provider handler sees an id number >1m, it automatically changes it to be the next available id #.  This is because all devices, scenes, rooms, sections and users need a unique id #.  Since there could be multiple web ui's submitting user changes at once, you don't want the web ui to assign the id # as there may be a collision.  If there were, the plugin would merge the data from the 2 post's.  By using an id# > 1m, you are ensured there will be no conflicts as the id # will be changed when it's processed.  Note that the same user_data you POST to with the new data, will also return the resulting user_data after the POST.  So after POST'ing the data, you should parse and use the user_data that is returned, and discard any copy of the user_data you posted, as the id #'s may be different.
+
:http://[ip address]:3480/data_request?id=status&output_format=xml
  
POST'ing the commands_ids is purely optional.  The Vera back-end doesn't ever use any of the _ids parameters in the json file.  They are there purely for the convenience of the web engine if it makes it easier to parse the json files.
+
:http://[ip address]:3480/data_request?id=status&DataVersion=315587159
  
== List of commands and parameters to send to devices  ==
 
  
The complete list of all commands and parameters is in the '''template_data''' JSON file explained [[Data Provider Catalog Plugin|here]]. There are over 1,000 commands in the full LinuxMCE command set. But the common ones used in Vera are:
+
The returned document contains four sets of information, which constantly change to reflect the current status:
 +
* root attributes including DataVersion, which is the status timestamp, plus other attributes such as LoadTime
 +
*the state of the system initialization, such as initialization of the plugin modules.
 +
*a '''subset''' of the user_data that represents the current state of the device's UPnP variables
 +
*the status of any active or recent '''jobs''', such as if a light was successfully turned off
  
'''#184 Set Level:''' Sets a device to a certain level. For dimmable lights this sets the level<br> Parameters: #76 Level: a number between 0 and 100
+
===Tracking status changes===
 +
If you call lu_status without passing a DataVersion on the URL, you will get the current value of all the UPnP variables for a device. Note that most of the UPnP variables do not ever change.  For example, with a light switch, only the variable "SwitchPower:Status" changes, as the switch is turned off and on.  There are many other variables, like "Capabilities" which are simply configuration data or settings the user modified.  If you pass &DataVersion=1 on the URL, you will only see the UPnP variables which have changed since the Luup engine started.  So, if you parse the initial UPnP variables when you first call user_data, you can call lu_status with DataVersion=1.  Once you call lu_status the first time, store the DataVersion and on subsequent calls pass it on the URL and you will only get the UPnP variables which have changed since that last DataVersion.  Regardless, you will also get the current state of jobs and system initialization.
  
'''#192 On/#193 Off:''' Turns a device on or off. This is also used for unlock/lock door locks<br> Parameters: #76 Level: a number between 0 and 100
+
On subsequent calls to lu_status, you should also pass back in the LoadTime which you received on the prior call.
  
'''#278 Set Temperature:''' Sets a thermostat's set point to a given temperature<br> Parameters: #5 Value_To_Assign: The temperature in degrees celsius. The number may be preceded with a - or a + to decrease/increase the temperature relative to its current setting, and may be followed by an H or C to set only heat or cool set point. If H or C is not specified, both heat/cool set points will be set for those thermostats that support dual set points
+
===Controlling the poll timing===
 +
You can also pass in a Timeout value, which means the call will block for up to that many seconds if nothing has changed, and will return immediately when something does. This way you can have infrequent polling, say every 60 seconds by putting a Timeout value of 60, but your UI will be immediately responsive since, when something changes, it returns immediately.  You can also add a MinimumDelay, which means that the call will wait for at least that many milliseconds.  This is advisable so that in the event there are lots of continuous changes, such as a scene turning off many lights, you won't have lu_status calls returning non-stop consuming all the resources on both the Vera and the UI.
  
'''#279 Set Fan:''' Sets the fan of a thermostat to always on or to automatic<br> Parameters: #8 On/Off: Set this value to 1 to put the thermostat in 'on' mode, and 0 to put it in 'auto' mode.
+
===Startup status===
 +
The section with the initialization tasks is shown in the startup tag as shown:
  
'''#280 Set Heat/Cool:''' Sets the thermostat to heat/cool<br> Parameters: #8 On/Off: Set this value to H for heat mode, C for cool. To turn the thermostat off, send command #193 (off), and to put it in full 'auto' mode, send command #192 (on)
+
    "startup": {
 
+
        "tasks": [
'''#370 Execute Command Group:''' In the user_data, find the device with the template "FK_DeviceTemplate": "27" (General_Info_Plugin) and send it this command to execute a scene. By including this command within a scene, you can have one scene execute or embed another scene.<br> Parameters: #28 PK_CommandGroup: This is the ID of the scene (i.e. the number following scene_).<br> Parameters: #9 Text: If you want to test a scene that you have not yet created, instead of passing the command group parameter above, you put send the raw string of commands in this format:<br> PK_Device,PK_DeviceGroup,PK_Command,Delay,CancelIfOther,IsTemporary,"PK_CommandParameter","Description"<br> where each command is separated with a new line (\n). In Vera's UI, when you execute a scene from the Dashboard (i.e. a scene that's already saved), it passes the scene # in parameter #28. When the user clicks 'Test' next to a scene in the scene editor, and you want to test a scene that you have not yet saved, it is sent as parameter #9. You can grep DCERouter.log for '^08' (lines starting with 08 are commands) after clicking 'Test' to see the syntax.
+
             {
 
+
                 "id": 0,
'''#684 Zoom In/#685 Zoom Out/#200 Move Up/#201 Move Down/#202 Move Left/#203 Move Right:''' Send these commands to a camera for pan/tilt/zoom.<br> Parameters: None
+
                 "status": 2,
 
+
                "type": "ZWave",
'''#84 Get_Video_Frame:''' Send this command to a camera to retrieve the current image as a JPEG file: Parameters: #19 Data: This is an output parameter that is returned, not an input parameter. It contains the actual image. The parameter type is 'Data', so it contains a block of binary data.<br> Parameters: #20 Format: This is the format of the data. Presently all the cameras return 'JPEG'.
+
                "comments": "No Z-Wave"  
 
+
'''#776 Reset (when sent to a Z-Wave node):''' When sent to a Z-Wave node (i.e. a child of the device Z-Wave interface), it resets that node and causes it to be reconfigured. This is what's sent with Vera's "configure node right now" button. A configuration job is immediately added to the queue.<br> Parameters: none
+
 
+
'''#776 Reset (when sent to the Z-Wave interface):''' When sent to the parent Z-Wave device, the interface which is often device #9, it resets the Z-Wave pairing in dongle. This is the only way to restore the black dongle to a clean state. If you do a hardware reset of Vera, without sending this command, the pairings will remain because they're stored in the dongle itself. This command is sent from Vera's Devices, Z-Wave options, 'reset zwave network' button explained here: [[ZWave Options]].<br> Parameters: #51 <br>Arguments: This parameter can be: SUC or SIS (i.e. send either of those 3 character strings, or leave the parameter blank). The default is to send it with SIS. This is a Z-Wave term, meaning the dongle will report new nodes to slave controllers.
+
 
+
'''#967 Add Node:''' When sent to the parent Z-Wave device, the interface which is often device #9, it causes the dongle to go into 'pairing' mode to add new devices. See [[ZWave Options|Z-Wave Options]]<br> Parameters: #39 Options: This parameter can be the single character H to use high power inclusion. Or it can be the word CANCEL to stop any current add/remove going on.<br> Parameters: #48 Value: If empty or set to 1, any type of node can be added. You can also send one of the following values to restrict what type of node is added: 2=node controller, 3=node slave, 4=node existing, 5=node stop, 6=node stop failed<br> Parameters: #182 Timeout: Number of seconds to timeout. If not specified default is 60 seconds. This is how long to wait for the new node.<br> Parameters: #259 Multiple: If true (i.e. 1) then multiple devices can be added and the dongle will stay in include mode until the timeout is reached. Otherwise, the dongle will only add 1 device and exit add mode.
+
 
+
'''#968 Remove Node:''' When sent to the parent Z-Wave device, the interface which is often device #9, it causes the dongle to go into 'reset' mode to remove devices. See [[ZWave Options|Z-Wave Options]]<br> Parameters: #39 Options: This parameter can be the single character H to use high power inclusion.<br> Parameters: #48 Value: If empty or set to 1, any type of node can be removed. You can also send one of the following values to restrict what type of node is removed: 2=node controller, 3=node slave, 4=node existing, 5=node stop, 6=node stop failed<br> Parameters: #182 Timeout: Number of seconds to timeout. If not specified default is 60 seconds. This is how long to wait for the node to be removed.<br> Parameters: #259 Multiple: If true (i.e. 1) then multiple devices can be removed and the dongle will stay in remove mode until the timeout is reached. Otherwise, the dongle will only remove 1 device and exit remove mode.
+
 
+
'''#972 Set Sensor State:''' In the user_data, find the device with the template "FK_DeviceTemplate": "33" (Security_Plugin) and send it this command to change the arm/unarmed state of a sensor. Z-Wave doesn't have the concept of armed/unarmed sensors. But the security plugin keeps a flag for all sensors so when a sensor is tripped, it can fire the normal 'sensor tripped' only, or also a 'armed sensor is tripped' event.<br> Parameters: #2 PK_Device: This is the device ID of the sensors<br> Parameters: #5 Value To Assign: Can be either: ARMED or UNARMED
+
 
+
'''#974 Set PIN:''' For door locks, this sets a user code or pin.<br> Parameters: #17 PK_Users: This is user code to set<br> Parameters: #99 Password: This is the pin code. Leave it blank to clear the pin code for the given user.
+
 
+
== Timer ==
+
 
+
If you want to have a scene executed automatically at a certain time, add a [[Timer]].  As explained above, you must re-send the whole scene with the timer.  Add a JSON block like this to a scene to make it a timer:
+
 
+
             "Timer": {
+
                 "PK_Timer_1": {
+
                    "Description": "T_on30m",
+
                    "Type": "1",
+
                    "Enabled": "1",
+
                    "Criteria": {
+
                        "param_1": {
+
                            "PK_CriteriaParmList": 11,
+
                            "Operator": 1,
+
                            "Parm": "",
+
                            "Value": "30m"
+
                        }
+
                    }
+
                 }
+
            }
+
 
+
The Timer ID # (1 in this case) can be whatever you want, as well as the description.  If Enabled is set to "0", the timer will not execute.  Type can be: INTERVAL_EVENT=1 (ie does something every x minutes/seconds), DAY_OF_WEEK=2, DAY_OF_MONTH=3, ABSOLUTE_TIME=4.  In all cases, the parameters for the type are specified in the Criteria section.  The operator is OPERATOR_EQUALS=1, OPERATOR_NOTEQUALS=2, OPERATOR_GREATERTHAN=3, OPERATOR_LESSTHAN=4, OPERATOR_CONTAINS=5.
+
 
+
For interval timers, leave parm blank, use "PK_CriteriaParmList": 11 (per LinuxMCE this is: #define CRITERIAPARMLIST_Time_of_day_CONST 11), and set the value to a number followed by m or h (minutes/hours).  The above is a timer that will go off every 30 minutes.
+
 
+
For Day of Week timers, set CRITERIAPARMLIST_Day_Of_Week_CONST 17 with a comma separated list of days of week (ie 1=Sunday), and CRITERIAPARMLIST_Time_of_day_CONST 11 is the time of day.  Multiple times are comma separated.  Times can be in 12 hour (with an optional am/pm) or 24 hour.  All the following are acceptable ways of saying 3:15pm: 3:15pm 3:15 p.m., 3:15p, 15:15.  Generally we use 24 hour time since it's simpler.  Here is a day of week timer that goes off every day at 6pm and 8pm:
+
 
+
                    "Criteria": {
+
                        "param_1": {
+
                            "PK_CriteriaParmList": 17,
+
                            "Operator": 1,
+
                            "Parm": "",
+
                            "Value": "1,2,3,4,5,6,7"
+
                        },
+
                        "param_2": {
+
                            "PK_CriteriaParmList": 11,
+
                            "Operator": 1,
+
                            "Parm": "",
+
                            "Value": "6:00pm ,20:00"
+
                        }
+
                    }
+
 
+
For day of month timers, type 3, set CRITERIAPARMLIST_Day_Of_Month_CONST 18 to the days of the month, and CRITERIAPARMLIST_Time_of_day_CONST 11 to the time(s) of day.  The following goes off on the 2nd and 7th of each month, at midnight, and 9:30:35pm
+
 
+
"Criteria": {
+
                        "param_1": {
+
                            "PK_CriteriaParmList": 18,
+
                            "Operator": 1,
+
                            "Parm": "",
+
                            "Value": "2,7"
+
                        },
+
                        "param_2": {
+
                            "PK_CriteriaParmList": 11,
+
                            "Operator": 1,
+
                            "Parm": "",
+
                            "Value": "0:00,21:30:35"
+
                        }
+
                    }
+
 
+
 
+
For absolute timers, set "PK_CriteriaParmList": 19 (CRITERIAPARMLIST_Specific_Date_CONST 19) and set the Value to the actual date/time.  The following timer will go off on Feb 15, 2009 at 14:30:30
+
 
+
"PK_Timer_2": {
+
                    "Description": "New timer",
+
                    "Type": "4",
+
                    "Enabled": "1",
+
                    "commands_ids": [
+
                       
+
                    ],
+
                    "commands": {
+
                       
+
                    },
+
                    "Criteria": {
+
                        "param_1": {
+
                            "PK_CriteriaParmList": 19,
+
                            "Operator": 1,
+
                            "Parm": "",
+
                            "Value": "2009-2-15 14:30:30"  
+
                        }
+
                    }
+
                }
+
 
             },
 
             },
  
 +
The startup tasks begin whenever the Luup engine is reset, such as after the user makes a configuration change.  Ever plugin and module in the Luup engine does a startup sequence.  The id is not really important.  The status numbers are the same as for jobs, so 2 means the module failed to startup.  The 'Type' is what you can use to key off of to know which module is being reported, such as "ZWave", and comments are just notes indicating the current state.  For example, "No Z-Wave" means there's no Z-Wave dongle connected.
  
== Event  ==
+
Once all the plugins have been initialized successfully the startup section will disappear completely from lu_status.
 
+
To make a scene happen automatically, add an [[Event]]. Note that any device in the system can fire any event. The event ID numbers and the parameters for each are defined in'''template_data'''. Therefore, when you add an event, this is a free-form template that can be used for any type of event. '''PK_CriteriaParmList''' is one of the following:
+
 
+
1=CRITERIAPARMLIST_System_CONST<br> 2=CRITERIAPARMLIST_PK_Installation_CONST<br> 3=CRITERIAPARMLIST_PK_Skin_CONST<br> 5=CRITERIAPARMLIST_Month_CONST<br> 8=CRITERIAPARMLIST_PK_Device_CONST<br> 10=CRITERIAPARMLIST_PK_DeviceTemplate_CONST<br> 11=CRITERIAPARMLIST_Time_of_day_CONST<br> 12=CRITERIAPARMLIST_PK_DeviceCategory_CONST<br> 13=CRITERIAPARMLIST_PK_Room_CONST<br> 14=CRITERIAPARMLIST_PK_DeviceGroup_CONST<br> 15=CRITERIAPARMLIST_House_Mode_CONST<br> 16=CRITERIAPARMLIST_Room_Mode_CONST<br> 17=CRITERIAPARMLIST_Day_Of_Week_CONST<br> 18=CRITERIAPARMLIST_Day_Of_Month_CONST<br> 19=CRITERIAPARMLIST_Specific_Date_CONST<br> 20=CRITERIAPARMLIST_PK_RoomType_CONST<br> 22=CRITERIAPARMLIST_PK_EventList_CONST<br> 23=CRITERIAPARMLIST_PK_EventHandler_CONST<br> 24=CRITERIAPARMLIST_PK_EventParameter_CONST<br> 25=CRITERIAPARMLIST_User_Mode_CONST<br> 26=CRITERIAPARMLIST_State_CONST<br>
+
  
The operator is OPERATOR_EQUALS=1, OPERATOR_NOTEQUALS=2, OPERATOR_GREATERTHAN=3, OPERATOR_LESSTHAN=4, OPERATOR_CONTAINS=5.  
+
Note that lu_status also returns UserData_DataVersion, which is the dataversion from user_data.  That way you don't need to poll user_data in parallel.  Simply retrieve the user_data one time at startup, then poll lu_status, and, if UserData_DataVersion is different from the previous user_data you retrieved, then download user_data again.
  
Only CRITERIAPARMLIST_PK_EventParameter_CONST uses the "Parm" field for the criteria, and in this case, the "Parm" field is the ID of the EventParameter and Value is the value of the event parameter.  
+
Some notes on building a full replacement, including configuration, are available here [[UI_Notes_Replacement]], however the syntax is not up to date with the Luup architecture.
  
The following event will be evaluated TRUE when the device #21 (see 8=CRITERIAPARMLIST_PK_Device_CONST, operator 1 is 1) fires the event #25 (EVENT_Temperature_Changed_CONST 25) and the parameter #30 for the event EVENTPARAMETER_Value_CONST 30 is &gt;32 -- that is, (24=CRITERIAPARMLIST_PK_EventParameter_CONST parameter #30 operator 3=&gt; and value is 32). In other words, when the thermostat says the temperature is &gt; 32 degrees celsius the event will fire and the scene the event is attached to will be executed.
+
===Job status===
 +
The jobs for a device will look like this:
  
                "PK_Event_2": {
+
    "devices": [
                    "Description": "temp reached",
+
        {
                    "FK_CannedEvents": "101",
+
            "id": 1,
                    "PK_Event": "25",
+
            "Jobs": [
                     "Enabled": "1",
+
                {
                     "Criteria": {
+
                     "id": "1",
                        "param_42": {
+
                     "name": "job#1 :getnodes (0x00D068F0) P:10 S:4",
                            "Operator": "1",
+
                    "icon": "",
                            "Value": "21",
+
                    "comments": "",
                            "Parm": "",
+
                    "status": "4"  
                            "PK_CriteriaParmList": "8"
+
                        },
+
                        "param_43": {
+
                            "Operator": "3",
+
                            "Value": "32",
+
                            "PK_ParameterType": 2,
+
                            "Parm": "30",
+
                            "PK_CriteriaParmList": "24"
+
                        }
+
                    }
+
 
                 }  
 
                 }  
 +
            ]
 +
        },
  
Rather than presenting the user a free-form form to fill out to specify his event, Vera uses "Canned Events", which are defined in template_data. These are basically event templates that define some common events and what parameters to prompt the user for. In the example above, note the canned event is 101. In template data:  
+
The id is the job id number.  When you run an action, like turning on a light, if it happens asynchronously, you'll get a job id number. All pending jobs for a device are shown by their id number.  The name is just an internal name for the job.  Icon is an optional keyword to indicate what sort of icon should be shown to the user. For example, 'getnodes' has no icon, meaning this type of job is generally not of interest to a user.  If the icon was 'ON' or 'OFF' that would mean this job is busy turning on or off a light. Comments is notes about the job, if any.  This may be shown to a user in a tool tip or similar, but is generally more technical than users would care to know.  The status indicates the current state of the job, as shown:
  
"PK_CannedEvents_101": { "Description":"Temperature is reached", "FK_Event":"25", "bIsAnd":"1", "bIsNot":"0" },  
+
*job_None=-1, // no icon
 +
*job_WaitingToStart=0, // gray icon
 +
*job_InProgress=1, // blue icon
 +
*job_Error=2,  // red icon
 +
*job_Aborted=3,  // red icon
 +
*job_Done=4, // green icon
 +
*job_WaitingForCallback=5  // blue icon - Special case used in certain derived classes
  
So it's an event handler for event #25, which is:
+
If the status is 0, this means the job is queued but hasn't started.  If it's 1 or 5 the job is being executed right now.  Generally both 1 and 5 are presented to the user the same way as a 'busy', although technically 1 means Vera is actively talking to the device, and 5 means Vera is waiting for a reply from the device.  Status codes 2, 3 and 4 mean the job has finished.  4 means the job went ok, and both 2 and 3 mean it failed.  Technically 3 means the job was aborted by another job or an external process, like a user cancelling it, while 2 means it failed due to a problem talking to the device.  In both cases this is usually presented the user the same way, as a failure.
  
"PK_Event_25": { "FK_EventCategory":"10", "Description":"Temperature Changed" },
+
== Categories and device types ==
  
'''bIsAnd''' means all the parameters are AND'd together and must all match. If bIsAnd were 0, it would be an OR. bIsNot means the negative, that is, trip the event if all the criteria are false. You also see:  
+
The values used in user_data to determine the types of devices are in [[Luup_UPNP_Files]]. In general you can use the category instead of the devicetype since it's an integer and is thus faster to compare:
  
"PK_CannedEvents_CriteriaParmList_102": { "FK_CannedEvents":"101", "FK_CriteriaParmList":"8", "Description":"Which device?", "Comments":"", "Operator":"1", "Parm":"", "DefaultValue":"1", "ExtraInfo":"", "Required":"0" }, "PK_CannedEvents_CriteriaParmList_103": { "FK_CannedEvents":"101", "FK_CriteriaParmList":"24", "Description":"What temperature?", "Comments":"", "Operator":"1", "Parm":"30", "DefaultValue":"", "ExtraInfo":"", "Required":"0" },
+
== pseudo-code for a UI ==
  
So, when prompting the user for a "Temperature changed" event, we will want to get 2 things: the device, and the temperature. Notice that in Vera's UI, the user is prompted for both, and they become part of the event that is attached to the scene. (See '''template_data''' for the complete list of events.)
+
Here is some pseudo code to show how the polling mechanism should be properly implemented. The parsing code is, of course, unique to your UI, so placeholder function names are shown here, like FetchAndParse.  This shows the flow for handling the polling so you know you get the changes reported correctly.
  
You do not necessarily need to parse '''template_data''' in your own UI implementation. The cleanest UI has a custom "hardcoded" panel for the user to fill out. But, '''template_data''' explains all the events Vera's UI prompts for and what values are used.
+
variable int DataVersion_lustatus=0
 +
variable int LoadTime=0
 +
variable int DataVersion_userdata=0
  
== Sending Commands ==
+
:START
 +
  variable boolean FetchUserData=false;
 +
  if( DataVersion_userdata==0 ) // If we're on the first loop and haven't retrieved user_data, do it and don't do an lu_status
 +
    FetchUserData=true;
 +
  else
 +
  {
 +
    while(true)
 +
    {
 +
        newdata = FetchAndParse("lu_status&DataVersion="+DataVersion_lustatus+"&LoadTime="+LoadTime);
 +
        if( newdata.IsEmpty()==false && newdata.isError()==false )
 +
            break;  // If we got data, continue on and process it
 +
        else
 +
            Sleep 1; // If we didn't get anything, or if lu_status failed, just sleep 1 second and stay in the loop to try again
 +
    } // End of while loop
  
The UI should always send commands with a return response (type r or o), as explained in [[Data Provider Catalog Plugin]]. The response will be "OK x" where x is the optional job #. For most Z-Wave activities, a job is created and the ID is returned. Some types of commands don't have job numbers, like controlling a camera. However, you must always check for an OK. It is normal that when you send a command it might not get through because the router is reloading the data, or the Z-Wave device is reset. After you submit new data with a user_data post, the router will reload, which takes a couple seconds, and then the Z-Wave device will also reload and re-configure any devices. So when sending a command, you should do this in a loop that tries to re-send the command every 5 seconds, for up to 30 seconds, until it gets an OK. During this time the UI should display some hourglass or something so the user knows his command hasn't been received or acknowledged yet. If the router and the Z-Wave module are already running, which is normally the case if you haven't just saved, you should get back the OK in less than 1 second. In the case of Z-Wave, the OK just means the command has been queued. It does not mean it's actually been sent on the Z-Wave network. Under normal circumstance the command will be sent right away. But, sometimes, the Z-Wave network may be busy. Or if the device is flaky, or if needs a lot of hops, or if it's a secure device which causes key exchange, the command can take a while to be processed. And, the command may fail. The initial OK just tells you the job was queued, not that it was successful.
+
    if( newdata.UserData_DataVersion!=DataVersion_userdata )
 +
    {
 +
        FetchUserData=true;
 +
    }
 +
    else  // Only Parse if userdata is the same, otherwise we're going to reload user_data
 +
    {
 +
        ParseLuStatus();  // This won't run if user_data has changed
 +
        DataVersion_lustatus=newdata.DataVersion
 +
      }
 +
  }  // end of else loop
  
To find out if the job was successful and monitor its progress, you can do 3 things:
+
if( FetchUserData==true )
 +
{
 +
  UI.HourglassAndSuspend(true); // Put a 'busy' hourglass in the UI, display a message in the info panel "Updating data" and suspend all UI stuff since this may take a moment
 +
  newdata = FetchAndParse("user_data2");
 +
    if( newdata.IsEmpty()==false && newdata.isError()==false )
 +
    {
 +
        ParseUserData();
 +
        DataVersion_lustatus=newdata.DataVersion
 +
        LoadTime=newdata.LoadTime
 +
        DataVersion_userdata=newdata.DataVersion
 +
    }
 +
    else
 +
      UI.DisplayError("Failed to update data"); // Display in the info panel an error message that the user will see for 10 seconds or so
  
1) you can use the '''zwave_status''' request (see [[ZWave Status|Z-Wave Status]]). This shows you all the jobs that are currently active or were completed within the last 30 seconds. It is broken down by device, and will contain the job ID.
+
  UI.HourglassAndSuspend(false); // Put a 'busy' hourglass in the UI, display a message in the info panel "Updating data" and suspend all UI stuff since this may take a moment
 
+
}
2) use '''job_status''' passing in the device ID only, such as '''http://127.0.0.1:3451/data_request?id=job_status&amp;parameters=13''' (for the parameter, you can pass either the device id of the Z-Wave device itself, or any of its children). This will return all jobs that are currently active. Jobs that are completed are not on the list. (See [[Data Provider Catalog Plugin Requests]])
+
 
+
3) use the same request, but add [job #]. This will return just the information on the requested job, and you can get information on the job up to 3 minutes after the job has ended. ( See [[Data Provider Catalog Plugin Requests]])
+
 
+
The reason for the 30 second timeout in option #1 is to make the UI presentation easier. The assumption is that if you're going to show all devices and icons representing the active jobs, after a job is completed and 30 seconds has passed, you probably don't want it on the list. But, if you're requesting specific information on a particular job, as in #3, you want the job info to be available as long as possible, and 3 minutes is how long a job is kept in the memory after completion before it's dumped.
+
 
+
== Miscellaneous Test Tips ==
+
 
+
If you want to create some sample devices, run:
+
 
+
'''/usr/bin/MessageSend localhost 0 9 1 776 51 MANYNODES 88 xxx'''
+
  
where '''xxx''' is the number of sets of test devices. This will create a set of dummy devices that don't actually exist, but that you can see how they work in the UI. Such as a thermostat, light switch, etc. So if you run it with xxx=1, it will create 1 set. If you want to see how the UI looks with lots of creates, run it with 15. Run it with 0 to return to normal.
+
Sleep 1; // We know we just parsed user_data or lu_status, so sleep before looping
 +
goto START; // Loop again and start over

Latest revision as of 12:27, 3 July 2015

Here is some general information about getting information to display in a user interface:

Contents

[edit] UPnP messaging system

Vera uses UPnP for all the messaging, such as turning lights on and off. So Vera translates Z-Wave, Insteon, infrared codes, etc., into UPnP actions. If you have already implemented a UPnP stack and can send properly formated UPnP SOAP/XML requests, you can control everything using standard UPnP action invocation. If you did not, Vera provides a simple HTTP GET interface as well, which is discussed below.

In a nutshell UPnP works like this: You have UPnP devices, which are things that can be controlled and can report their state, like a light switch. And you have UPnP Control Points, which are the things that let a user control UPnP devices, like a touch-screen web pad. The Control Point does this by a) reading the device and descriptions for the UPnP device to see what it can do, and b) invoking actions on the UPnP device (ie telling it to do something), and c) reading and setting variables for the device which describe the current state and/or configuration settings for the device.

A UPnP device is defined in an XML document called a device description document. To see one, in Vera's setup UI, go to Devices, Luup plugins, Luup Files, and click 'view' file next to D_BinaryLight1.xml. Use Firefox since it has a built-in XML viewer. Notice the tag: <deviceType>urn:schemas-upnp-org:device:BinaryLight:1</deviceType>. This defines the type of device, namely an on/off light switch, which is what you use to know how to represent this device to a user. A device optionally implements one or more services. In this case the services: urn:upnp-org:serviceId:SwitchPower1, urn:micasaverde-com:serviceId:EnergyMetering1 and urn:micasaverde-com:serviceId:HaDevice1.

A service is a collection of actions which a device implement and which you can invoke from a UPnP Control Point, as well as a collection of variables which always have a current value. The variables describe the current state of the device and/or configuration settings. View the file S_SwitchPower1.xml to see a service. For example, the device urn:schemas-upnp-org:device:BinaryLight:1 implements the service urn:upnp-org:serviceId:SwitchPower1, which has the action SetTarget, which is how you turn the light on and off. The action takes a single argument newTargetValue which can be 0 to turn the light off and 1 to turn it on. The service also has the variable Status which is 0 or 1 depending on whether the light is currently on or off.

If you open the device description for a dimmable light D_DimmableLight1.xml you'll see that it implements the same service S_SwitchPower1.xml, since you can still turn it on and off, and it also implements the service urn:upnp-org:serviceId:Dimming1, which has an action to set the dim level (SetLoadLevelTarget).

To test UPnP calls you can use the Intel Device Spy utility available here. It should pick up Vera, show you all the devices, like light switches, thermostats, etc., let you expand the services and see the actions and variables. Click an action, like SetTarget, to specify the arguments and click 'Invoke' to run the action, such as turning on and off the light.

[edit] JSON vs. XML

The native UPnP protocol uses XML/SOAP. But there are also several times you will request data from Vera that has nothing to do with the UPnP spec. These will be done with data_request's as explained below, such as user_data, lu_status, etc. Internally Vera uses JSON as the native format, but Vera can convert to XML (details follow). In general when you want to view data in a human readable format, such as the device list, it's easiest to use the Firefox browser, and request Vera convert the data to XML. Firefox has a nice browser to display XML in human readable format. If you want to make the JSON data nicely formatted, you can use the web site jsonlint.com. In a UI application which will request data regularly from Vera we recommend retrieving everything in JSON format, not XML, because Vera's CPU is not that powerful and so continuous requests of data in XML format will cause a lot of CPU time to be devoted to converting JSON into XML.

[edit] Finding Vera on the local network

You can find Vera by using the traditional UPnP discovery process, or you can retrieve this URL:
https://sta1.mios.com/locator_json.php?username=xxx where the username=xxx is optional, but, if specified, it will report all systems that mios.com user xxx can report whether local or remote, and without the username=xxx it only shows the Vera's on the user's local home network.

Each Vera, when it boots up, reports its internal IP address to the central mios.com server, which tracks this along with the external IP address. locator.php shows all serial numbers and internal network IP addresses on the same external IP. For example, if https://sta1.mios.com/locator_json.php?username=xxx.

[edit] The HTTP interface

Vera listens on port 3480. Vera responds to UPnP actions the normal way, or by making simple HTTP requests. For example, to turn on a light you can either send the UPnP action "SetTarget" to the device using the normal UPnP mechanism, or you can simply put this URL in your web browser, or with wget, or similar:

http://[ipadress]:3480/data_request?id=lu_action&output_format=xml&DeviceNum=10&serviceId=urn:upnp-org:serviceId:SwitchPower1&action=SetTarget&newTargetValue=1

That URL will return the same results of the action as using the normal UPnP architecture. The output_format=xml on the URL means the data returned should be in XML format. You can instead use output_format=json

The service ID's, actions, and arguments are all defined by the UPnP forum. A list of ratified UPnP devices and services is available on the UPnP Forum. Mi Casa Verde added its own custom devices and services when there was no existing UPnP standard. A list of these can be found in the Luup_UPNP_Files header files.

[edit] Getting the system configuration

Either use the UPnP service/action:
urn:micasaverde-com:serviceId:HomeAutomationGateway1/GetUserData

or use the built-in request:

http://ipaddress:3480/data_request?id=user_data2&output_format=json (or xml)

This returns the system configuration file for Vera. It's assumed you understand the way Vera categorizes devices with Rooms, Devices, Scenes, etc. When creating a user interface for controlling Vera only, like on a mobile phone, most of the tags can be ignored, since usually you just need the list of rooms and devices.

[edit] Accessing Vera remotely through the mios server

Native UPnP only works on a local area home network, and cannot be used over the Internet. The mios server provides a secure way to remotely access and control your Vera system using the HTTP interface without having to make any substantial changes to the UI. Everything you can do locally with Vera on port 3480, you can do remotely with mios using the exact same syntax. You only need to ask the user for his username and password and pass them on the URL to the remote access server, along with the serial number of the unit (ie like 12345). For example, the above user_data is the syntax for local access on a home network. To retrieve the same URL over the internet with mios use:

https://fwd2.mios.com/demovera/myvera123/12345/data_request?id=lu_status&output_format=json (or use fwd1.mios.com)

assuming demovera is the username and myvera123 is the password that the user chose setting up his mios.com account. Note that since the request is https, the username and password are encrypted because https encrypts the URL's as well as the contents of the page.

[edit] Building a control-only UI for Vera

If you just want to control Vera, and not modify the configuration, such as with a cell phone interface or web pad, the flow might possibly work like this:

1) For the initial setup, you need to ask whether the user wants to (a) access Vera remotely with the mios service, and if so, get the user's username/password; or (b) access Vera directly on the home network. You can use locator.php to show the Vera on the home network. You might want to do an auto-detect. For example, you could use locator.php to see if Vera exists locally, and if not, prompt the user for a mios username and password. You can use locator.php and pass the username to get the serial number and internal IP, and then automatically switch to direct access if locator.php (without the username) indicates that serial number is found on the local network. This would allow the user to automatically switch between local access with Wi-Fi (which is much faster of course) and remote access with mios and the mobile phone network. Or just ask for his mios username and show him all the Vera's he can control, either local or remote.

2) Once the connection is established, retrieve the list of rooms, scenes, and devices from Vera (see user_data below). You can cache this data locally so you don't need to retrieve it and parse it over and over.

3) Present the user with the rooms, scenes, devices. In Vera's UI's we show first the rooms and then let the user pick a device or scene in the room. However this data could be presented graphically, such as on a floorplan. Your UI can have Vera store extra tags and data in the configuration database (ie user_data) to store things like coordinates for icons, outlines or rooms and so on.

4) If the user picks a scene you can run the scene with the following URL, passing the scene number as x, and it will return an OK if it went okay:

http://127.0.0.1:3480/data_request?id=lu_action&serviceId=urn:micasaverde-com:serviceId:HomeAutomationGateway1&action=RunScene&SceneNum=x

5) If the user picks a device, you use the category which is contained in the user_data to determine what type of controls to present the user. (See Luup UPNP Files for a list of the categories.) When the user chooses an action, you can send it like this:

http://ipadress:3480/data_request?id=lu_action&output_format=xml&DeviceNum=10&serviceId=urn:upnp-org:serviceId:SwitchPower1&action=SetTarget&newTargetValue=1

For a list of common actions and device types see: Luup CP Mandatory Types

Some actions return immediately with an 'OK'. Other jobs may take time to complete and are processed asynchronously. For these asynchronous jobs you will get a job ID back. There are several ways to present this to the user. One possibility is to do what Vera does in the UI, namely to use lu_status (explained next) to find all active jobs and to put a 'job' icon next to each device to indicate the progress of the job. In this way the user isn't tracking a particular job per se, but just has visual feedback that a device is busy, and if the job icon(s) turn green, that everything went through okay. You could instead track the action individually using the job number that is returned, or use some other method, like making the icon for the device appear animated while it's busy, and turn green or red if the last command succeeded or failed.

6) Periodically poll the system with lu_status (explained below), like this:

http://ipaddress:3480/data_request?id=lu_status&output_format=json

That returns the current values of the UPnP variables, which you can use to show the user current status. For example, if the variable Status is 1 for a switch, you can show the 'on' button in a selected state, while 0 shows it in an 'off' state. lu_status also shows any active jobs for a device.

[edit] user_data

The user_data is the main configuration file that Vera uses to store all the rooms, devices, scenes, timers, events, users, and any other data about the system. You should request the user_data to get whatever data you need to present to the user, at a minimum, for example, you'll need the list of devices, their descriptions, and the categories (light switch, thermostat, etc.). You'll also want the list of scenes to present the user. To fetch the current user_data from Vera use the user_data request, like this:

Returns JSON (preferred native format):

http://[ip address]:3480/data_request?id=user_data

Returns XML:

http://[ip address]:3480/data_request?id=user_data&output_format=xml

You can also add a 'DataVersion=TimeStamp' parameter to the URL. It the data has changed since the TimeStamp, all the data is returned. If the data has not changed since the TimeStamp, Vera will return a page with the text 'NO_CHANGES':

http://[ip address]:3480/data_request?id=user_data&DataVersion=315587159

The user_data contains the state for all the devices. For example this indicates that the device id #17, called "Switch" is turned off (ie service SwitchPower1, variable Status is 0)

{

   "devices": [
       {
           "id": 17,
           "category": 3,
           "room": 1,
           "name": "Switch",
           "ip": "",
           "mac": "",
               {
                   "service": "urn:upnp-org:serviceId:SwitchPower1",
                   "variable": "Status",
                   "value": "0" 
               }
       }
    ]

}

Warning.png On UI7 build lu_sdata and lu_status have been deprecated, and you should use "status" instead.

[edit] lu_status

The UPnP variables describe the state of the devices according to the UPnP specs. When the variables change that information needs to be shown to the user, eg change a Switch icon from off to on. If you are interfacing with Vera using the UPnP stack, you can subscribe to the device's events to receive notifications automatically when a device's state changes. However if you're using the web interface you will need to poll using status request.

Call lu_status request like so:

http://[ip address]:3480/data_request?id=status
http://[ip address]:3480/data_request?id=status&output_format=xml
http://[ip address]:3480/data_request?id=status&DataVersion=315587159


The returned document contains four sets of information, which constantly change to reflect the current status:

  • root attributes including DataVersion, which is the status timestamp, plus other attributes such as LoadTime
  • the state of the system initialization, such as initialization of the plugin modules.
  • a subset of the user_data that represents the current state of the device's UPnP variables
  • the status of any active or recent jobs, such as if a light was successfully turned off

[edit] Tracking status changes

If you call lu_status without passing a DataVersion on the URL, you will get the current value of all the UPnP variables for a device. Note that most of the UPnP variables do not ever change. For example, with a light switch, only the variable "SwitchPower:Status" changes, as the switch is turned off and on. There are many other variables, like "Capabilities" which are simply configuration data or settings the user modified. If you pass &DataVersion=1 on the URL, you will only see the UPnP variables which have changed since the Luup engine started. So, if you parse the initial UPnP variables when you first call user_data, you can call lu_status with DataVersion=1. Once you call lu_status the first time, store the DataVersion and on subsequent calls pass it on the URL and you will only get the UPnP variables which have changed since that last DataVersion. Regardless, you will also get the current state of jobs and system initialization.

On subsequent calls to lu_status, you should also pass back in the LoadTime which you received on the prior call.

[edit] Controlling the poll timing

You can also pass in a Timeout value, which means the call will block for up to that many seconds if nothing has changed, and will return immediately when something does. This way you can have infrequent polling, say every 60 seconds by putting a Timeout value of 60, but your UI will be immediately responsive since, when something changes, it returns immediately. You can also add a MinimumDelay, which means that the call will wait for at least that many milliseconds. This is advisable so that in the event there are lots of continuous changes, such as a scene turning off many lights, you won't have lu_status calls returning non-stop consuming all the resources on both the Vera and the UI.

[edit] Startup status

The section with the initialization tasks is shown in the startup tag as shown:

   "startup": {
       "tasks": [
           {
               "id": 0,
               "status": 2,
               "type": "ZWave",
               "comments": "No Z-Wave" 
           },

The startup tasks begin whenever the Luup engine is reset, such as after the user makes a configuration change. Ever plugin and module in the Luup engine does a startup sequence. The id is not really important. The status numbers are the same as for jobs, so 2 means the module failed to startup. The 'Type' is what you can use to key off of to know which module is being reported, such as "ZWave", and comments are just notes indicating the current state. For example, "No Z-Wave" means there's no Z-Wave dongle connected.

Once all the plugins have been initialized successfully the startup section will disappear completely from lu_status.

Note that lu_status also returns UserData_DataVersion, which is the dataversion from user_data. That way you don't need to poll user_data in parallel. Simply retrieve the user_data one time at startup, then poll lu_status, and, if UserData_DataVersion is different from the previous user_data you retrieved, then download user_data again.

Some notes on building a full replacement, including configuration, are available here UI_Notes_Replacement, however the syntax is not up to date with the Luup architecture.

[edit] Job status

The jobs for a device will look like this:

   "devices": [
       {
           "id": 1,
           "Jobs": [
               {
                   "id": "1",
                   "name": "job#1 :getnodes (0x00D068F0) P:10 S:4",
                   "icon": "",
                   "comments": "",
                   "status": "4" 
               } 
           ] 
       },

The id is the job id number. When you run an action, like turning on a light, if it happens asynchronously, you'll get a job id number. All pending jobs for a device are shown by their id number. The name is just an internal name for the job. Icon is an optional keyword to indicate what sort of icon should be shown to the user. For example, 'getnodes' has no icon, meaning this type of job is generally not of interest to a user. If the icon was 'ON' or 'OFF' that would mean this job is busy turning on or off a light. Comments is notes about the job, if any. This may be shown to a user in a tool tip or similar, but is generally more technical than users would care to know. The status indicates the current state of the job, as shown:

  • job_None=-1, // no icon
  • job_WaitingToStart=0, // gray icon
  • job_InProgress=1, // blue icon
  • job_Error=2, // red icon
  • job_Aborted=3, // red icon
  • job_Done=4, // green icon
  • job_WaitingForCallback=5 // blue icon - Special case used in certain derived classes

If the status is 0, this means the job is queued but hasn't started. If it's 1 or 5 the job is being executed right now. Generally both 1 and 5 are presented to the user the same way as a 'busy', although technically 1 means Vera is actively talking to the device, and 5 means Vera is waiting for a reply from the device. Status codes 2, 3 and 4 mean the job has finished. 4 means the job went ok, and both 2 and 3 mean it failed. Technically 3 means the job was aborted by another job or an external process, like a user cancelling it, while 2 means it failed due to a problem talking to the device. In both cases this is usually presented the user the same way, as a failure.

[edit] Categories and device types

The values used in user_data to determine the types of devices are in Luup_UPNP_Files. In general you can use the category instead of the devicetype since it's an integer and is thus faster to compare:

[edit] pseudo-code for a UI

Here is some pseudo code to show how the polling mechanism should be properly implemented. The parsing code is, of course, unique to your UI, so placeholder function names are shown here, like FetchAndParse. This shows the flow for handling the polling so you know you get the changes reported correctly.

variable int DataVersion_lustatus=0
variable int LoadTime=0
variable int DataVersion_userdata=0
START
 variable boolean FetchUserData=false;
 if( DataVersion_userdata==0 )  // If we're on the first loop and haven't retrieved user_data, do it and don't do an lu_status
   FetchUserData=true;
 else
 {
    while(true)
    {
        newdata = FetchAndParse("lu_status&DataVersion="+DataVersion_lustatus+"&LoadTime="+LoadTime);
        if( newdata.IsEmpty()==false && newdata.isError()==false )
           break;  // If we got data, continue on and process it
       else
           Sleep 1; // If we didn't get anything, or if lu_status failed, just sleep 1 second and stay in the loop to try again
    } // End of while loop
    if( newdata.UserData_DataVersion!=DataVersion_userdata )
    {
       FetchUserData=true;
    }
    else  // Only Parse if userdata is the same, otherwise we're going to reload user_data
    {
       ParseLuStatus();  // This won't run if user_data has changed
       DataVersion_lustatus=newdata.DataVersion
     }
 }  // end of else loop
if( FetchUserData==true )

{

  UI.HourglassAndSuspend(true); // Put a 'busy' hourglass in the UI, display a message in the info panel "Updating data" and suspend all UI stuff since this may take a moment
  newdata = FetchAndParse("user_data2");
   if( newdata.IsEmpty()==false && newdata.isError()==false )
   {
       ParseUserData();
       DataVersion_lustatus=newdata.DataVersion
        LoadTime=newdata.LoadTime
        DataVersion_userdata=newdata.DataVersion
   }
   else
      UI.DisplayError("Failed to update data"); // Display in the info panel an error message that the user will see for 10 seconds or so
  UI.HourglassAndSuspend(false); // Put a 'busy' hourglass in the UI, display a message in the info panel "Updating data" and suspend all UI stuff since this may take a moment

}

Sleep 1; // We know we just parsed user_data or lu_status, so sleep before looping goto START; // Loop again and start over

Personal tools