Utiliser un produit, c'est bien. Apprendre à le contrôler, c'est mieux. Les Philips Hue sont un bon cas d'école, avec une API facilement accessible et demandant peu de compétences techniques pour en tirer parti.
Après être revenus sur la gamme de produits Hue de Signify (maison mère des luminaires Philips), sa constitution et les possibilités qu'elle offre, passons aux choses sérieuses : comment récupérer des informations sur votre installation et vos ampoules, puis les utiliser à distance en communicant avec le pont.
La société a mis en place une interface RESTful locale, qui permet d'effectuer des requêtes sans avoir à passer par une application spécifique. Un navigateur ou un simple terminal suffisent.
Notre dossier sur les ampoules Philips Hue :
- Retour sur la gamme Hue de Philips et quelques applications créées par la communauté
- Apprenez à utiliser l'API locale Philips Hue et à l'utiliser dans un premier script Python
- Utilisez Python et WSGI pour monter un serveur web local et gérer vos ampoules Hue (à venir)
Trouver l'IP du pont, utiliser l'API
Commençons par la gestion la plus manuelle et directe du pont. Une fois connecté à votre réseau local, la première étape est de trouver son adresse IP. Pour cela, une ligne de commande via cURL suffit, grâce à une URL spécifique.
Pour rappel, cet outil est intégré nativement à de nombreuses distributions Linux, et les versions récentes de Windows 10. Vous pouvez également le télécharger et l'installer :
curl https://discovery.meethue.com
Si vous vous rendez sur l'URL avec un navigateur, le résultat sera également affiché. Il se présente toujours cette forme :
[{"id":"ID_du_pont","internalipaddress":"IP_du_pont"}]
Si plusieurs ponts sont sur le même réseau, ils seront tous listés. Vous devrez donc identifier celui correspondant aux produits que vous voulez contrôler. Les ponts peuvent également être découverts via d'autres biais, comme les protocoles SSDP ou mDNS.
Une fois l'IP trouvée, vous pouvez accéder à l'interface web permettant d'effectuer des requêtes, l'API Debug Tool :
http://IP_du_pont/debug/clip.html
Il se compose de quatre sections : l'URL à utiliser pour la requête, la commande à envoyer, le contenu du message, le contenu de la réponse récupérée. On peut l'utiliser pour une première requête, affichant les informations relatives au pont. Pour cela, il suffit d'envoyer une requête via la commande GET sur l'URL /api/config
:

On récupère ainsi, au format JSON, le nom du pont, son adresse MAC, son ID, son modèle, les versions de l'API utilisée et du logiciel installé, un indicateur sur le fait qu'il soit neuf ou non, etc.
Notez que l'on aurait pu obtenir le même résultat en utilisant cURL via la ligne de commande suivante :
curl IP_du_pont/api/config
Récupérer et supprimer un jeton utilisateur
Passons maintenant au niveau supérieur. Car pour effectuer des requêtes, il faut être autorisé à le faire. Que ce soit pour gérer des ampoules ou obtenir des informations précises.
On utilise donc un jeton d'authentification (token) attribué par le pont après une phase d'appairage : l'username
. Une fois créé, il est ajouté à une liste blanche. Utilisé au sein d'une requête, il permet au pont de savoir qu'il peut répondre en toute sécurité. Bien entendu, il est possible de le révoquer en le retirant de la liste blanche si vous le jugez nécessaire.
Pour l'obtenir, il faut effectuer une requête POST sur l'URL /api
, en précisant le nom de l'appareil à enregistrer dans le message envoyé. Cela passe par un objet JSON assez simple, qui peut être par exemple :
{"devicetype":"my_hue_app#nom_de_l_appareil"}
Si vous voulez effectuer cette requête via curl, il faut utiliser commande suivante. Notez que sous Windows, des caractères d'échappement sont nécessaires (première ligne), mais pas sous Linux (deuxième ligne) :
curl -X POST -d {\"devicetype\":\"my_hue_app#davtest\"} IP_du_pont/api
curl -X POST -d '{"devicetype":"my_hue_app#davtest"}' IP_du_pont/api
Normalement, vous obtiendrez une erreur sous cette forme :
[{"error":{"type":101,"address":"","description":"link button not pressed"}}]
Le pont vous répond ainsi qu'il n'était pas en mode appairage, et qu'il faut tout d'abord presser son bouton. Une fois que cela est fait, envoyez à nouveau votre requête, vous obtiendrez alors votre jeton (username):
[{"success":{"username":"votre_jeton"}}]
Mettez cette information de côté (si possible dans un espace sécurisé pour éviter qu'un tiers puisse s'en servir). Créez ensuite un second jeton avec le nom d'appareil toDelete
après avoir à nouveau appuyé sur le bouton d'appairage :
{"devicetype":"my_hue_app#toDelete"}
Cela permet d'obtenir un second utilisateur que nous pourrons ensuite supprimer. Avant cela, nous allons afficher le contenu de la liste blanche, accessible dans la configuration du pont :
URL : /api/votre_jeton/config
Commande : GET
curl -X GET IP_du_pont/api/votre_jeton/config/
Comme vous êtes identifié, vous obtiendrez bien plus d'informations que précédemment, et notamment l'élément nommé whitelist
contenant tous les jetons créés, appareils associés, dates de création et de dernier usage.
Pour supprimer un jeton, là encore une requête suffit :
URL /api/votre_jeton/config/whitelist/jeton_a_supprimer
Commande : DELETE
curl -X DELETE IP_du_pont/api/votre_jeton/config/whitelist/jeton_a_supprimer
Si tout s'est bien passé, vous obtenez une réponse sous la forme :
[{"success":"/config/whitelist/jeton_a_supprimer deleted"}]
Lister et gérer vos ampoules
Maintenant que nous disposons d'un jeton, utilisons-le pour allumer et éteindre une ampoule. Tout d'abord, nous devons récupérer les informations les concernant, chacune étant identifiée par un nombre :
URL : /api/votre_jeton/lights
Commande : GET
curl -X GET IP_du_pont/api/votre_jeton/lights
Pour chaque ampoule vous obtenez différents éléments : name
, type
, state
, capabilities
, etc. Pour le moment, le seul élément qui compte est le nombre qui définit celle sur laquelle vous voulez effectuer votre test, la 6 dans notre cas.
Si l'on souhaite l'allumer, il faut exécuter la requête suivante :
URL : /api/votre_jeton/lights/ID/state
Commande : GET
Message : {"on":true}
curl -X PUT -d '{\"on\":true}' IP_du_pont/api/votre_jeton/lights/ID_de_la_lampe/state
Puis pour l'éteindre :
URL : /api/votre_jeton/lights/ID/state
Commande : PUT
Message : {"on":false}
curl -X PUT -d '{\"on\":false}' IP_du_pont/api/votre_jeton/lights/ID_de_la_lampe/state
Si tout se passe bien, le pont répond avec un message identique à ceux-ci :
[{"success":{"/lights/6/state/on":true}}]
[{"success":{"/lights/6/state/on":false}}]
Un premier script Python pour allumer/éteindre une lumière
Tâchons maintenant de rendre tout cela facilement exploitable avec un petit programme. Nous l'écrirons en Python pour le rendre utilisable sous Linux, macOS et Windows. S'il n'est pas installé sur votre système, vous pourrez trouver les fichiers nécessaires par ici :
Sous Windows, pensez à cocher la case Add Python.exe to Path dans la liste des éléments proposés. Il nous faut ensuite installer le module requests servant à exécuter des requêtes. Cela passe par une ligne de code que l'on peut taper dans un terminal une fois Python installé sur le système (pour certaines distributions Linux, le paquet python-pip sera à installer) :
pip install requests
Créez ensuite un fichier hue_manager.py
que vous ouvrirez avec votre éditeur préféré : Atom, Notepad++, Visual Studio Code, etc. Pour rappel, Python est un langage interprété, souvent utilisé pour des scripts, notamment parce qu'il dispose d'un écosystème complet et de nombreuses bibliothèques clé en main (comme requests dans notre exemple).
Il en existe d'ailleurs pour les Philips Hue, comme phue ou qhue. Pour ce petit programme, nous nous en passerons. Nous partons aussi du principe que vous avez déjà identifié l'IP de votre pont, le nombre de l'ampoule à utiliser et obtenu un jeton.
Nous allons tout d'abord réaliser un petit script permettant d'afficher l'URL pour la requête sur l'ensemble des lampes, puis celle pour la lampe que vous voulez gérer en particulier. Placez le code suivant dans hue_manager.py :
import requests
import json
bridge_ip = "IP_du_pont"
username = "votre_jeton"
light_number = "ID_de_la_lampe"
lights_url = "http://{}/api/{}/lights".format(bridge_ip, username)
light_state_url = "{}/{}/state".format(lights_url, light_number)
print lights_url
print light_state_url
On indique tout d'abord que l'on va utiliser les modules json
et requests
, puis on définit les variables utiles au bon fonctionnement de notre script sous forme de textes (ou string, d'où les guillemets). Pensez bien à les adapter selon votre configuration (IP, jeton, nombre de l'ampoule). Ensuite, nous composons les deux URL nécessaires avec la méthode str.format()
.
Celle-ci nous permet d'indiquer comment est composée l'URL puis de lister les variables à utiliser. Une fois ceci fait, nous affichons le résultat avec l'instruction print.
Pour exécuter le programme, tapez la commande suivante :
python hue_manager.py
Affichons maintenant le statut de nos différentes ampoules en ajoutant les lignes de code suivantes à notre script :
r = requests.get(lights_url)
for light in r.json():
light_current_status = "{} - {} : {}".format(light,
r.json()[light]["name"].encode("utf-8"),
r.json()[light]["state"]["on"])
print light_current_status
La première ligne exécute une requête simple sur l'URL permettant d'obtenir les informations sur les lumières. Nous récupérons ensuite le résultat au format JSON (r.json()
) pour l'utiliser dans une boucle. Le contenu de la boucle est décalé par rapport au reste du code, c'est la manière de faire de Python.
Pour chaque ampoule, nous affichons trois éléments : son nombre, son nom (.encode("utf-8")
permettant d'éviter les soucis avec les accents et caractères spéciaux), puis son statut (allumée ou non).
Enfin, si la lampe désignée est éteinte, nous l'allumons, ou inversement :
new_state = not r.json()[light_number]["state"]["on"]
message = json.dumps({"on": new_state})
action = requests.put(light_state_url, data=message)
print action.content
On récupère l'état inverse à celui de l'ampoule désignée au départ, puis on prépare le message pour la requête à envoyer. Celui-ci soit être converti de simple texte à un élément JSON (via json.dumps()
). La requête est ensuite envoyée. Nous affichons enfin son résultat.
Notez que Signify indique dans sa documentation que la phase de transition par défaut de ses ampoules est de 400 ms (elle peut être réduite à 0 ms ou allongée), et que la latence peut aller de 40 à 125 ms. Il faut donc veiller à ne pas trop envoyer de commandes. Au cas où vous auriez eu envie de jouer à « nuit... jour... nuit... jour... nuit... ».
Mais maintenant que vous avez accès à l'API et à sa documentation, la seule limite est votre imagination. Tentez donc de faire mieux (et publiez-en les sources). Celle de l'exercice du jour sont disponibles par ici.