Developing tutorial

From ago control wiki
Revision as of 17:18, 1 November 2013 by Dinki (Talk | contribs)

Jump to: navigation, search

Data Handling within the ago control web admin

Below is ago control developer Hari's explanation of internal data handling data within the ago control web admin:

Within ago control we have the resolver which manages the inventory. Each device entry in the inventory has:

  • a state value and
  • a values map, where other values can be stored

these values are filled with statuschanged and <whatever>changed events. The resolver just listens on all events and when it sees one of these events, it will update the matching device by uuid with the event values. For example, an event.environment.humiditychanged, with event values: uuid (of the device we're talking about), level (humidity level in this case), unit (percent in this case). Here is a humidty sensor from my inventory:

"3669aa90-61f9-48bb-b9f7-45da644faf55": {
  "devicetype": "brightnesssensor",
  "handled-by": "zwave",
  "internalid": "16/1-Luminance",
  "lastseen": 1383225812,
  "name": "",
  "room": "",
  "stale": 0,
 "state": "0",
 "values": {
    "brightness": {
      "level": "0",
      "timestamp": "1381158563",
      "unit": "%"

You can see that the state is "0", as nobody sent a state changed event for it (this would not make sense for such this kind of sensors as it doesn't have a definable state). When you look at the values, you have a quantity key, named "brightness", below that, you have a level, the unit, and the timestamp when this was last updated.

Of course there are also devices with multiple values, like in this example:

  "values": {
    "humidity": {
      "level": 70,
      "timestamp": "1380721587",
      "unit": "percent"
    "temperature": {
      "level": 9,
      "timestamp": "1380721586",
      "unit": "degC"

There are a lot of these quantities used, like "power" for powermeters:

"power": {
        "level": "40.450",
        "timestamp": "1383180526",
        "unit": "W"

From an ago control perspective, the resolver does not care whatever you announce in an "event.environment.<quantitiy>changed" event, as it will just take the level and the unit from the event, and store it under the <quantity> key in the values map of that device in the inventory.

Parallel to that is the device state. This is kind of "legacy" as it was only used to have a state between 0-255. While this is fine for dimmers, switches, and binary sensors, it did not allow to cover whatever values these "old" states are changed with in the "event.device.statechanged" events.

When you open the web interface, the browser opens a connection to the internal webserver of the agorpc component. The embedded mongoose webserver of ago control serves the whole html/javascript pages to the client. The javascript contains the knockout.js application. The agorpc has some special URLs on the internal webserver, too like /jsonrpc . This does not serve a static page, but it is a RPC interface that talks the JSONRPC protocol, version 2. The app now uses that interface, to talk to the other ago control components so when it starts up in the browser after the page is fully loaded, it sends an "inventory" request message out this is honoured by the resolver, which replies a complete inventory to the Knockout JS app. Knockout JS supports a MVC (model, view, controller).

The Javascript app parses the inventory into an internal datamodel and the KO controller connects that with the view, which are the html templates. When it draws the grid on the main page, it puts a view there for each device with the underlying data model hence you can access the device name, the room, the values, the state, etc from the model in the specific template. There is a default template, and there are specific templates for some devicetypes which override the default template. In the template you can use html code to do the shiny layout, and use Knockout specific model "accessors" to tie into the datamodel. This is not only about getting data out, as when you change a value in the GUI, the MVC will trigger a setter function. An example: when you click on "ON" on a device, the Knockout MVC will trigger the javascript method which sends a command out via the JSON-RPC interface.

With this nice and smart MVC thing, we have a good separation between view and data model hence a web designer does not need to care about where the values for each html template come because the Knockout app does all the magic bits by talking to ago control and keeping the datamodel current. This even goes so far, that the Knockout app does not need to refresh the inventory. After pulling the inventory initially, it stays up to date by listening to the events. So in fact, when your app is already running in the browser, and you send that humiditychanged event above not only does the agoresolver store it in its inventory, but also, the agorpc will reply that event on the long standing ajax request to the Knockout app in the browser thus letting the Knockout app update its internal data model. Then the MCV bits come into play and all of a sudden, the browser view is updated with the live values.

Personal tools