Récupérer la température et l'hygrométrie de thermomètres Switch-Bot à l'aide de leur API+petit bonus

Hello,

Les thermomètres Switch-Bot ne pouvaient pas, par défaut, être intégrés dans Home-Assistant.
Désormais, l’intégration switch-bot native existe et permet d’utiliser les thermomètres en plus du premier appareil de cette marque, qui permet de connecter un interrupteur.
Elle permet maintenant d’utiliser une grande partie des appareils de la marque.

Cependant, il existe une API qui permet, entre autre, de consulter la température de ses thermomètres Switchbot.
Pour une installation de Home Assistant où le §Bluetooth n’est pas envisageable, c’est une alternative, bien que dépendante du cloud.
Il existe également une intégration permettant d’utiliser certains appareils via l’API, notemment les télécommandes.
Les thermomètres ne sont à ma connaissance et selon la documentation pas pris en charge par cette intégration utilisant l’API.

Prérequis

  • Avoir installé l’application de la marque
  • Avoir créé son compte
  • Avoir ajouté ses thermomètres
  • Possèder un Hub Switchbot comme le Hub mini
  • Avoir activé le mode cloud sur les thermomètres à intégrer, même si ça fonctionne peut-être sans ; la documentation n’est pas claire à ce sujet, pour ça aller dans les paramètres de chaque thermomètre puis aller dans le mode cloud
  • Avoir installé curl qui est déjà dispo sous Windows 10 et jq optionnel mais qui aide néanmoins à faciliter les choses pour récupérer les informations.

Récupération du token

Pour accéder à l’API, il faut connaître son jeton d’accès :
Dans l’application Switchbot, aller dans Profile→Paramètres→Developer options et notez le token affiché.

Récupération des identifiants des thermomètres

C’est là que ça devient barbu, tout se passe en ligne de commande.
Voici comment récupérer la liste de vos appareils (désolé pour les utilisateurs de Windows, je ne suis pas entièrement convaincu que ça passe en l’état) :
curl -H "Content-Type: application/json; charset=utf8" -H "Authorization: <token>" https://api.switch-bot.com/v1.0/devices | jq -r ".body.deviceList[] | \"ID : \"+.deviceId+\" ; Nom : \"+.deviceName+\" ; type : \"+.deviceType"
Penser à remplacer <token> par le token récupéré depuis l’application.

On récupère ainsi une liste présentée comme suit :
ID: <id> ; nom : <nom> ; type : <type>

Pour tous les éléments qui ont le type meter, on aura besoin du id pour les futures sensors.
Le nom nous permettra de savoir comment nommer chaque sensor.

Mise en place des sensors

Nous allons utiliser un ensemble de rest sensors pour tout récupérer d’un coup.
D’autres aproches sont possibles mais c’est celle que je trouve la plus directe.

Dans config.yaml, mettre ceci :

rest:
  - resource: "https://api.switch-bot.com/v1.0/devices/<id>/status"
    scan_interval: 60
    method: GET
    headers:
      Authorization: <token>
      Content-Type: "application/json; charset=utf8"
    sensor:
      - name: Thermomètre Bureau
        value_template: "{{ value_json.body.temperature if value_json.statusCode==100 else states('sensor.thermometre_bureau') }}"
        device_class: temperature
        unit_of_measurement: "°C"
        force_update: true # Peut-être superflu 

      - name: Hygromètre Bureau
        value_template: "{{ value_json.body.humidity if value_json.statusCode==100 else states('sensor.hygrometre_bureau') }}"
        device_class: humidity
        unit_of_measurement: "%"
        force_update: true # Peut-être superflu

Les valeurs retournées par l’API ne tiennent pas compte de l’étalonage qui aurait été fait dans l’application Switch-Bot.
Pour tenir compte de celui-ci, il faut refaire le calcul dans le sensor, par exemple pour ajouter 0.3 :

    sensor:
      - name: Thermomètre Bureau
        value_template: "{{ value_json.body.temperature+0.3 if value_json.statusCode==100 else states('sensor.thermometre_bureau') }}"
        device_class: temperature
        unit_of_measurement: "°C"
        force_update: true # Peut-être superflu 

La même chose est à faire dans le sensor hygromètre si l’hygrométrie est à étaloner.

Pensez à remplacer <token> par votre token API et <id> par l’identifiant du thermomètre.
Pour rajouter des thermomètres, il suffit de recopier toutes les lignes à partir de - resource: "https://api.switch-bot.com/v1.0/devices/<id>/status"

Le souci que j’ai eu avec cette méthode est qu’il n’est pas possible de placer les entités dans des pièces vu qu’on ne peut pas leur attribuer d’identifiant unique.

L’utilisation d’un rest sensor par thermomètre avec toutes les données en atributs et de deux template sensors un pour la température et l’autre pour l’hygrométrie basé sur l’état des attributs respectifs du rest sensor permettrait de placer les deux dernières entités dans une pièce.
Mais j’ai préféré l’approche pour laquelle j’ai mis la config pour avoir le moins d’entités possible.

atention !

Le nombre d’appels à l’API est limité à 10000 apels par jour et par token.

Pour la fin, Contrôle infrarouge

Depuis la rédaction de ce tuto, l’intégration Switch Bot cloud a été créée et permet de contrôler les télécommandes du Hub Switch Bot ainsi que d’autres appareils.
Seul les états allumé et éteint sont supportés, sauf pour les climatiseurs qui eux sont plus complets.
Avant de mettre les mains dans le YAML, une lecture de la documentation de cette intégration peut être judicieuse si cette intégration fait déjà ce don vous avez besoin.
Si vous avez rajouté des télécommandes, voici comment en contrôler.

On commence donc par récupérer la liste des appareils infrarouge enregistrés.
curl -H "Content-Type: application/json; charset=utf8" -H "Authorization: <token>" https://api.switch-bot.com/v1.0/devices | jq -r ".body.infraredDeviceList[] | \"ID : \"+.deviceId+\" ; Nom : \"+.deviceName+\" ; type : \"+.remoteType"

à l’aide d’une commande rest, on peut envoyer toute commande supportée :

rest_command:
  controler_barre_de_son:
    url: "https://api.switch-bot.com/v1.0/devices/<id>/commands"
    method: post
    content_type: "application/json; charset=utf8"
    headers:
      Authorization: <token>
    payload: '{"command": "{{ commande }}", "commandType": "{{ type_commande }}"}'

Ou <id> est à remplacer par l’identifiant de la télécommande et <token> par le token API.

Il est donc possible, avec une barre de son par exemple, de créer un switch pour l’allumer ou l’éteindre et de créer deux scripts : un pour augmenter le volume et l’autre pour le baisser :

switch:
  - platform: template
    switches:
      barre_de_son_salon:
        friendly_name: "Barre de Son Salon"
        unique_id: "switch.barre_de_son_salon"
        turn_on:
          service: rest_command.controler_barre_de_son
          data:
            commande: "turnOn"
            type_commande: ""
        turn_off:
          service: rest_command.controler_barre_de_son
          data:
            commande: "turnOff"
            type_commande: "command"

script:
  barre_son_volume_plus:
    alias: "Augmenter le volume de la barre de son"
    description: "Augmente le son de la barre de son"
    mode: queued
    sequence:
      - service: rest_command.controler_barre_de_son
        data:
          commande: "volumeAdd"
          type_commande: "command"

  barre_son_volume_moins:
    alias: "Diminuer le volume de la barre de son"
    description: "Diminue le son de la barre de son"
    mode: queued
    sequence:
      - service: rest_command.controler_barre_de_son
        data:
          commande: "volumeSub"
          type_commande: "command"

Un script serait suffisant pour allumer ou éteindre la barre de son mais on aimait trop la phrase de Google « j’éteint la barre de son salon » qu’on avait quand on utilisait l’intégration Switchbot pour Google Assistant.

Conclusion

Il est donc possible d’intégrer les thermomètres Switchbot à Home Assistant en utilisant autre chose que le Bluetooth, sachant que l’utilisation de l’API rend dépendant du cloud. Une lecture de la documentation de l’API permet de voir le champ d’action.
L’utilisation des télécommandes du hub ne peut pas se faire en utilisant le Bluetooth, par contre il est possible que l’intégration Switchbot Cloud permette d’utiliser certaines sans avoir à toucher au YAML.
Elle permet également de contrôler les Switchbot curtains mais n’ayant pas le produit, je préfère vous renvoyer à la documentation. De plus, ces derniers sont également contrôlables avec l’intégration native de Home Assistant, en Bluetooth.

J’espère que ce tutoriel aura été claire, compte tenu notamment de l’heure de sa rédaction :smiley: mais aussi du fait que la récupération des informations nécessaire n’est pas forcément aisée.

Changements

  • 11/11/2021 : la limite de 10000 demandes à l’API n’est dèsormais plus un secret
  • Ajout des modifications à faire si besoin d’étalonner la température ou l’hygrométrie, merci @NuM82
  • 09/03/2024 : modification de l’introduction pour spécifier que l’intégration native prend en charge les thermomètres, l’API est donc seulement une alternative
  • Mention de l’intégration Switchbot Cloud
3 « J'aime »

Bonjour,

Si vous avez étalonné vos « Switchbot Meter », les infos récupérés via l’API (et ce super tuto) ne sont pas corrigées.
Pour y remédier, remplacer :

pour un éalonnage de +0.3 par :

Vous pouvez également appliquer ce correctif pour la partie hydromètre.

1 « J'aime »

Merci, je ne savais pas que l’API ne tenait pas compte de la valeur étalonnée, je supposais que ce paramètre était directement envoyé aux meters qui appliquaient en suite le calcul n’ayant pas eu besoin d’étalonner mes thermomètres.
J’ai donc rajouté une petite note au tuto :slight_smile:

Pour info, les valeurs retournées via bluetooth sont les valeurs étalonnées.

ça par exemple, sachant que l’API a ses valeurs un moment donné par le bluetooth vu que c’est par le hub ou un smart phone vu que les meters ne communiquent pas directement avec les serveurs switchbot, voilà un phénomène étrange :wink:

Bonsoir ! Je découvre ce tuto super et ça marche du 1er coup ! Merci.

Pour information, et peut-être pour simplifier les prérequis, il semblerait que les ID des devices soient les MAC adress BLE que l’on peut obtenir facilement via les infos de chaque device sur l’application. Ca évite de faire des manipulations via curl et jd pour les non initiés.

Bonne soirée !

1 « J'aime »

Dommage qu’il n’y ait pas de méthode pour récupérer la valeur de leur batterie !

1 « J'aime »

Bonjour à tous ! Autre subtilité, pour obtenir le token, si le menu « developer » n’est pas présent, il faut cliquer plusieurs fois sur l’encart qui affiche le numéro de version. Cela déverrouillera le menu.
Bonne journée

2 « J'aime »

Par l’API non mais via BLE oui

1 « J'aime »

Bonjour et bonne année
Merci pour ce tuto, je l’ai suivi et j’ai mis l’adresse Ble comme mentionné mais mes entités affichent inconnu. Cela vient il de là ou il y a un autre soucis quelque part a votre avis ?
Merci d’avance pour vos réponses :slight_smile:

edit: problème résolu. Après avoir essayer de récupérer les id sous curl je me suis aperçu que j’avais mis les « : » entre chaque pair de lettre comme sur l’application alors qu’il ne fallait pas. si ça peut aider une autre personne.
encore merci pour le tuto !

1 « J'aime »

Bonjour, c’est encore moi :sweat_smile:

j’ai bien réussis à installer mes thermomètres tout fonctionne et j’ai voulu passer une télécommande que j’utilise avec le hub mini. j’ai suivi tout le tuto en mettant l’id du hub au lieu de la télécommande (adresse mac de l’application) avant de comprendre mon erreur.
J’ai donc toute l’installation de faite et je voulais simplement remplacer le mauvais id par le bon.
malheureusement quand je rentre dans le terminal le code pour récupérer les id des télécommande j’ai ce message d’erreur :


alors que pour les thermomètre je rentre le code est tout m’apparaît bien (j’ai même fais la manip de changer le infrareddevicelist par device list et ça fonctionne bien donc pas d’erreur dans le token et jq est bien installé.
une idée du soucis ?
Merci d’avance pour vos réponses !

Bonjour,
et comment récupérer le niveau de batterie de mes thermomètre switchbot ?

Dans la doc il est mentionné un attribut JSON battery mais je ne sais pas s’il est uniquement valable pour l’API v2 ou non et je ne peux pas tester, je n’utilise plus le hub.

Donc peut-être en faisant comme ça :

      - name: Thermomètre bureau batterie
        value_template: "{{ value_json.body.battery if value_json.statusCode==100 else states('sensor.thermometre_bureau_batterie') }}"
        device_class: battery
        unit_of_measurement: "%"
        force_update: true # Peut-être superflu

à tester du coup, je ne suis vraiment pas sûr que ça fonctionne avec l’API 1.0 que ce tuto utilise.

j’ai déjà essayé ça et voici le résultat:

Enregistreur: homeassistant.components.sensor
Source: helpers/entity_platform.py:576
intégration: Capteur (documentation, problèmes)
S'est produit pour la première fois: 8 mars 2024 à 18:44:37 (3 occurrences)
Dernier enregistrement: 8 mars 2024 à 18:44:37

Error adding entity sensor.switchbot_batterie_bureau for domain sensor with platform rest
Error adding entity sensor.switchbot_batterie_chambre_raph for domain sensor with platform rest
Error adding entity sensor.switchbot_batterie_garage for domain sensor with platform rest
Traceback (most recent call last):
  File "/usr/src/homeassistant/homeassistant/components/sensor/__init__.py", line 663, in state
    numerical_value = int(value)
                      ^^^^^^^^^^
ValueError: invalid literal for int() with base 10: ''

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/usr/src/homeassistant/homeassistant/components/sensor/__init__.py", line 666, in state
    numerical_value = float(value)
                      ^^^^^^^^^^^^
ValueError: could not convert string to float: ''

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/usr/src/homeassistant/homeassistant/helpers/entity_platform.py", line 576, in _async_add_entities
    await coro
  File "/usr/src/homeassistant/homeassistant/helpers/entity_platform.py", line 865, in _async_add_entity
    await entity.add_to_platform_finish()
  File "/usr/src/homeassistant/homeassistant/helpers/entity.py", line 1327, in add_to_platform_finish
    await self.async_added_to_hass()
  File "/usr/src/homeassistant/homeassistant/helpers/trigger_template_entity.py", line 161, in async_added_to_hass
    await super().async_added_to_hass()
  File "/usr/src/homeassistant/homeassistant/components/rest/entity.py", line 42, in async_added_to_hass
    self._update_from_rest_data()
  File "/usr/src/homeassistant/homeassistant/components/rest/sensor.py", line 180, in _update_from_rest_data
    self._process_manual_data(raw_value)
  File "/usr/src/homeassistant/homeassistant/helpers/trigger_template_entity.py", line 238, in _process_manual_data
    self.async_write_ha_state()
  File "/usr/src/homeassistant/homeassistant/helpers/entity.py", line 992, in async_write_ha_state
    self._async_write_ha_state()
  File "/usr/src/homeassistant/homeassistant/helpers/entity.py", line 1113, in _async_write_ha_state
    state, attr, capabilities, shadowed_attr = self.__async_calculate_state()
                                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/src/homeassistant/homeassistant/helpers/entity.py", line 1050, in __async_calculate_state
    state = self._stringify_state(available)
            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/src/homeassistant/homeassistant/helpers/entity.py", line 998, in _stringify_state
    if (state := self.state) is None:
                 ^^^^^^^^^^
  File "/usr/src/homeassistant/homeassistant/components/sensor/__init__.py", line 670, in state
    raise ValueError(
ValueError: Sensor sensor.switchbot_batterie_bureau has device class 'battery', state class 'None' unit '%' and suggested precision 'None' thus indicating it has a numeric value; however, it has the non-numeric value: '' (<class 'str'>)

Et si tu enlève la classe battery, quelle valeur a le sensor ?
ça pourrait permètre de comprendre ce qui ne va pas.

J’ai édité le post initial de ce sujet pour mentionner que l’intégration Switch Bot native permet d’utiliser les thermomètres, en Bluetooth.

En mise à jour, mention également de l’intégration Switch Bot Cloud qui utilise cette API et qui si elle ne permet pas d’récupérer l’état des thermomètres, permet de contrôler les télécommandes du Hub.

en supprimant la classe battery,
j’ai toujours la même erreur.

si je comprends bien la dernière ligne de cette erreur, il me dit qu’il attend une valeur numérique et qu’il obtient une valeur non numérique car elle est vide.
donc je pense que je ne pourrais pas avoir l’état de la batterie.
Domage

Autant pour moi, j’avais lu trop vite ce matin.
it has the non-numeric value: ''
Pas fait attention aux deux apostrophes.
Du coup il faut croire que malheureusement, ça ne fonctionne qu’avec l’API v2.
Peut-être que ça peut être réadapté, mais je ne m’y risquerais pas vu que je ne peux pas tester.

Après objectivement à moins de ne pas du tout pouvoir utiliser le Bluetooth, l’API n’est plus le moyen le plus simple pour intégrer des thermomètres Switch Bot. Du coup je ne sais pas si ça vaudrait le coup de te pencher sur une réadaptation à l’API v2 qui te permettrait hypothétiquement d’avoir la batterie.

Pourrais-tu m’en dire plus sur l’api v2 ou me dire ou je peux prendre des info stp

Pour commencer, hier n’était visiblement pas ma journée, parce que j’ai dit une petite bêtise.
Il s’agit de l’API 1.1, pas 2.0.
Cela dit, si j’avais relu la documentation, je l’aurais su :slight_smile:

Le processus d’authentification est plus complexe et l’hôte à renseigner est différent mais globalement, j’ai l’impression qu’elle s’utilise à peu près de la même manière.

La documentation de l’API est là où était celle de la 1.0 :