Protocol

Tobias Bräutigam edited this page Oct 25, 2017 · 3 revisions

This page describes the protocol between the CometVisu Client and the backend. It is of interest for the developers that are porting the backend to a new system.

The german version can be found at Protokoll. This version here will be translated to English.

Table of Contents

Basics

The communication is using a HTTP connection, that should be protected by TLS (also known as HTTPS).

The CometVisu consists out of different parts that have to be distinguished:

  • backend
  • client
  • application
The backend supplies the (dynamic) data and runs typically on a web server system. Typically it's implemented in scripting languages like PHP or Perl, but a resource efficient implementation in C oder C++, that even doesn't need a usual web server, is also possible.

The client is a part of the application. Together they build the web pages (i.e. the visualisation) that are viewed in a web browser (systems that are using the CometVisu protocol but are not a web page are also possible, but will not be covered further).

The client is a JavaScript library that uses technologies like AJAX and COMET to communicate with the backend in JSON notation and provide the application with real time updates.

Login

The session will be started by calling the "page"

GET /l?u=USER&p=PASSWORD&d=DEVICE
Thereby:
USER = user id, a normal string that is backend specific. (Optional)
PASSWORD = password, a normal string that is backend specific. (Optional)
DEVICE = device id, a unique and backend specific string to identify the client (e.g. "visu living room"). (Optional)
Backend answer:
{
  "v":"MAJOR.MINOR.OTHER",
  "s":"SESSION"
}
MAJOR.MINOR.OTHER = normal string containing the protocol version. MAJOR and MINOR are integer values, OTHER a string (it might even contain additional full stops). (Required)
SESSION = session id, a string that is backend specific. (Required)
The protocol versions of the same major version a downward compatible, i.e. during a major version only optional features will be added.

Even when an anonymous session should be used (i.e. a session id will be ignored by the client or not implemented in the backend), a login is required. The parameters "u" and "p" will not be provided then. The returned session id has to be "0" (a string consisting out of the number zero). During the following communication it's always allowed to pass the anonymous session id (i.e. "0"). The backend has to handle that in the same way as when no session id would have been provided.

If the device id feature will not be used (or isn't implemented) the parameter "d" will not be passed. Should it have been passed, the backend has to ignore it.

Filter

Um das Volumen der zu übertragenden Daten gering zu halten, gibt es das optionale Konzept der Filter. Hier teilt der Client dem Backend mit, welche Adressen zusammen interessant sind und zu einer Filter-ID zusammengefasst werden sollen. Filter können erstellt, aktualisiert oder gelöscht werden:

Neuen Filter erstellen:

POST /f?s=SESSION
{
  "a": [ADDRESS1,ADDRESS2,...]
  "h": [ADDRESSHASH1,ADDRESSHASH2,...]
}

Aktualisieren eines vorhandenen Filters:

PUT /f?f=FILTER&s=SESSION
{
  "a": [ADDRESS1,ADDRESS2,...]
  "h": [ADDRESSHASH1,ADDRESSHASH2,...]
}

Löschen eines vorhandenen Filters:

DELETE /f?f=FILTER&s=SESSION

die Antwort ist immer

{
  "f":"FILTER"
}
dabei gilt:
FILTER = Filter-ID, normaler String in Backend spezifischer Form (Optional, s.u.)
ADDRESS* = Adresse, bei KNX z.B. "1/2/3" (Optional)
ADDRESSHASH* = Hashwert einer Adresse, normaler String in Backend spezifischer Form (Optional)
SESSION = Session-ID (Optional, s.o.)
Wenn das Backend keine Filter unterstützt, oder aber einen Filter gelöscht hat (s.o.), so ist die Rückgabe-Filter-ID gleich "0". Ansonsten die neu erzeugte, oder gerade aktualisierte Filter-ID. Hinweis: es ist zulässig, wenn das Backend bei einer Filter-Änderung eine neue Filter-ID erzeugt, d.h. der Parameter "f" der Antwort ein anderer als der des Aufrufs ist.

Excursus addresses

Addresses can be transmitted in two ways: normal and optionally as a hash value. The hash is a bijective representation of a normal address that the backend changed to a (proprietary) representation for higher performance. So the hash address type will exist only on implementations where application and backend are integrated.

The normal address consists out of:

NAMESPACE:VALUE
NAMESPACE = a backend specific representation of a data source like "KNX", "iKO" or "xPL". It's a normal string that must not contain the character ":". (Optional, see below)
VALUE = the address itself in a namespace specific format. For "KNX" it would be e.g. "1/2/3". Wildcards are allowed. (Required)
If the address doesn't start with a known namespace followed by a colon, then it's optionally allowed to assume a standard namespace.

Read

Calling the page

GET /r?s=SESSION&f=FILTER1&f=...&a=ADDRESS1&a=...&h=ADDRESSHASH1&h=...&t=TIMEOUT&i=INDEX
will read data. It holds
SESSION = session id (Optional, see above)
FILTER* = filter id (Optional)
ADDRESS* = one or multiple addresses (Required)
ADDRESSHASH* = one or multiple address hashes (Required)
TIMEOUT = time out, a integer (Optional)
INDEX = index, a backend specific string (Optional)
At least one the parameters "f", "a" or "h" is required.

If the parameter "t" was left out, the backend keeps the connection open till filter fulfilling data is available (-> COMET). A backend specific time out might close the connection earlier. If the parameter "t" is provided the backend will answer with cached data that is not older than TIMEOUT seconds. Is TIMEOUT equal to "0" or if there is no relevant data in the cache the backend will try to read the data from the bus. A negative TIMEOUT will only deliver data out of the cache, reading from the bus will not happen.

The index is required that no data will be lost between two read requests (so no client specific data has to be remembered by the backend). The value of the INDEX was sent by the backend with the answer to the last read request. If the index was left out, the backend will assume that the client is up to date.

The answer to the read request is:

{
  "d": {
       "ADDRESS1": VALUE,
       ...
       },
  "i": "INDEX"
}
VALUE is a namespace specific JSON value, usually raw data as a string. The HTTP header of the answer has the status:
200: request successful
401: session id required - an empty page will be returned
403: not authorized - an empty page will be returned
404: at least one address or filter id is unknown - an empty page will be returned

Write

Calling the page

GET /w?s=SESSION&a=ADDRESS1&a=...&v=VALUE
will write data. It holds
SESSION = session id (Optional, see above)
ADDRESS* = one or multiple addresses (Required)
VALUE = namespace specific data. Usually the RAW data as a string or JSON for more complex data
The value will be written to all addresses (the order is not defined)

The answer is an empty page with the HTTP status:

200: write successful
401: session id required - no value written
403: not authorized - no value written
404: at least one address is unknown - no value written

Miscellaneous

The order of the parameters of the client requests are examples. Backend implementations have to work with any order.

You can’t perform that action at this time.
You signed in with another tab or window. Reload to refresh your session. You signed out in another tab or window. Reload to refresh your session.
Press h to open a hovercard with more details.