Mes passions, le boulots, mes coups de gueule...




TP-Link Cloud API : Contrôle d’une ampoule LB120

Catégories : Domotique, Geek, Informatique, Linux, Mac, Raspberry Pi · par 31 Déc 2017

Introduction

La lampe

Pour la Noël, j’ai reçu une ampoule TP-Link LB120. C’est une lampe autonome qui incorpore une connexion Wi-Fi et qui ne nécessite pas de bridge comme la majorité de la gamme Philips Hue par exemple.

On la trouve sur Amazon à un prix qui oscille entre 30€ et 35€.

Les projets

Il existe différents projets sur GitHub (et sans doute ailleurs) qui permettent de prendre le contrôle sur la lampe grâce à du JavaScript, du Python ou autre… Et ce, sur le réseau local en s’adressant directement à la lampe ou en en passant par l’API de TP-Link Cloud.

  • tplink-lightbulb : Ce projet permet de contrôler les périphériques « smart-home » TP-Link à partir de nodejs ou en ligne de commande.
  • tplink-cloud-api : Ce module node.js npm permet de contrôler à distance les « smartplugs » TP-Link (HS100, HS110) et « smartbulbs » (LB100, LB110, LB120, LB130) à l’aide de leur « cloud web service » (sans avoir besoin d’être sur le même wifi/lan).

TP-Link Cloud API

Local ou Cloud API ?

Local

Il n’est pas aisé de communiquer directement avec la lampe sur le réseau local.

Ce dépôt GitHub consacré à la prise Wi-Fi TP-Link HS100 en explique les raisons de manière détaillée :

Le TP-Link HS100 (et la famille apparentée) est une prise Wi-Fi intelligente. Par défaut, elle se connecte au service Kasa par lequel elle est géré à distance. Cependant, elle dispose d’une interface locale non documentée sur le port 9999, XOR-obfuscated JSON, mais qui est autrement complètement ouverte.

Cet objet intelligent ne permet pas la communication TCP directe sur le LAN local, mais permet une communication HTTP sur ce LAN. Nous utiliserons donc un proxy HTTP pour lui parler. Ce proxy LAN local permet d’envoyer des POST JSON au service et de recevoir des réponses JSON, avec lesquelles le gestionnaire de périphériques peut travailler.

Cloud API

Avec l’API du Cloud de TP-Link, il est plus facile de communiquer avec la lampe. Pour ce faire, nous enverrons une requête avec un POST dans une commande cURL vers le serveur https://eu-wap.tplinkcloud.com. Pour l’anecdote, il s’agit d’un serveur Amazon AWS à Dublin.

Une fois la requête acceptée, le serveur TP-Link envoie un ordre à la lampe.

cURL

Token & Device ID

Token

Avant de pouvoir nous lancer et communiquer avec le serveur, nous allons récupérer un TOKEN en fournissant l’adresse mail (login) et le mot de passe qui ont servi à nous enregistrer sur l’application mobile « Kasa » ou sur le site web https://www.tplinkcloud.com/ :

$ curl --silent --request POST "https://eu-wap.tplinkcloud.com/ HTTP/1.1" --data '{ "method": "login", "params": { "appType": "Kasa_Android", "cloudUserName": "MonAdresseMail", "cloudPassword": "MonPassword", "terminalUUID": "" } }' --header "Content-Type: application/json"

EDIT 25/09/2021

De puis quelques jours, le requête cURL requiert une valeur dans le champ terminalUUID.

Vous pouvez en générer une aléatoirement via ce site : https://www.uuidgenerator.net/version4

Nous aurons donc une ligne similaire à ceci :

$ curl --silent --request POST "https://eu-wap.tplinkcloud.com/ HTTP/1.1" --data '{ "method": "login", "params": { "appType": "Kasa_Android", "cloudUserName": "MonAdresseMail", "cloudPassword": "MonPassword", "terminalUUID": "MonTerminalUUID" } }' --header "Content-Type: application/json"

Référence :


Vous devriez obtenir ce genre de réponse :

{"error_code":0,"result":{"regTime":"2017-12-21 03:05:33","email":"monmail@mondomaine.tld","token":"xxxxxxxx-xxxxxxxxxxxxxxxxxxxxxxx"}}

Device ID

Pour pouvoir s’adresser au bon objet (si vous avez plusieur lampes et/ou prises intelligentes), nous aurons besoin de son identifiant. Pour l’obtenir, nous utiliserons la même commande cURL, mais avec ces données et en remplaçant les xxxxx par le token obtenu à l’étape précédente :

curl --silent --request POST "https://wap.tplinkcloud.com?token=xxxxxxxx-xxxxxxxxxxxxxxxxxxxxxxx HTTP/1.1" --data '{"method":"getDeviceList"}' --header "Content-Type: application/json"

Vous devriez obtenir ce genre de réponse :

{"error_code":0,"result":{"deviceList":[{"fwVer":"1.6.0 Build 170703 Rel.141938","deviceName":"Smart Wi-Fi LED Bulb with Tunable White Light","status":1,"alias":"Mon ampoule intelligente","deviceType":"IOT.SMARTBULB","appServerUrl":"https://eu-wap.tplinkcloud.com","deviceModel":"LB120(EU)","deviceMac":"xxxxxxxxxxxx","role":0,"isSameRegion":true,"hwId":"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx","fwId":"00000000000000000000000000000000","oemId":"F6A0ACBBD7B8B723AE1E32C273ACB5CE","deviceId":"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx","deviceHwVer":"1.0"}]}}

L’identifiant de l’objet (DeviceID) se situe vers la fin de la ligne.

Script

Voici un petit script en BASH pour obtenir ces deux infos :

#!/bin/bash

Login="monmail@mondomaine.tld"
CloudPsw="MonPassword"

# On demande le TOKEN à partir du login et du password enregistré avec l'App Kasa
# --silent : Pour éviter la barre de progression.
CurlResult=$(curl --silent --request POST "https://eu-wap.tplinkcloud.com/ HTTP/1.1" \
--data '{ "method": "login", "params": { "appType": "Kasa_Android", "cloudUserName": '$Login', "cloudPassword": '$CloudPsw', "terminalUUID": "" } }' \
--header "Content-Type: application/json")

#echo Réponse Curl complète : $CurlResult

# On découpe la réponse pour ne grader de le TOKEN
# Coupe après le 15ème "
Token=$(echo $CurlResult | cut -d \" -f 16)
echo Token : $Token

# On demande la liste des Devices
CurlResult=$(curl --silent --request POST "https://wap.tplinkcloud.com?token=$Token HTTP/1.1" \
--data '{"method":"getDeviceList"}' \
--header "Content-Type: application/json")

#echo Réponse Curl complète : $CurlResult

# On découpe la réponse pour ne grader de le DeviceID
# Coupe après le 55ème "
DeviceID=$(echo $CurlResult | cut -d \" -f 56)
echo<span style="display: inline-block; width: 0px; overflow: hidden; line-height: 0;" data-mce-type="bookmark" class="mce_SELRES_start"></span> Device ID : $DeviceID

Vous pouvez télécharger ce script en cliquant sur ce lien.

Pour le rendre exécutable :

chmod +x Token+DeviceID_Request.sh

Et pour l’exécuter :

./Token+DeviceID_Request.sh

La réponse devrait ressembler à ceci :

Token : xxxxxxxx-xxxxxxxxxxxxxxxxxxxxxxx
Device ID : xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

Action

Détail du data

Pour passer les données par la commande cURL, voici les données que nous devrons envoyer :

curl --silent --request POST "https://eu-wap.tplinkcloud.com/?token=$Token HTTP/1.1" \
 --data '{"method":"passthrough", "params": {
     "deviceId": '$DeviceID', "requestData": "{
         \"smartlife.iot.smartbulb.lightingservice\":{
             \"transition_light_state\":{
                 \"on_off\":'$LightState',
                 \"transition_period\":'$TransitionPeriod',
                 \"mode\":\"normal\",
                 \"hue\":$Hue,
                 \"saturation\":$Saturation,
                 \"color_temp\":'$ColorTemp',
                 \"brightness\":'$Brightness'
                 }
             }
         }"
     }
 }' \
 --header "Content-Type: application/json"

J’ai introduit quelques variables (en couleur) qui seront utilisées dans le script ci-dessous :

$Token              # xxxxxxxx-xxxxxxxxxxxxxxxxxxxxxxx
$DeviceID           # xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

$LightState         # 1 = ON / 0 = OFF
$TransitionPeriod   # Durée de transition en ms
$Brightness         # Intensité limineuse en % : min = 1 / max = 100
$ColorTemp          # Température de couleur en Kelvin : min = 2700 / max = 6500

$Hue et $Saturation ne seront utilisés qu’avec la lampe TP-Link LB130 qui gère la trichromie.

J’ignore à quoi sert le paramettre mode. Peut-être une sélection entre « normal » et « preset »… Si vous le savez, indiquez-le dans les commentaires.

Script

Voici un petit script qui vous demandera d’introduire chaque valeur à assigner à la lampe :

#!/bin/bash

Token=xxxxxxxx-xxxxxxxxxxxxxxxxxxxxxxx
DeviceID=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

echo Token : $Token
echo Device ID : $DeviceID
echo

read -p "Etat ? 1=ON 0=OFF : " LightState
read -p "Intensité ? Min=1 Max=100 : " Brightness
read -p "T. de couleur en K ? Min=2700 Max=6500 : " ColorTemp
read -p "T. de transfert en ms ? : " TransitionPeriod

CurlResult=$(curl --silent --request POST "https://eu-wap.tplinkcloud.com/?token=$Token HTTP/1.1" \
 --data '{"method":"passthrough", "params": {"deviceId": '$DeviceID', "requestData": "{\"smartlife.iot.smartbulb.lightingservice\":{\"transition_light_state\":{\"on_off\":'$LightState',\"transition_period\":'$TransitionPeriod',\"mode\":\"normal\",\"hue\":0,\"saturation\":0,\"color_temp\":'$ColorTemp',\"brightness\":'$Brightness'}}}" }}' \
 --header "Content-Type: application/json")

Vous pouvez télécharger ce script en cliquant sur ce lien.

Pour le rendre exécutable :

chmod +x tpl-lb.sh

Et pour l’exécuter :

./tpl-lb.sh

Voilà, la lampe devrait maintenant répondre à vos commandes au clavier… 🙂

Références :

(3) comments

jvunc
3 ans ago · Répondre

bonjour
c’est très intéressant.
j’ai pu récupérer le token et afficher les device id.
comme j’ai des smartplug HS110, comment on fait pour récupérer les mesures ?

Laisser un commentaire

Ce site utilise Akismet pour réduire les indésirables. En savoir plus sur comment les données de vos commentaires sont utilisées.