Home assistant est en mesure de créer une entité pour à peu près tout ce qu'on veut.
Une entité, c'est un peu comme un objet, unique, qu'on différencie des autres entités par un identifiant.
Il y a des entités possibles pour tout.
Par exemple, une lumière, un ventilateur, un moteur de volet roulant, une prise éléctrique... tout ça est enregistré dans Home Assistant sous forme d'une entité pour chacun.
En modifiant la valeur de cette entité, on agit sur l'objet qui lui est lié: allumer une lumière, changer sa couleur, son intensité, baisser ou relever un volet roulant, allumer ou éteindre une prise.
Certaines entités ne sont pas faites pour être contrôlées. Elles contiennent une information, que l'on peut lire.
Par exemple, une sonde de température est liée à une entité. On peut lire cette entité, mais pas la modifier. C'est Home Assistant qui la modifie lorsqu'il récupère la température relevée par la sonde.
On pourrait vulgairement dire que Home Assistant est orienté objet. On peut définir des scripts ou des automatismes en fonction de l'était de ces objets.
Et ces objets, ce sont les entités.
Alors pourquoi je vous parle de ça ? Et bien parce qu'il existe de nombreuses autres façons de récupérer l'état d'un capteur ou d'un appareil, et d'influer dessus. Et parmi les méthodes possibles, il y a le MQTT.
Et bien que Home Assistant pourrait tout à fait se passer du MQTT, puisqu'il sait gérer lui même ses entités, il l'intègre néanmoins.
La raison est simple: bien que le MQTT ne soit pas à l'origine du tout prévu pour la domotique, ce protocole s'impose désormais comme un incontournable dans le domaine.
Et avant de se demander quelles sont les différences entre les entités de Home Assistant et le MQTT, la première question serait: c'est quoi le MQTT ?

Alors, c'est quoi le MQTT ?
Message Queuing Telemetry Transport
A l'origine crée par des ingénieurs pour l'industrie pétrolière, ce protocole de communication est conçu pour échanger des informations très rapidement, efficacement, et avec une consommation de bande passante très réduite.
Tout est hiérarchisé en MQTT.
Un serveur (qu'on appelle Broker) possède des fils (appelés topic).
Voyez ça comme des "sujets de conversation".
Un topic peut comporter plusieurs sections, et des des sous-sections.
Un appareil peut s'abonner à l'un de ces topics, ou bien à plusieurs.
Il peut lire ou, s'il en a les droits, mettre à jour les informations des topics auxquels il est abonné.
Vous êtes libre de hiérarchiser vos topics et leurs contenus à votre guise.
Le MQTT au sein de River Island
Lorsqu'un sujet est mis à jour, tous ceux qui y sont abonnés peuvent être informés.
Voici l'organisation que j'ai mis en place sur le serveur principal de River Island:
- Paramètres système
- Gestion du mode d'exploitation
- Gestion de la maintenance
- Attraction 1
- Moteur
- Vitesse de rotation
- Lumières
- Moteur
- Attraction 2
- Moteur
- Vitesse de rotation
- Lumières
- Moteur
Et voici concrètement l'arborescence:
Toutes les attractions sont hiérarchiquement similaires.
- Le topic principal porte le nom de l'attraction. Il indique si l'attraction est ouverte, fermée ou en maintenance.
- Une sous-section 'lights' renseigne sur l'état des lumières: allumées, éteintes ou en animation
- Une autre sous-section 'engine' renseigne sur le sens de rotation du moteur de l'attraction: horaire (CW) ou anti horaire (CCW).
- Enfin, une sous-sous-section de la partie 'engine', 'speed' renseigne sur la vitesse de rotation du moteur (de 0 à 100%).
Bien que ces topics soient portés par Home Assistant, puisqu'il est le broker, ils sont majoritairement mis à jour par la console de commande.
Etant donné que l'écran principal donne la possibilité de contrôler toute la maquette, les topics sont mis à jour au fur et à mesure par lui.
Selon l'appareil, l'action se produit directement sur lui, ou bien lance un script sur Home Assistant, ou bien encore dans l'ESP directement.
Un exemple parlant est celui du mode manuel.
Le code du mode manuel se trouve dans l'ESP qui gère l'écran principal.
Dans le mode manuel, un menu déroulant permet de sélectionner l'attraction.
Une fois l'attraction sélectionnée, on en obtient le contrôle total. Moteur, vitesse, sens de rotation, lumières, état de l'attraction...
Par conséquent, le programme doit pouvoir accéder à tous les topics, mais également tous les modifier.
Le mode manuel est à lui seul une sorte de programme dans le programme.
Ses 300 lignes contrôlent tout, et obtient en même temps les informations de toutes les attractions, en MQTT.
En voici les grandes lignes.
Je définit d'abord quelques variables, avec des valeurs par défaut:
globals:
- id: manual_mqtt_topic_selection
type: std::string
restore_value: no
initial_value: '"home/attractions/ferris_wheel"'
- id: manual_mqtt_topic_selection_light
type: std::string
restore_value: no
initial_value: '"home/attractions/ferris_wheel/lights"'
- id: manual_mqtt_topic_selection_engine
type: std::string
restore_value: no
initial_value: '"home/attractions/ferris_wheel/engine"'
- id: manual_mqtt_topic_selection_engine_speed
type: std::string
restore_value: no
initial_value: '"home/attractions/ferris_wheel/engine/speed"'
Elles portent les valeurs par défaut des topics de la première attraction du menu déroulant, la Grande Roue.
Dans les valeurs de ces variables, on retrouve bien la structure des topics que j'ai présenté plus haut.
Ensuite vient le code en lui même.
Voici par exemple la section qui affiche le menu déroulant. J'utilise LVGL pour les affichages:
lvgl:
touchscreens:
- touch
displays:
- my_display
theme:
button:
border_width: 2
border_color: 0xFFFFFF
bg_color: 0x278EDA
radius: 5
checkable: false
label:
text_color: 0x000000
text_font: helvetica_20
buffer_size: 25%
pages:
# Page de controle manuel
- id: manuel
bg_color: 0x000000
opa: COVER
bg_opa: COVER
border_width: 2
border_color: 0xFFFFFF
radius: 7
widgets:
- obj:
bg_color: 0x000000
height: 100%
width: 100%
y: 0
bg_opa: COVER
opa: COVER
border_width: 0
widgets:
- dropdown:
x: 100
y: 5
width: 310
id: dropdown_attraction_selection
dir: TOP
options:
- Grande Roue
- Pieuvre
- Chaises volantes
- Auto Tamponneuses
- Flipper
- Top Spin
- Chenille
selected_index: 0
on_value:
- logger.log:
format: "Selected index is: %d"
args: [ x ]
- script.execute: attraction_selection
Le menu déroulant renvoie une valeur numérique: la position de l'élément sélectionné.
Dans notre cas, nous avons donc:
Ne reste qu'à définir la valeur des variables qu'on a crée au préalable, selon le choix fait dans le menu déroulant.
Ensuite, tous les autres éléments du mode manuel appelleront ces variables.
script:
- id: attraction_selection
then:
- lambda: |-
int selected_value = lv_dropdown_get_selected(id(dropdown_attraction_selection));
ESP_LOGD("dropdown", "Selected value: %d", selected_value);
if (selected_value == 0) {
id(manual_mqtt_topic_selection) = "home/attractions/ferris_wheel";
id(manual_mqtt_topic_selection_light) = "home/attractions/ferris_wheel/lights";
id(manual_mqtt_topic_selection_engine) = "home/attractions/ferris_wheel/engine";
id(manual_mqtt_topic_selection_engine_speed) = "home/attractions/ferris_wheel/engine/speed";
}
if (selected_value == 1) {
id(manual_mqtt_topic_selection) = "home/attractions/octopussy";
id(manual_mqtt_topic_selection_light) = "home/attractions/octopussy/lights";
id(manual_mqtt_topic_selection_engine) = "home/attractions/octopussy/engine";
id(manual_mqtt_topic_selection_engine_speed) = "home/attractions/octopussy/engine/speed";
}
if (selected_value == 2) {
id(manual_mqtt_topic_selection) = "home/attractions/flying_chairs";
id(manual_mqtt_topic_selection_light) = "home/attractions/flying_chairs/lights";
id(manual_mqtt_topic_selection_engine) = "home/attractions/flying_chairs/engine";
id(manual_mqtt_topic_selection_engine_speed) = "home/attractions/flying_chairs/engine/speed";
}
if (selected_value == 3) {
id(manual_mqtt_topic_selection) = "home/attractions/bumper_cars";
id(manual_mqtt_topic_selection_light) = "home/attractions/bumper_cars/lights";
id(manual_mqtt_topic_selection_engine) = "home/attractions/bumper_cars/engine";
id(manual_mqtt_topic_selection_engine_speed) = "home/attractions/bumper_cars/engine/speed";
}
if (selected_value == 4) {
id(manual_mqtt_topic_selection) = "home/attractions/flipper";
id(manual_mqtt_topic_selection_light) = "home/attractions/flipper/lights";
id(manual_mqtt_topic_selection_engine) = "home/attractions/flipper/engine";
id(manual_mqtt_topic_selection_engine_speed) = "home/attractions/flipper/engine/speed";
}
if (selected_value == 5) {
id(manual_mqtt_topic_selection) = "home/attractions/top_spin";
id(manual_mqtt_topic_selection_light) = "home/attractions/top_spin/lights";
id(manual_mqtt_topic_selection_engine) = "home/attractions/top_spin/engine";
id(manual_mqtt_topic_selection_engine_speed) = "home/attractions/top_spin/engine/speed";
}
if (selected_value == 6) {
id(manual_mqtt_topic_selection) = "home/attractions/jungle_train";
id(manual_mqtt_topic_selection_light) = "home/attractions/jungle_train/lights";
id(manual_mqtt_topic_selection_engine) = "home/attractions/jungle_train/engine";
id(manual_mqtt_topic_selection_engine_speed) = "home/attractions/jungle_train/engine/speed";
}
Ce code est largement perfectible.
Par exemple, on pourrait définir que
Mais mes connaissances sont encore trop faibles pour savoir la syntaxe pour cela. Mais ça fonctionne !
Avec cette portion de code fonctionnelle, le développement de l'interface graphique avance d'un grand pas.
Reste à configurer le mode autonome. Et c'est dans Home Assistant que ça se passera !












