API pour applications tierces

Décuplez le potentiel de votre installation NXT en l'intégrant à d'autres applications tierces.

Objectif

L'API du serveur NXT rend possible l'intégration au sein d'autres systèmes et d'applications externes.

Technologie

  • REST API: pour la lecture de l'installation et le lancement d'actions
  • WebSockets: pour la réception des mises-à-jour de statuts en temps réel

Par défaut, l'API du serveur NXT est désactivée !

Afin d'activer l'API, connectez-vous au serveur NXT en tant qu'administrateur et allez dans "Paramètres généraux".

Sous la rubrique "API", cochez la case "API activée" et découvrez la clé secrète partagée JWT (JSON Web Token), nécessaire pour se connecter à l'API.

Domaine

L'API est accessible à la fois localement (http://dobiss.local ou http://[adresse IP]) et via l'accès cloud de votre serveur NXT (https://[mondomaine].mydobiss.com).

Si vous travaillez via le cloud, l'utilisation d'une connexion sécurisée est obligatoire (HTTPS et WSS).

Authentification

L'authentification se fait par l'échange d'un JWT (JSON Web Token) qui doit être crypté avec la clé secrète partagée qui se trouve dans les paramètres de votre serveur NXT.

En limitant la validité du JWT, vous pouvez vous assurer que même si le JWT est intercepté, il ne pourra être utilisé que pendant une durée limitée. Une fois que le JWT a expiré, l'accès sera refusé.

Bien entendu, il est important de ne jamais partager ou exposer la clé secrète JWT.

Exemples: Node.js

REST API

var jwt = require('jsonwebtoken');
var secret = 'sdfsljdflsjefolz496879846879sf7z6e8f4z9';
var token = jwt.sign({name:'my_application'}, secret, {expiresIn: "24h" });

var https = require('https');
var options = {
  host: 'my_domain.mydobiss.com',
  path: '/api/local/discover',
  headers: {'Authorization': 'Bearer ' + token }
};

callback = function(response) {
  var str = '';
  //another chunk of data has been received, so append it to `str`
  response.on('data', function (chunk) {
    str += chunk;
  });

  //the whole response has been received, so we just print it out here
  response.on('end', function () {
    console.log(str);
  });
}

https.request(options, callback).end();

WebSockets API

const WebSocket = require('ws');
var jwt = require('jsonwebtoken');
var secret = 'sdfsljdflsjefolz496879846879sf7z6e8f4z9/8e7f6z8e74f';
var token = jwt.sign({name:'my_application'}, secret, {expiresIn: "24h" });

const ws = new WebSocket('wss://my_domain.mydobiss.com/sockets/api', {headers : { "Authorization": "Bearer " + token}});

REST API

GET /api/local/discover

Renvoie la liste de toutes les sorties, scénarios, programmations, conditions logiques, zones de température, zones audio et drapeaux. Les sorties sont regroupées en groupes logiques (cfr. interface tactile), toutes les autres sont regroupées par type.

Request
  • Header: JWT dans HTTP Authorization header
  • Body: vide
Response

Structure

  • groups: array of objects => tous les groupes de votre installation domotique
    • group: object
      • id
      • name
    • subjects: array of objects => tous les éléments qui font partie de ce groupe
      • name
      • address
      • channel
      • type : voir liste des types possibles
      • tags
      • icons_id
      • dimmable: true or false
  • temp_calendars: array of objects => les calendriers définis pour les zones de température
    • id
    • name
  • audio_sources: object => les différentes sources audio par par zone
    • audio zone id: object
      • source id => source name

Exemple

{
    "groups": [
        {
            "group": {
                "id": 0,
                "name": "No group"
            },
            "subjects": [
                {
                    "name": "Input  1.10",
                    "address": "1",
                    "channel": "9",
                    "type": "1",
                    "tags": "1.10",
                    "icons_id": "100",
                    "dimmable": false
                }
            ]
        },
        {
            "group": {
                "id": "1",
                "name": "Rez-de-chaussée",
                "icons_id": "0",
                "color": null,
                "image": null,
                "weight": "0"
            },
            "subjects": [
                {
                    "name": "Salle-à-manger",
                    "address": "4",
                    "channel": "0",
                    "type": "16",
                    "tags": "4.1",
                    "icons_id": "0",
                    "dimmable": true
                },
                {
                    "name": "Salon",
                    "address": "4",
                    "channel": "1",
                    "type": "16",
                    "tags": "4.2",
                    "icons_id": "0",
                    "dimmable": true
                }
            ]
        },
        {
            "group": {
                "id": 201,
                "name": "Scenarios"
            },
            "subjects": [
                {
                    "name": "Panique",
                    "address": 201,
                    "channel": "2",
                    "type": 201,
                    "tags": "2",
                    "icons_id": 201,
                    "dimmable": false
                },
                {
                    "name": "OFF général",
                    "address": 201,
                    "channel": "1",
                    "type": 201,
                    "tags": "1",
                    "icons_id": 201,
                    "dimmable": false
                }
            ]
        },
        {
            "group": {
                "id": 202,
                "name": "Automations"
            },
            "subjects": [
                {
                    "name": "Absence",
                    "address": 202,
                    "channel": "2",
                    "type": 202,
                    "tags": "2",
                    "icons_id": 202,
                    "dimmable": false
                },
                {
                    "name": "Stores",
                    "address": 202,
                    "channel": "3",
                    "type": 202,
                    "tags": "3",
                    "icons_id": 202,
                    "dimmable": false
                }
            ]
        },
        {
            "group": {
                "id": 203,
                "name": "Logical conditions"
            },
            "subjects": [
                {
                    "name": "Absence de la maison",
                    "address": 203,
                    "channel": "1",
                    "type": 203,
                    "tags": "1",
                    "icons_id": 203,
                    "dimmable": false
                },
                {
                    "name": "Obscurité extérieure",
                    "address": 203,
                    "channel": "2",
                    "type": 203,
                    "tags": "2",
                    "icons_id": 203,
                    "dimmable": false
                }
            ]
        },
        {
            "group": {
                "id": 204,
                "name": "Temperature"
            },
            "subjects": [
                {
                    "name": "All zones",
                    "address": 204,
                    "channel": 255,
                    "type": 204,
                    "tags": "*",
                    "icons_id": 204
                },
                {
                    "name": "Salle-de-bain",
                    "address": 204,
                    "channel": "4",
                    "type": 204,
                    "tags": "4",
                    "icons_id": 204,
                    "dimmable": false
                },
                {
                    "name": "Salon",
                    "address": 204,
                    "channel": "3",
                    "type": 204,
                    "tags": "3",
                    "icons_id": 204,
                    "dimmable": false
                }
            ]
        },
        {
            "group": {
                "id": 205,
                "name": "Audio"
            },
            "subjects": [
                {
                    "name": "Cuisine",
                    "address": 205,
                    "channel": "4",
                    "type": 205,
                    "tags": "4",
                    "icons_id": 205,
                    "dimmable": false
                },
                {
                    "name": "Salon",
                    "address": 205,
                    "channel": "3",
                    "type": 205,
                    "tags": "3",
                    "icons_id": 205,
                    "dimmable": false
                }
            ]
        },
        {
            "group": {
                "id": 206,
                "name": "Flags"
            },
            "subjects": [
                {
                    "name": "Alarme",
                    "address": 206,
                    "channel": "2",
                    "type": 206,
                    "tags": "2",
                    "icons_id": 206,
                    "dimmable": false
                }
            ]
        }
    ],
    "temp_calendars": [
        {
            "id": "1",
            "enabled": null,
            "name": "Présence",
            "created": "2007-01-01 02:41:59"
        },
        {
            "id": "2",
            "enabled": null,
            "name": "Minimum",
            "created": "2007-01-06 01:39:05"
        }
    ],
    "audio_sources": {
        "4": {
            "1": "Radio Contact",
            "2": "Vivacité"
        },
        "3": {
            "1": "Radio Contact",
            "2": "Vivacité"
        }
    }
}
GET /api/local/status

Renvoie le statut de l'ensemble du système, d'un module ou d'une sortie.

Request
  • Header: JWT dans HTTP Authorization header
  • Body: vide ou un objet Json avec le module ou la sortie dont l'état est demandé.
{
     "address"   : OPTIONNEL, adresse du module ou de l´action du NXT (>200),
     "channel"   : OPTIONNEL, sortie du module (commence à 0) ou sortie du NXT (commence à 1)
}
Response

Structure

Le statut demandé sous forme de matrice (voir API Websockets) ou de valeur (si l'adresse et le canal sont envoyés).

POST /api/local/action

Exécute une action dans votre installation DOBISS en postant l'action sous forme d'objet Json dans le corps de votre requête.

Request
  • Header: JWT dans HTTP Authorization header
  • Body: objet Json avec l'action qui doit être exécutée
{
     "address"   : OBLIGATOIRE, adresse du module ou de l´action du NXT (>200),
     "channel"   : OBLIGATOIRE, sortie du module (commence à 0) ou sortie du NXT (commence à 1),
     "action"    : OBLIGATOIRE, id action (0 = OFF, 1 = ON, 2 = inversion) // voir liste d'actions
     "option1"   : dimmer: valeur (0-100) / audio: volume (0-100) / température: définir une température (0 = 5.0°C - 250 = 30.0°C) ou calendrier (ID)
     "option2"   : dimmer: soft start/stop (0-254) / audio: source / température: période (0xFE = permanent / 0 = jusque la prochaine période / X = X x 15 minutes)
     "delayon"   : 
     	{
     	   "value" : 0..120	,	1..90	,	120/150/180..900	,	960/720/780..1440
           "unit"  : "s"	, 	"min"	,	"min"				,	"min"
        }
     "delayoff"  :
        {
           "value" : 0..120	,	1..90	,	120/150/180..900	,	960/720/780..1440
           "unit"  : "s"	, 	"min"	,	"min"				,	"min"
        }
     "condition" : 
        {   
           "id"    : ID de la condition logique qui doit être vérifiée pour l´exécution,
           "operator": 'true' or 'false'
     }
}
Response

Statut de l'élément après l'exécution de l'action (si l'action est retardée, cet état sera incorrect).

{
    "new_status": 0
}

API Websockets

Une fois connecté à l'API Websockets, les mises-à-jour de statut en temps réel sont envoyées à tous les clients connectés (push).
Structure

Le statut se compose de 2 parties:

1. Statut de tous les modules de sorties connectés (relais, dimmers, etc...)

Une matrice avec le statut de chaque canal par module.

{
  "2":[0,0,0,0,0,0,0,0,0,0,0,0],
  "3":[0,0,0,0,0,0,0,0,0,0,0,0]
}

2. Statut de tous les éléments du NXT (températures, audio, drapeaux, etc...)

Un objet avec comme "key" le canal et comme "value" le statut de cet élément (cela peut être un nombre ou un objet.

{
  "202":{"2":"0","3":"1","8":"1","5":"1","4":"0","7":"0","9":"0","1":"1","6":"0","10":"0"},
  "0":{"0":255,"1":255,"2":255,"10":0,"11":0,"12":0,"13":0,"14":0,"15":0,"16":0,"17":0,"18":0,"19":0,"20":0,"21":0,"22":0,"23":0,"30":0},
  "205":{
    "1":{"status":0,"volume":13,"source":0,"extra":"","system":"sonos"},
    "2":{"status":0,"volume":29,"source":3,"extra":"","system":"sonos"}
  },
  "204":{
    "4":{"status":0,"temp":"25.9","asked":"15.0","time":-30,"calendar":"2","cooling_status":null,"cooling_asked":null,"cooling_time":null},
    "3":{"status":0,"temp":"26.7","asked":"15.0","time":-30,"calendar":"2","cooling_status":null,"cooling_asked":null,"cooling_time":null}
  },
  "206":{"1":"0","2":0,"3":"0","4":0,"5":"0","6":"0","7":"0","8":"0","9":"0","10":"0","11":"0","12":"0"}
}

Parfois, ces deux parties sont transmises ensemble, mais le plus souvent elles sont envoyées séparément.

Listes

Subject types
0 Serveur NXT DO5520
1 Module d'entrée universel DO5480
4 Module DALI DO5460
8 Module relais DO5411 / DO5475
16 Module dimmer universel 230VAC DO5450
24 Module 0-10V/1-10V DO5470
     
201 Scénarios  
202 Programmations  
203 Conditions logiques  
204 Température  
205 Audio  
206 Drapeaux  
207 Pilotage RGB(W)  
208 Notifications  
Actions
0

OFF

1 ON
2 Inversion ON/OFF
3 Début du dimming
4 Fin du dimming
5 Clignotement et ON (delayOn = fréquence / delayOff = durée totale)
6 Clignotement et OFF (delayOn = fréquence / delayOff = durée totale)
7 Clignotement et état de départ (delayOn = fréquence / delayOff = durée totale)
8 -
9 ON via détecteur
10 On en millisecondes
104 Source suivante (uniquement pour audio)
110 Choix d'un calendrier (uniquement pour température)