HA-Panneau de commande pour piscine avec un ESP32, OpenHASP et Home Assistant


Intro

Dans cet article, je vous présente un projet que j’ai adoré mettre en place : un panneau de commande tactile pour gérer ma piscine, basé sur un module ESP32 avec écran tactile, et utilisant OpenHASP pour l’interface graphique. Ce dispositif, connecté à Home Assistant, me permet de surveiller et de contrôler les paramètres de ma piscine (température, pH, ORP, filtration, etc.) depuis une interface intuitive. Je vais vous expliquer comment j’ai flashé l’ESP32, configuré OpenHASP avec un fichier JSONL, et créé une interface sur mesure, avec des captures d’écran pour illustrer le résultat !

Objectif du projet

L’objectif était de centraliser le contrôle de ma piscine sur un petit écran tactile, que je peux installer près de la piscine ou dans mon local technique. Ce panneau affiche des données en temps réel (température de l’eau, pH, pression du filtre, etc.) et me permet de contrôler des équipements comme la pompe de filtration ou le volet de la piscine. Le module ESP32 avec écran tactile est idéal pour ce projet : compact, abordable et compatible avec OpenHASP.

Matériel utilisé

  • Module ESP32 avec écran tactile : Un module ESP32 équipé d’un écran TFT tactile de 2,8 pouces (résolution 480×320 pixels). Ce modèle intègre un ESP32 et un écran tactile capacitif, parfait pour une interface utilisateur acheté sur AliExpress.
  • Câble USB-C : Pour l’alimentation
  • Un convertisseur USB<->Port série pour le flashage du firmware.
  • Une connexion WiFi pour intégrer le panneau à Home Assistant.

Flashage initial du module

Avant de pouvoir utiliser OpenHASP, il faut flasher le firmware sur le module ESP32.

Préparation du matériel :

  • Branchez le module ESP32 à votre ordinateur via le convertisseur USB-série. Il devrait être reconnu comme un port série (par exemple, /dev/ttyUSB0 sur Linux ou COM3 sur Windows).
  • Téléchargez et installez esptool.py, un outil pour flasher les ESP32. Vous pouvez l’installer via pip : pip install esptool.

    Téléchargement du firmware OpenHASP :

    • Rendez-vous sur le site officiel d’OpenHASP (Openhasp) et téléchargez le firmware correspondant à votre modèle d’écran. Pour mon module, j’ai choisi une version pour un ESP32 avec écran TFT 320×240.
    • Prendre le Firmware: panlee-zw3d95ce01s-tr-4848_16MB si vous avez acheté le même panel
    • Si votre écran n’est pas listé, vous devrez peut-être compiler le firmware vous-même en utilisant PlatformIO, en ajustant les paramètres de l’écran (résolution, pilote, etc.).

    Flashage du firmware :

    Afin d’utiliser ce module avec HA, nous devons flasher le panel via son port série.

    Il faut connecter le module au port USB d’un PC avec ce type de module., c’est un convertisseur USB<->Port série.

    Vous devez le brancher à votre carte selon le mapping suivant (utilisation des câbles Dupont):

    • Carte relais (connecteur 20 broches femelles)<-> Convertisseur
      • GND <-> GND
      • Tx <-> Rx
      • Rx <-> Tx
      • 3.3 V <-> Vcc
    • Nota 1: Sur le panel, Il faut ponter les broches GND et I00 (uniquement pour ce premier flashage)
    • Nota 2: Sur le convertisseur, positionner un cavalier sur le 3.3V.
    • Ouvrez un terminal et exécutez la commande suivante pour flasher le firmware (remplacez /dev/ttyUSB0 par votre port série et path-to-your-firmware/panlee-zw3d95ce01s-ar-4848_ota_v0.7.0-rc8_f28627c.bin par le chemin de votre fichier firmware) :
    esptool.py --port /dev/xxx write_flash 0x0 '/path-to-your-firmware/panlee-zw3d95ce01s-ar-4848_ota_v0.7.0-rc8_f28627c.bin' 
    • Une fois le flashage terminé, l’écran affiche une interface par défaut avec un message de bienvenue d’OpenHASP

    Vous trouverez des explications complémentaires en suivant ce lien

    Configuration initiale :

    • OpenHASP crée un point d’accès WiFi temporaire (SSID : HASP_XXXX). Connectez-vous à ce réseau avec votre téléphone ou ordinateur.
    • Accédez à l’interface web d’OpenHASP via l’adresse 192.168.4.1. Depuis cette interface, configurez les identifiants de votre réseau WiFi pour connecter le module à votre réseau local.
    • Notez l’adresse IP attribuée au module (par exemple, 192.168.0.xxx), car vous en aurez besoin pour la configuration.

    Ecran de configuration du Module

    En saisissant l’adresse IP du du module vous arrivez sur l’interface web OpenHASP.

    Fonctionnalités de l’interface web OpenHASP

    En plus de l’intégration dans Home Assistant, OpenHASP propose une interface web accessible via l’adresse IP du module (par exemple, http://192.168.0.xxx). Cette interface, disponible pour mon appareil ecran01, offre un ensemble d’outils pratiques pour gérer le panneau, personnaliser son interface graphique, et effectuer des tâches de maintenance. Voici un aperçu des fonctionnalités disponibles, illustré par une capture d’écran de cette interface.

    Aperçu des options de l’interface web

    L’interface web d’OpenHASP, visible dans la capture d’écran, propose plusieurs sections, chacune offrant des fonctionnalités spécifiques pour gérer le panneau :

    • HASP Design : Cette section permet de configurer les paramètres d’affichage et d’interface du panneau. Comme montré dans la capture, elle inclut plusieurs options :
      • UI Theme : Permet de sélectionner un thème d’interface (par exemple, “Hasp Light” dans la capture). Cela change l’apparence générale de l’interface graphique.
      • Primary Color et Secondary Color : Définit les couleurs principales et secondaires utilisées dans l’interface (bleu et orange dans la capture). Ces couleurs peuvent être ajustées pour correspondre à vos préférences esthétiques.
      • Default Font : Permet de choisir une police par défaut pour les textes affichés (ici, “None” est sélectionné, ce qui utilise la police par défaut d’OpenHASP).
      • Start Layout : Indique le fichier de configuration chargé au démarrage (dans mon cas, /pages.jsonl, qui correspond au fichier JSONL que j’ai utilisé pour définir l’interface graphique).
      • Startup Page : Définit la page affichée au démarrage (page 1 dans la capture, correspondant à la page “Piscine”).
      • Startup Dim : Ajuste la luminosité initiale de l’écran au démarrage (255 dans la capture, soit la luminosité maximale).
      • Save Settings : Un bouton pour enregistrer les modifications apportées dans cette section. Ces paramètres permettent de personnaliser l’apparence et le comportement initial du panneau sans modifier directement le fichier JSONL.
    • Screenshot : Cette fonctionnalité permet de capturer une image de l’écran actuel du panneau. C’est particulièrement utile pour documenter l’interface ou partager des aperçus de l’affichage, comme les captures de la page “Piscine” ou “Commandes” que j’ai présentées plus tôt. La capture est générée directement depuis l’ESP32 et peut être téléchargée.
    • Information : Cette section affiche des détails techniques sur le panneau, comme la version du firmware (OpenHASP 0.7.0-rc9 dans la capture), l’adresse IP, l’état de la connexion WiFi, et d’autres informations système (utilisation de la mémoire, état des capteurs, etc.). C’est un outil précieux pour le débogage ou pour vérifier que le panneau fonctionne correctement.
    • Configuration : Permet de modifier les paramètres d’OpenHASP, comme les identifiants WiFi, les paramètres MQTT (adresse du broker, port, utilisateur, mot de passe), ou les options d’affichage (luminosité, délai d’inactivité, etc.). C’est ici que j’ai initialement configuré la connexion MQTT pour intégrer ecran01 dans Home Assistant.
    • Firmware Update : Cette option permet de mettre à jour le firmware d’OpenHASP directement depuis l’interface web. Il suffit de télécharger la nouvelle version du firmware (par exemple, depuis le site officiel d’OpenHASP) et de la charger via cette section. Cela garantit que le panneau reste à jour avec les dernières améliorations et corrections de bugs.
    • File Editor : Un éditeur de fichiers intégré qui permet de modifier les fichiers de configuration (comme le fichier JSONL que j’utilise pour définir l’interface graphique). Vous pouvez télécharger, éditer, ou supprimer des fichiers directement depuis cette interface, ce qui est pratique pour ajuster l’interface graphique sans avoir à re-flasher l’ESP32.
    • Restart : Un bouton rouge qui permet de redémarrer l’ESP32 à distance. Cette fonctionnalité est similaire au bouton button.ecran01_restart disponible dans Home Assistant, mais elle est accessible directement depuis l’interface web. C’est utile pour appliquer des modifications (par exemple, après une mise à jour du firmware ou un changement de configuration) sans avoir à débrancher physiquement le panneau.

    Pourquoi ces fonctionnalités sont-elles utiles ?

    L’interface web d’OpenHASP est un complément précieux à l’intégration dans Home Assistant. Elle offre une gestion autonome du panneau, ce qui est particulièrement utile lors de la configuration initiale ou pour des tâches de maintenance. Par exemple, j’ai utilisé la section HASP Design pour ajuster la luminosité de démarrage (Startup Dim) et définir la page “Piscine” comme page par défaut (Startup Page), garantissant que le panneau affiche directement les informations essentielles au démarrage. La section Screenshot m’a permis de capturer les images que j’ai partagées dans cet article. La possibilité de mettre à jour le firmware ou de redémarrer l’appareil à distance via l’interface web est également un gain de temps, surtout si le panneau est installé dans un endroit difficile d’accès, comme mon local technique.

    Intégration avec Home Assistant

    OpenHASP communique avec Home Assistant via MQTT ou l’intégration « openHASP ».

    Configuration MQTT :

    • Assurez-vous qu’un broker MQTT (comme Mosquitto) est configuré dans Home Assistant.
    • Dans l’interface web d’OpenHASP (accessible via l’adresse IP du module, par exemple http://192.168.0.xxx), allez dans les paramètres et entrez les informations de votre broker MQTT (adresse, port, utilisateur, mot de passe).

    Intégration »openHASP » :

    Elle est disponible dans la bibliothèque des integrations:

    Une fois configurée le module est automatiquement détecté par Home Assistant et met à disposition des entités de contrôle et de configuration.

    Configuration de l’interface avec OpenHASP

    OpenHASP utilise des fichiers JSONL (JSON Lines) pour définir l’interface graphique. J’ai créé un fichier de configuration pour personnaliser mon panneau de commande, en m’appuyant sur le fichier pane1.yaml que je partage en annexe pour lier les données dynamiques, et sur le fichier « pages.JSONL » que je vais détailler ici pour la mise en page graphique.

    Structure générale de l’interface

    Le fichier « pages.JSONL » définit trois pages principales :

    • Page 0 : Contient des éléments communs à toutes les pages, comme l’heure, les températures intérieure et extérieure, et les boutons de navigation.
    • Page 1 : Vue générale de la piscine, avec les paramètres essentiels (température, pH, ORP, etc.) et des contrôles.
    • Page 2 : Contrôles manuels pour activer/désactiver les équipements.
    • Page 3 : Réglages des modes de fonctionnement.

    Page 0 : Éléments communs

    Cette page définit des éléments affichés en haut et en bas de l’écran sur toutes les pages :

    • Heure (p0b2) :
      {"page":0,"id":2,"obj":"btn","x":10,"y":0,"w":62,"h":40,"text":"00:00","text_font":28,"bg_color":"#2C3E50","text_color":"#FFFFFF","radius":0,"border_side":0}

    Affiche l’heure (09:53 dans les captures). La valeur est mise à jour dynamiquement via pane1.yaml :

      - obj: "p0b2"
        properties:
          "text": "{{ states('sensor.time') }}"
    • Température extérieure (p0b6) :
      {"page":0,"id":6,"obj":"btn","x":300,"y":0,"w":100,"h":40,"bg_color":"#2C3E50","text":"00.00","text_color":"#FFFFFF","radius":0,"border_side":0,"text_font":28}

    Affiche la température extérieure (16.8°C dans les captures), mise à jour via :

      - obj: "p0b6"
        properties:
          "text": "\uE2DC {{'%.1f' | format (states('sensor.vp2_temp_out') | round(1)) }}°C"
    • Température intérieure (p0b7) :
      {"page":0,"id":7,"obj":"btn","x":80,"y":0,"w":100,"h":40,"bg_color":"#2C3E50","text":"00.00","text_color":"#FFFFFF","radius":0,"border_side":0,"text_font":28}

    Affiche la température intérieure (21.9°C dans les captures), mise à jour via :

      - obj: "p0b7"
        properties:
          "text": "\uE6A1 {{'%.1f' | format (states('sensor.vp2_temp_in') | round(1)) }}°C"
    • Boutons de navigation (p0b3, p0b4, p0b5) :
      {"page":0,"id":3,"obj":"btn","action":"prev","x":0,"y":440,"w":160,"h":40,"bg_color":"#2C3E50","text":"\uE141","text_color":"#FFFFFF","radius":0,"border_side":0,"text_font":32}
      {"page":0,"id":4,"obj":"btn","action":"back","x":160,"y":440,"w":160,"h":40,"bg_color":"#2C3E50","text":"\uE2DC","text_color":"#FFFFFF","radius":0,"border_side":0,"text_font":32}
      {"page":0,"id":5,"obj":"btn","action":"next","x":320,"y":440,"w":160,"h":40,"bg_color":"#2C3E50","text":"\uE142","text_color":"#FFFFFF","radius":0,"border_side":0,"text_font":32}

    Ces boutons permettent de naviguer entre les pages (précédent, retour, suivant), visibles en bas des captures d’écran.

    Page 1 : Vue générale de la piscine

    Cette page affiche les paramètres essentiels de la piscine et permet de contrôler certains équipements. Voici quelques éléments clés :

    • Titre (p1b1) :
      {"page":1,"id":1,"obj":"btn","x":0,"y":0,"w":480,"h":40,"text":"Piscine","text_font":28,"bg_color":"#2C3E50","text_color":"#FFFFFF","radius":0,"border_side":0}

    Affiche le titre “Piscine” en haut de la page (visible dans la première capture).

    • Température de l’eau (p1b130, p1b131) :
      {"page":1,"id":130,"obj":"label","x":5,"y":50,"w":80,"h":80,"text":"\uE50F","text_font":80,"align":1,"text_color":"#00ff00"}
      {"page":1,"id":131,"obj":"label","x":120,"y":50,"w":225,"h":80,"text":"Offline","text_font":80,"align":1,"text_color":"#2C3E50"}

    Affiche une icône de thermomètre et la température de l’eau (16.6°C dans la capture), mise à jour via :

      - obj: "p1b131"
        properties:
          "text": "{{ states('sensor.esp178_temperature_eau')|float(0) |round(1)}} C°"
    • pH (p1b135, p1b136) :
      {"page":1,"id":135,"obj":"label","x":5,"y":130,"w":80,"h":80,"text":"\uE606","text_font":80,"align":1,"text_color":"#00ff00"}
      {"page":1,"id":136,"obj":"label","x":120,"y":130,"w":240,"h":80,"text":"Offline","text_font":80,"align":1,"text_color":"#2C3E50"}

    Affiche une icône et le pH de l’eau (5.85 dans la capture), mis à jour via :

      - obj: "p1b136"
        properties:
          "text": "{{ states('sensor.esp178_ph_ezo')|float(0) |round(2)}} pH"
    • Pompe de filtration (p1b132, p1b133) :
      {"page":1,"id":132,"obj":"label","x":380,"y":50,"w":90,"h":25,"text":"Ppe","text_font":16,"align":1,"text_color":"#2C3E50"}
      {"page":1,"id":133,"obj":"btn","x":385,"y":75,"w":80,"h":60,"text":"\uE156","text_font":48,"mode":"break","align":1,"radius":0,"text_color":"#FFFFFF","border_color":"#2C3E50","bg_color":"#2C3E50"}

    Affiche un bouton pour la pompe de filtration, qui change de couleur et d’icône selon son état (désactivée dans la capture, icône rouge). La logique est définie dans pane1.yaml :

      - obj: "p1b133"
        properties:
          "val": '{{ 1 if states("switch.esp178_cde_pompe_filtration") == "on" else 0 }}'
          "text": '{{ "\uE12C" if is_state("switch.esp178_cde_pompe_filtration", "on") else "\uE156" | e }}'
          "text_color": "{{ '#00ff00' if is_state('switch.esp178_cde_pompe_filtration', 'on') else '#ff0000' }}"
        event:
          "up":
            - service: homeassistant.toggle
              entity_id: "switch.esp178_cde_pompe_filtration"
    • Volet de la piscine (p1b137, p1b138) :
      {"page":1,"id":137,"obj":"label","x":380,"y":130,"w":90,"h":25,"text":"Volet","text_font":16,"align":1,"text_color":"#2C3E50"}
      {"page":1,"id":138,"obj":"btn","x":385,"y":155,"w":80,"h":60,"text":"\uE156","text_font":48,"mode":"break","align":1,"radius":0,"text_color":"#FFFFFF","border_color":"#2C3E50","bg_color":"#2C3E50"}

    Affiche un bouton pour le volet (fermé dans la capture, icône verte), mis à jour via :

      - obj: "p1b138"
        properties:
          "val": '{{ 1 if states("cover.esp178_volet_piscine") == "on" else 0 }}'
          "text": '{{ "\uF11E" if is_state("cover.esp178_volet_piscine", "open") else "\uF11C" | e }}'
          "text_color": "{{ '#ff0000' if is_state('cover.esp178_volet_piscine', 'open') else '#00ff00' }}"
        event:
          "up":
            - service: homeassistant.toggle
              entity_id: "cover.esp178_volet_piscine"
    • Autres données :
    • Horaire de filtration (p1b140, p1b141) :
    {"page":1,"id":140,"obj":"label","x":5,"y":210,"w":90,"h":40,"text":"Horaire:","text_font":30,"align":1,"text_color":"#2C3E50"} {"page":1,"id":141,"obj":"label","x":100,"y":210,"w":300,"h":40,"text":"Offline","text_font":40,"align":"center","text_color":"#2C3E50"}
    

      Affiche les horaires (12:00/12:15 dans la capture), mis à jour via :

       - obj: "p1b141" properties: "text": "{{ states('sensor.esp178_affich_heure_filtration')}}"
      • Durée de filtration (p1b145, p1b146) :
      {"page":1,"id":145,"obj":"label","x":5,"y":255,"w":70,"h":40,"text":"Duree:","text_font":30,"align":1,"text_color":"#2C3E50"} {"page":1,"id":146,"obj":"label","x":90,"y":255,"w":160,"h":40,"text":"Offline","text_font":40,"align":"left","text_color":"#2C3E50"}

      Affiche la durée (00:00:00), mis à jour via :

       - obj: "p1b146" properties: "text": "{{ states('time.esp178_duree_filtration')}}"
      • Coefficient de filtration (p1b147, p1b148) :
      {"page":1,"id":147,"obj":"label","x":260,"y":255,"w":70,"h":40,"text":"Coef:","text_font":30,"align":1,"text_color":"#2C3E50"} {"page":1,"id":148,"obj":"label","x":300,"y":255,"w":150,"h":40,"text":"Offline","text_font":40,"align":"right","text_color":"#2C3E50"}

      Affiche le coefficient (80.0%), mis à jour via :

       - obj: "p1b148" properties: "text": "{{ states('number.esp178_coeff_filtration')}} %"
      • Mode de fonctionnement (p1b150, p1b151) :
      {"page":1,"id":150,"obj":"label","x":5,"y":305,"w":70,"h":40,"text":"Fonct:","text_font":30,"align":1,"text_color":"#2C3E50"} {"page":1,"id":151,"obj":"dropdown","x":100,"y":305,"w":300,"h":40,"options":"Palier\nClassique\nAbaque\nHoraire\nMa_f\nAt_f","direction":1,"text_font":25,"align":1,"text_color":"#2C3E50"}
      • Permet de sélectionner le mode de fonctionnement (Horaire dans la capture), contrôlé via :
      - obj: "p1b151"
        properties:
          "val": >
            {% set st = states('select.esp178_mode_fonctionnement_filtration')%}
            {% for text,num in [('Palier',0),('Classique',1),('Abaque',2),('Horaire',3),('Ma_f',4),('At_f',5) ] %}
            {% if st == text %}
              {{ num }}
            {%endif%}
            {% endfor %}
        event:
          "changed":
            - service: select.select_option
              target:
                entity_id: select.esp178_mode_fonctionnement_filtration
              data:
                option: >
                  {% if text == "Palier" -%}
                  Palier
                  {% elif text == 'Classique' -%}
                  Classique
                  {% elif text == 'Abaque' -%}
                  Abaque
                  {% elif text == 'Horaire' -%}
                  Horaire
                  {% elif text == 'Ma_f' -%}
                  Ma_f
                  {% elif text == 'At_f' -%}
                  At_f
                  {% endif -%}
      • Pression, ORP, Puissance, Conso journalière (p1b221 à p1b231) :
      {"page":1,"id":221,"obj":"label","x":5,"y":355,"w":130,"h":40,"text":"Pression:","text_font":30,"align":"left","text_color":"#2C3E50"} {"page":1,"id":222,"obj":"label","x":140,"y":355,"w":100,"h":40,"text":"Offline","text_font":30,"align":"left","text_color":"#2C3E50"} {"page":1,"id":223,"obj":"label","x":250,"y":355,"w":130,"h":40,"text":"-ORP:","text_font":30,"align":"left","text_color":"#2C3E50"} {"page":1,"id":224,"obj":"label","x":330,"y":355,"w":150,"h":40,"text":"Offline","text_font":30,"align":"left","text_color":"#2C3E50"} {"page":1,"id":225,"obj":"label","x":5,"y":395,"w":130,"h":40,"text":"Puissance:","text_font":30,"align":"left","text_color":"#2C3E50"} {"page":1,"id":226,"obj":"label","x":140,"y":395,"w":150,"h":40,"text":"Offline","text_font":30,"align":"left","text_color":"#2C3E50"} {"page":1,"id":230,"obj":"label","x":250,"y":395,"w":130,"h":40,"text":"-Conso J:","text_font":30,"align":"left","text_color":"#2C3E50"} {"page":1,"id":231,"obj":"label","x":370,"y":395,"w":150,"h":40,"text":"Offline","text_font":30,"align":"left","text_color":"#2C3E50"}

      • Affiche la pression (0.304 bar), l’ORP (72.80 mV), la puissance (8.30 W), et la consommation journalière (0 kWh), mis à jour via :
      - obj: "p1b222"
        properties:
          "text": "{{ states('sensor.esp178_pression_filtre') }} b"
      - obj: "p1b224"
        properties:
          "text": "{{ states('sensor.esp178_orp_ezo') }} ms"
      - obj: "p1b226"
        properties:
          "text": "{{ states('sensor.pzem_pisc_puissance') }} W"
      - obj: "p1b231"
        properties:
          "text": "{{ states('sensor.compteur_energie_piscine_jour_hp_hc') }} kWh"

      Page 2 : Contrôles manuels

      Cette page permet de contrôler manuellement différents équipements de la piscine.

      • Titre (p2b1) :
        {"page":2,"id":1,"obj":"btn","x":0,"y":0,"w":480,"h":40,"text":"Cde","text_font":28,"bg_color":"#2C3E50","text_color":"#FFFFFF","radius":0,"border_side":0}

      Affiche le titre “Cde” (Commandes) en haut de la page (visible dans la troisième capture).

      • Boutons de contrôle (p2b101 à p2b127) :
        {"page":2,"id":101,"obj":"label","x":5,"y":45,"w":90,"h":25,"text":"Ppe","text_font":16,"align":1,"text_color":"#2C3E50"}
        {"page":2,"id":121,"obj":"btn","x":10,"y":70,"w":80,"h":60,"text":"\uE156","text_font":48,"mode":"break","align":1,"radius":0,"text_color":"#FFFFFF","border_color":"#2C3E50","bg_color":"#2C3E50"}

      Boutons pour activer/désactiver la pompe de filtration, la pompe pH-, la pompe chlore, l’ouverture/fermeture du volet, l’éclairage, et l’électrovanne d’eau. Dans la capture, tous sont désactivés (icônes rouges). Exemple pour la pompe de filtration :

      - obj: "p2b121"
        properties:
          "val": '{{ 1 if states("switch.esp178_cde_pompe_filtration") == "on" else 0 }}'
          "text": '{{ "\uE12C" if is_state("switch.esp178_cde_pompe_filtration", "on") else "\uE156" | e }}'
          "text_color": "{{ '#00ff00' if is_state('switch.esp178_cde_pompe_filtration', 'on') else '#ff0000' }}"
        event:
          "up":
            - service: homeassistant.toggle
              entity_id: "switch.esp178_cde_pompe_filtration"
      • Ajustement du coefficient (p2b150 à p2b153) :
        {"page":2,"id":150,"obj":"label","x":100,"y":225,"w":90,"h":30,"text":"Coef:","text_font":30,"align":"center","text_color":"#2C3E50"}
        {"page":2,"id":151,"obj":"btn","x":10,"y":260,"w":80,"h":60,"text":"\uE374","text_font":48,"mode":"break","align":"center","radius":0,"text_color":"#FFFFFF","border_color":"#2C3E50","bg_color":"#2C3E50"}
        {"page":2,"id":152,"obj":"btn","x":100,"y":260,"w":110,"h":60,"text":"\uE156","text_font":30,"mode":"break","align":"center","radius":0,"text_color":"#FFFFFF","border_color":"#2C3E50","bg_color":"#2C3E50"}
        {"page":2,"id":153,"obj":"btn","x":220,"y":260,"w":80,"h":60,"text":"\uE415","text_font":48,"mode":"break","align":"center","radius":0,"text_color":"#FFFFFF","border_color":"#2C3E50","bg_color":"#2C3E50"}

      Permet d’ajuster le coefficient de filtration (80% dans la capture) avec des boutons “+” et “-”, contrôlé via :

        - obj: "p2b151"
          event:
            "up":
              - service: number.decrement
                target:
                  entity_id: number.esp178_coeff_filtration
        - obj: "p2b152"
          properties:
            "text": "{{'%.0f' | format (states('number.esp178_coeff_filtration') | round(0)) }}%"
        - obj: "p2b153"
          event:
            "up":
              - service: number.increment
                target:
                  entity_id: number.esp178_coeff_filtration

      Page 3 : Réglages

      Cette page permet de configurer les modes de fonctionnement.

      • Titre (p3b1) :
        {"page":3,"id":1,"obj":"btn","x":0,"y":0,"w":480,"h":40,"text":"Autom's","text_font":28,"bg_color":"#2C3E50","text_color":"#FFFFFF","radius":0,"border_side":0}

      Affiche le titre “Autom’s” (Automatisations) en haut de la page (visible dans la deuxième capture).

      • Modes de régulation (p3b101 à p3b132) :
        {"page":3,"id":101,"obj":"label","x":5,"y":100,"w":130,"h":40,"text":"Regul pH:","text_font":30,"align":"left","text_color":"#2C3E50"}
        {"page":3,"id":102,"obj":"dropdown","x":150,"y":100,"w":200,"h":40,"options":"Auto\nMa_f\nAt_f","direction":0,"text_font":25,"align":1,"text_color":"#2C3E50"}

      Permet de choisir le mode de régulation du pH (At_f dans la capture). La logique est définie dans pane1.yaml :

        - obj: "p3b102"
          properties:
            "val": >
              {% set st = states('select.esp178_mode_fonctionnement_regul_ph')%}
              {% for text,num in [('Auto',0),('Ma_f',1),('At_f',2) ] %}
              {% if st == text %}
                {{ num }}
              {%endif%}
              {% endfor %}
          event:
            "changed":
              - service: select.select_option
                target:
                  entity_id: select.esp178_mode_fonctionnement_regul_ph
                data:
                  option: >
                    {% if text == "Auto" -%}
                    Auto
                    {% elif text == 'Ma_f' -%}
                    Ma_f
                    {% elif text == 'At_f' -%}
                    At_f
                    {% endif -%}

      Des sélecteurs similaires existent pour la régulation du chlore, l’appoint d’eau, et le mode hors gel (Désactivé dans la capture).

      • RAZ du temps de galet de chlore (p3b150, p3b151) :
        {"page":3,"id":150,"obj":"label","x":5,"y":310,"w":160,"h":40,"text":"RAZ Cart Chl:","text_font":30,"align":"left","text_color":"#2C3E50"}
        {"page":3,"id":151,"obj":"btn","x":200,"y":300,"w":80,"h":60,"text":"\uE156","text_font":30,"mode":"break","align":1,"radius":0,"text_color":"#FFFFFF","border_color":"#2C3E50","bg_color":"#2C3E50"}

      Affiche le temps restant pour le galet de chlore (0h dans la capture) et permet de réinitialiser ce compteur, contrôlé via :

        - obj: "p3b151"
          properties:
            "text": "{{'%.0f' | format (states('sensor.esp178_temps_galet_chlore') | round(0)) }}h"
          event:
            "up":
              - service: button.press
                target:
                  entity_id: button.esp178_bp_raz_tps_galet_chlore

      Résultat et captures d’écran du module

      Voici à quoi ressemble mon panneau en action, comme montré dans les captures d’écran :

      • Page 1 (Piscine) : Une vue d’ensemble avec la température de l’eau (16.6°C), le pH (5.85), l’ORP (72.80 mV), la pression du filtre (0.304 bar), et des contrôles pour la pompe et le volet. Les horaires de filtration (12:00/12:15) et le coefficient (80%) sont également affichés.
      • Page 2 (Commandes) : Des boutons pour activer/désactiver manuellement les équipements (pompe, pH-, chlore, volet, éclairage, etc.), tous désactivés dans la capture. On peut aussi ajuster le coefficient de filtration.
      • Page 3 (Réglages) : Des sélecteurs pour configurer les modes de régulation (pH, chlore, eau, hors gel) et un bouton pour réinitialiser le compteur de galet de chlore.

      Intégration dans Home Assistant


      Écran de contrôle

      L’intégration d’OpenHASP dans Home Assistant offre un ensemble d’entités qui permettent de contrôler et de surveiller le panneau directement depuis l’interface de Home Assistant. Ces entités, générées automatiquement lors de l’intégration MQTT d’OpenHASP, sont accessibles dans Home Assistant sous le nom de l’appareil (dans mon cas, ecran01). Elles permettent de gérer des fonctionnalités comme le rétroéclairage, la navigation entre les pages, ou encore la protection contre la brûlure d’écran, tout en offrant une intégration fluide avec le reste de mon système domotique. Voici un aperçu de ces entités, de leurs fonctionnalités, et d’une automatisation que j’ai mise en place pour gérer l’écran, illustré par une capture d’écran de l’interface de Home Assistant.

      Entités fournies par l’intégration OpenHASP

      Une fois OpenHASP connecté via MQTT, Home Assistant détecte automatiquement l’appareil et expose plusieurs entités, visibles dans la capture d’écran sous l’appareil ecran01. Voici les principales entités et leurs usages :

      • Backlight (Rétroéclairage) : Cette entité est un interrupteur (switch.ecran01_backlight) qui permet d’allumer ou d’éteindre le rétroéclairage de l’écran. Dans la capture, il est activé (icône jaune allumée). Cela peut être utilisé dans une automatisation pour, par exemple, éteindre l’écran la nuit afin d’économiser de l’énergie.
      • Moodlight (Mode lumière) : Un autre interrupteur (switch.ecran01_moodlight) qui active ou désactive un mode “moodlight”. Ce mode peut modifier l’ambiance lumineuse de l’écran (par exemple, pour un effet décoratif). Dans la capture, il est désactivé, mais il pourrait être utilisé pour créer une ambiance visuelle dans certaines situations.
      • Switch 0 : Cette entité (switch.ecran01_switch_0) est un interrupteur générique fourni par OpenHASP. Elle peut être configurée pour contrôler une sortie GPIO de l’ESP32 ou une autre fonctionnalité personnalisée. Dans mon cas, je ne l’ai pas utilisée, et elle est désactivée dans la capture.
      • Antiburn (Protection contre la brûlure d’écran) : Un interrupteur (switch.ecran01_antiburn) qui active ou désactive la fonctionnalité de protection contre la brûlure d’écran. Lorsqu’elle est activée (comme dans la capture), OpenHASP déplace légèrement les pixels ou réduit la luminosité après une période d’inactivité, ce qui prolonge la durée de vie de l’écran TFT. C’est particulièrement utile pour un panneau qui affiche des données statiques en continu, comme les paramètres de ma piscine.
      • Page Number (Numéro de page) : Une entité de type “number” (number.ecran01_page_number) qui permet de sélectionner la page affichée sur le panneau. Dans la capture, la page 1 est sélectionnée, ce qui correspond à la page “Piscine” vue dans les captures précédentes. Cette entité est pratique pour naviguer entre les pages (Piscine, Commandes, Réglages) depuis Home Assistant, par exemple dans un tableau de bord ou une automatisation.
      • Restart (Redémarrage) : Un bouton (button.ecran01_restart) qui permet de redémarrer l’ESP32 à distance. Cela peut être utile pour appliquer des modifications ou résoudre des problèmes de connexion sans avoir à accéder physiquement au panneau.
      • Appuyer : Une entité de type bouton (button.ecran01_appuyer) qui semble être une action personnalisée ou un placeholder. Dans mon cas, elle n’est pas configurée pour une action spécifique, mais elle pourrait être utilisée pour déclencher une commande via MQTT ou HTTP, par exemple pour exécuter un script dans Home Assistant.

      Utilisation dans Home Assistant

      Ces entités peuvent être utilisées dans Home Assistant pour créer des tableaux de bord, des automatisations, ou des scripts. Par exemple, je pourrais créer une carte Lovelace qui affiche le numéro de page actuel (number.ecran01_page_number) et permet de naviguer entre les pages. L’entité switch.ecran01_antiburn est particulièrement utile pour garantir la longévité de l’écran, et je l’ai laissée activée en permanence.

      Dans la capture d’écran, on voit que l’appareil ecran01 est bien intégré dans Home Assistant, avec toutes les entités listées. Cela me permet de gérer le panneau de manière centralisée, aux côtés des autres entités de ma piscine (comme sensor.esp178_temperature_eau ou switch.esp178_cde_pompe_filtration).

      Exemple d’automatisation : Gestion du rétroéclairage

      Pour optimiser l’utilisation de l’écran et économiser de l’énergie, j’ai créé une automatisation dans Home Assistant qui ajuste le rétroéclairage toutes les 30 minutes. Voici le détail de cette automatisation, nommée “Ecran01 Eteint ecran toutes x mn” :

      alias: Ecran01 Eteint ecran toutes x mn
      description: ""
      mode: single
      triggers:
        - minutes: /30
          trigger: time_pattern
      conditions: []
      actions:
        - data:
            topic: hasp/ecran01/command
            payload: backlight {"state":"true","brightness":10}
          enabled: false
          action: mqtt.publish
        - data:
            topic: hasp/ecran01/config/gui
            payload: "{\"idle2\":20}"
          enabled: false
          action: mqtt.publish
        - type: turn_off
          device_id: 31203080ff3e67d781d95be03b42e98e
          entity_id: caf58cffba51ee848ade4eaa4c57a127
          domain: light

      Explication de l’automatisation :

      • Déclencheur : L’automatisation se déclenche toutes les 30 minutes (via time_pattern avec minutes: /30).
      • Actions :
      1. Ajustement du rétroéclairage : Envoie une commande MQTT au topic hasp/ecran01/command pour activer le rétroéclairage ("state":"true") avec une luminosité réduite à 10 ("brightness":10). Cette action est actuellement désactivée (enabled: false), mais elle pourrait être utilisée pour ajuster la luminosité à un niveau minimal.
      2. Configuration du mode inactif : Envoie une commande MQTT au topic hasp/ecran01/config/gui pour définir un délai d’inactivité ("idle2":20), après lequel l’écran pourrait passer en mode basse consommation. Cette action est également désactivée pour le moment.
      3. Extinction d’une lumière : Éteint une entité de type lumière (light avec l’entity_id: caf58cffba51ee848ade4eaa4c57a127). Dans mon cas, cette entité correspond probablement à une lumière associée au panneau ou à la piscine, mais elle n’est pas directement liée à OpenHASP. Cette action permet de coordonner l’extinction de l’écran avec d’autres équipements.

      Pourquoi cette automatisation ?
      Cette automatisation me permet de gérer l’écran de manière intelligente : en réduisant la luminosité ou en éteignant des équipements associés, je peux économiser de l’énergie tout en prolongeant la durée de vie de l’écran. Bien que certaines actions soient désactivées pour le moment, je peux les activer selon mes besoins, par exemple pour ajuster la luminosité en fonction de l’heure de la journée.

      Pourquoi c’est utile ?

      Ces entités fournies par l’intégration OpenHASP permettent une gestion fine du panneau directement depuis Home Assistant, sans avoir à passer par l’interface web d’OpenHASP. Elles offrent une flexibilité supplémentaire pour intégrer le panneau dans des scénarios domotiques complexes. Par exemple, l’automatisation ci-dessus montre comment je peux coordonner le rétroéclairage avec d’autres équipements, tandis que l’entité number.ecran01_page_number me permet de changer de page (par exemple, pour afficher la page “Commandes” dans certaines conditions). Cette intégration renforce l’aspect centralisé et pratique de mon système domotique.


      Conclusion

      Ce projet montre à quel point OpenHASP et un simple module ESP32 peuvent transformer la gestion d’une piscine en une expérience intuitive et centralisée. Avec Home Assistant, les possibilités de personnalisation sont infinies. Si vous avez une piscine ou un autre système à automatiser, je vous encourage à essayer OpenHASP ! Qu’en pensez-vous ? Avez-vous des idées pour améliorer ce panneau ? Laissez-moi un commentaire !


      Liste des publications en lien avec cet article:

      1. Filtration avec ESPHome et ESP32
      2. Filtration avec « AppDaemon »
      3. Filtration avec « Pool Pump Manager« 
      4. Mesure de puissance électrique
      5. Mise à niveau automatique
      6. Mesure du pH
      7. Régulation du Ph
      8. Mise Hors Gel
      9. Mesure de pression
      10. Mesure consommation d’eau
      11. Panneau de contrôle avec un ESP32
      12. Analyse de l’eau avec PoolLAB2.0

      Annexes:

      Fichier de configuration du panel « pages.JSONL »:

      {"page":0,"id":1,"obj":"btn","x":440,"y":0,"w":30,"h":40,"text":"\uE5A9","text_font":"2","text_color":"gray","bg_opa":0,"border_width":0}
      {"page":0,"id":2,"obj":"btn","x":10,"y":0,"w":62,"h":40,"text":"00:00","text_font":28,"bg_color":"#2C3E50","text_color":"#FFFFFF","radius":0,"border_side":0}
      
      {"page":0,"id":6,"obj":"btn","x":300,"y":0,"w":100,"h":40,"bg_color":"#2C3E50","text":"00.00","text_color":"#FFFFFF","radius":0,"border_side":0,"text_font":28}
      {"page":0,"id":7,"obj":"btn","x":80,"y":0,"w":100,"h":40,"bg_color":"#2C3E50","text":"00.00","text_color":"#FFFFFF","radius":0,"border_side":0,"text_font":28}
      
      {"page":0,"id":3,"obj":"btn","action":"prev","x":0,"y":440,"w":160,"h":40,"bg_color":"#2C3E50","text":"\uE141","text_color":"#FFFFFF","radius":0,"border_side":0,"text_font":32}
      {"page":0,"id":4,"obj":"btn","action":"back","x":160,"y":440,"w":160,"h":40,"bg_color":"#2C3E50","text":"\uE2DC","text_color":"#FFFFFF","radius":0,"border_side":0,"text_font":32}
      {"page":0,"id":5,"obj":"btn","action":"next","x":320,"y":440,"w":160,"h":40,"bg_color":"#2C3E50","text":"\uE142","text_color":"#FFFFFF","radius":0,"border_side":0,"text_font":32}
      
      
      {"page":1,"id":1,"obj":"btn","x":0,"y":0,"w":480,"h":40,"text":"Piscine","text_font":28,"bg_color":"#2C3E50","text_color":"#FFFFFF","radius":0,"border_side":0}
      
      
      {"page":1,"id":130,"obj":"label","x":5,"y":50,"w":80,"h":80,"text":"\uE50F","text_font":80,"align":1,"text_color":"#00ff00"}
      {"page":1,"id":131,"obj":"label","x":120,"y":50,"w":225,"h":80,"text":"Offline","text_font":80,"align":1,"text_color":"#2C3E50"}
      
      {"page":1,"id":132,"obj":"label","x":380,"y":50,"w":90,"h":25,"text":"Ppe","text_font":16,"align":1,"text_color":"#2C3E50"}
      {"page":1,"id":133,"obj":"btn","x":385,"y":75,"w":80,"h":60,"text":"\uE156","text_font":48,"mode":"break","align":1,"radius":0,"text_color":"#FFFFFF","border_color":"#2C3E50","bg_color":"#2C3E50"}
      
      {"page":1,"id":135,"obj":"label","x":5,"y":130,"w":80,"h":80,"text":"\uE606","text_font":80,"align":1,"text_color":"#00ff00"}
      {"page":1,"id":136,"obj":"label","x":120,"y":130,"w":240,"h":80,"text":"Offline","text_font":80,"align":1,"text_color":"#2C3E50"}
      
      {"page":1,"id":137,"obj":"label","x":380,"y":130,"w":90,"h":25,"text":"Volet","text_font":16,"align":1,"text_color":"#2C3E50"}
      {"page":1,"id":138,"obj":"btn","x":385,"y":155,"w":80,"h":60,"text":"\uE156","text_font":48,"mode":"break","align":1,"radius":0,"text_color":"#FFFFFF","border_color":"#2C3E50","bg_color":"#2C3E50"}
      
      {"page":1,"id":140,"obj":"label","x":5,"y":210,"w":90,"h":40,"text":"Horaire:","text_font":30,"align":1,"text_color":"#2C3E50"}
      {"page":1,"id":141,"obj":"label","x":100,"y":210,"w":300,"h":40,"text":"Offline","text_font":40,"align":"center","text_color":"#2C3E50"}
      
      {"page":1,"id":145,"obj":"label","x":5,"y":255,"w":70,"h":40,"text":"Duree:","text_font":30,"align":1,"text_color":"#2C3E50"}
      {"page":1,"id":146,"obj":"label","x":90,"y":255,"w":160,"h":40,"text":"Offline","text_font":40,"align":"left","text_color":"#2C3E50"}
      
      {"page":1,"id":147,"obj":"label","x":260,"y":255,"w":70,"h":40,"text":"Coef:","text_font":30,"align":1,"text_color":"#2C3E50"}
      {"page":1,"id":148,"obj":"label","x":300,"y":255,"w":150,"h":40,"text":"Offline","text_font":40,"align":"right","text_color":"#2C3E50"}
      
      {"page":1,"id":150,"obj":"label","x":5,"y":305,"w":70,"h":40,"text":"Fonct:","text_font":30,"align":1,"text_color":"#2C3E50"}
      {"page":1,"id":151,"obj":"dropdown","x":100,"y":305,"w":300,"h":40,"options":"Palier\nClassique\nAbaque\nHoraire\nMa_f\nAt_f","direction":1,"text_font":25,"align":1,"text_color":"#2C3E50"}
      
      
      {"page":1,"id":221,"obj":"label","x":5,"y":355,"w":130,"h":40,"text":"Pression:","text_font":30,"align":"left","text_color":"#2C3E50"}
      {"page":1,"id":222,"obj":"label","x":140,"y":355,"w":100,"h":40,"text":"Offline","text_font":30,"align":"left","text_color":"#2C3E50"}
      
      {"page":1,"id":223,"obj":"label","x":250,"y":355,"w":130,"h":40,"text":"-ORP:","text_font":30,"align":"left","text_color":"#2C3E50"}
      {"page":1,"id":224,"obj":"label","x":330,"y":355,"w":150,"h":40,"text":"Offline","text_font":30,"align":"left","text_color":"#2C3E50"}
      
      {"page":1,"id":225,"obj":"label","x":5,"y":395,"w":130,"h":40,"text":"Puissance:","text_font":30,"align":"left","text_color":"#2C3E50"}
      {"page":1,"id":226,"obj":"label","x":140,"y":395,"w":150,"h":40,"text":"Offline","text_font":30,"align":"left","text_color":"#2C3E50"}
      
      {"page":1,"id":230,"obj":"label","x":250,"y":395,"w":130,"h":40,"text":"-Conso J:","text_font":30,"align":"left","text_color":"#2C3E50"}
      {"page":1,"id":231,"obj":"label","x":370,"y":395,"w":150,"h":40,"text":"Offline","text_font":30,"align":"left","text_color":"#2C3E50"}
      
      
      {"page":2,"id":1,"obj":"btn","x":0,"y":0,"w":480,"h":40,"text":"Cde","text_font":28,"bg_color":"#2C3E50","text_color":"#FFFFFF","radius":0,"border_side":0}
      
      
      {"page":2,"id":101,"obj":"label","x":5,"y":45,"w":90,"h":25,"text":"Ppe","text_font":16,"align":1,"text_color":"#2C3E50"}
      {"page":2,"id":121,"obj":"btn","x":10,"y":70,"w":80,"h":60,"text":"\uE156","text_font":48,"mode":"break","align":1,"radius":0,"text_color":"#FFFFFF","border_color":"#2C3E50","bg_color":"#2C3E50"}
      
      {"page":2,"id":102,"obj":"label","x":100,"y":45,"w":90,"h":25,"text":"Ppe ph-","text_font":16,"align":1,"text_color":"#2C3E50"}
      {"page":2,"id":122,"obj":"btn","x":105,"y":70,"w":80,"h":60,"text":"\uE156","text_font":48,"mode":"break","align":1,"radius":0,"text_color":"#FFFFFF","border_color":"#2C3E50","bg_color":"#2C3E50"}
      
      {"page":2,"id":103,"obj":"label","x":195,"y":45,"w":90,"h":25,"text":"Ppe Chl","text_font":16,"align":1,"text_color":"#2C3E50"}
      {"page":2,"id":123,"obj":"btn","x":200,"y":70,"w":80,"h":60,"text":"\uE156","text_font":48,"mode":"break","align":1,"radius":0,"text_color":"#FFFFFF","border_color":"#2C3E50","bg_color":"#2C3E50"}
      
      {"page":2,"id":104,"obj":"label","x":290,"y":45,"w":90,"h":25,"text":"Ouv Volet","text_font":16,"align":1,"text_color":"#2C3E50"}
      {"page":2,"id":124,"obj":"btn","x":295,"y":70,"w":80,"h":60,"text":"\uE156","text_font":48,"mode":"break","align":1,"radius":0,"text_color":"#FFFFFF","border_color":"#2C3E50","bg_color":"#2C3E50"}
      
      {"page":2,"id":105,"obj":"label","x":385,"y":45,"w":90,"h":25,"text":"ferm Volet.","text_font":16,"align":1,"text_color":"#2C3E50"}
      {"page":2,"id":125,"obj":"btn","x":390,"y":70,"w":80,"h":60,"text":"\uE156","text_font":48,"mode":"break","align":1,"radius":0,"text_color":"#FFFFFF","border_color":"#2C3E50","bg_color":"#2C3E50"}
      
      {"page":2,"id":106,"obj":"label","x":5,"y":130,"w":90,"h":25,"text":"Spot","text_font":16,"align":1,"text_color":"#2C3E50"}
      {"page":2,"id":126,"obj":"btn","x":10,"y":155,"w":80,"h":60,"text":"\uE156","text_font":48,"mode":"break","align":1,"radius":0,"text_color":"#FFFFFF","border_color":"#2C3E50","bg_color":"#2C3E50"}
      
      {"page":2,"id":107,"obj":"label","x":100,"y":130,"w":90,"h":25,"text":"Ev eau","text_font":16,"align":1,"text_color":"#2C3E50"}
      {"page":2,"id":127,"obj":"btn","x":105,"y":155,"w":80,"h":60,"text":"\uE156","text_font":48,"mode":"break","align":1,"radius":0,"text_color":"#FFFFFF","border_color":"#2C3E50","bg_color":"#2C3E50"}
      
      {"page":2,"id":2,"obj":"btn","x":0,"y":220,"w":480,"h":2,"text":"","value_font":22,"text_color":"#000000","radius":0,"border_side":15,"border_color":"#2C3E50"}
      
      {"page":2,"id":150,"obj":"label","x":100,"y":225,"w":90,"h":30,"text":"Coef:","text_font":30,"align":"center","text_color":"#2C3E50"}
      {"page":2,"id":151,"obj":"btn","x":10,"y":260,"w":80,"h":60,"text":"\uE374","text_font":48,"mode":"break","align":"center","radius":0,"text_color":"#FFFFFF","border_color":"#2C3E50","bg_color":"#2C3E50"}
      {"page":2,"id":152,"obj":"btn","x":100,"y":260,"w":110,"h":60,"text":"\uE156","text_font":30,"mode":"break","align":"center","radius":0,"text_color":"#FFFFFF","border_color":"#2C3E50","bg_color":"#2C3E50"}
      {"page":2,"id":153,"obj":"btn","x":220,"y":260,"w":80,"h":60,"text":"\uE415","text_font":48,"mode":"break","align":"center","radius":0,"text_color":"#FFFFFF","border_color":"#2C3E50","bg_color":"#2C3E50"}
      
      
      {"page":3,"id":1,"obj":"btn","x":0,"y":0,"w":480,"h":40,"text":"Autom's","text_font":28,"bg_color":"#2C3E50","text_color":"#FFFFFF","radius":0,"border_side":0}
      
      {"page":3,"id":2,"obj":"label","x":100,"y":40,"w":150,"h":30,"text":"Régulations","text_font":30,"align":"center","text_color":"#2C3E50"}
      
      
      {"page":3,"id":101,"obj":"label","x":5,"y":100,"w":130,"h":40,"text":"Regul pH:","text_font":30,"align":"left","text_color":"#2C3E50"}
      {"page":3,"id":102,"obj":"dropdown","x":150,"y":100,"w":200,"h":40,"options":"Auto\nMa_f\nAt_f","direction":0,"text_font":25,"align":1,"text_color":"#2C3E50"}
      
      {"page":3,"id":111,"obj":"label","x":5,"y":150,"w":130,"h":40,"text":"Regul Chl:","text_font":30,"align":"left","text_color":"#2C3E50"}
      {"page":3,"id":112,"obj":"dropdown","x":150,"y":150,"w":200,"h":40,"options":"Auto\nMa_f\nAt_f","direction":0,"text_font":25,"align":1,"text_color":"#2C3E50"}
      
      {"page":3,"id":121,"obj":"label","x":5,"y":200,"w":130,"h":40,"text":"Regul Eau:","text_font":30,"align":"left","text_color":"#2C3E50"}
      {"page":3,"id":122,"obj":"dropdown","x":150,"y":200,"w":200,"h":40,"options":"Auto\nMa_f\nAt_f","direction":0,"text_font":25,"align":1,"text_color":"#2C3E50"}
      
      {"page":3,"id":131,"obj":"label","x":5,"y":250,"w":130,"h":40,"text":"Hors Gel:","text_font":30,"align":"left","text_color":"#2C3E50"}
      {"page":3,"id":132,"obj":"dropdown","x":150,"y":250,"w":200,"h":40,"options":"Desactivé\nActivé","direction":0,"text_font":25,"align":1,"text_color":"#2C3E50"}
      
      
      
      {"page":3,"id":150,"obj":"label","x":5,"y":310,"w":160,"h":40,"text":"RAZ Cart Chl:","text_font":30,"align":"left","text_color":"#2C3E50"}
      {"page":3,"id":151,"obj":"btn","x":200,"y":300,"w":80,"h":60,"text":"\uE156","text_font":30,"mode":"break","align":1,"radius":0,"text_color":"#FFFFFF","border_color":"#2C3E50","bg_color":"#2C3E50"}
      

      Fichier de configuration Home Assistant: pane1.yaml

      openhasp:
        ecran01:
          objects:
            - obj: "p0b1"
              properties:
                "text_color": "{% if -30 <= state_attr('openhasp.ecran01','rssi') |int %}#00ff00{% elif -31 > state_attr('openhasp.ecran01','rssi') |int >= -50 %}#ccff00{% elif -51 > state_attr('openhasp.ecran01','rssi') |int >= -80 %}#ff9100{% else %}#ff0000{% endif %}"
            - obj: "p0b2"
              properties:
                "text": "{{ states('sensor.time') }}"
            - obj: "p0b6"
              properties:
                "text": "\uE2DC {{'%.1f' | format (states('sensor.vp2_temp_out') | round(1)) }}°C"
            - obj: "p0b7"
              properties:
                "text": "\uE6A1 {{'%.1f' | format (states('sensor.vp2_temp_in') | round(1)) }}°C"
      
      
      
      # Affichage piscine
            - obj: "p1b131"
              properties:
                "text": "{{ states('sensor.esp178_temperature_eau')|float(0) |round(1)}} C°" 
      
            - obj: "p1b133"  
              properties:
                "val": '{{ 1 if states("switch.esp178_cde_pompe_filtration") == "on" else 0 }}'
                "text": '{{ "\uE12C" if is_state("switch.esp178_cde_pompe_filtration", "on") else "\uE156" | e }}'
                "text_color": "{{ '#00ff00' if is_state('switch.esp178_cde_pompe_filtration', 'on') else '#ff0000' }}" 
              event:
                "up":
                  - service: homeassistant.toggle
                    entity_id: "switch.esp178_cde_pompe_filtration"
      
            - obj: "p1b136"
              properties:
                "text": "{{ states('sensor.esp178_ph_ezo')|float(0) |round(2)}} pH" 
      
            - obj: "p1b138"  
              properties:
                "val": '{{ 1 if states("cover.esp178_volet_piscine") == "on" else 0 }}'
                "text": '{{ "\uF11E" if is_state("cover.esp178_volet_piscine", "open") else "\uF11C" | e }}'
                "text_color": "{{ '#ff0000' if is_state('cover.esp178_volet_piscine', 'open') else '#00ff00' }}" 
              event:
                "up":
                  - service: homeassistant.toggle
                    entity_id: "cover.esp178_volet_piscine"
      
            - obj: "p1b141"
              properties:
                "text": "{{ states('sensor.esp178_affich_heure_filtration')}}" 
      
            - obj: "p1b146"
              properties:
                "text": "{{ states('time.esp178_duree_filtration')}}" 
      
            - obj: "p1b148"
              properties:
                "text": "{{ states('number.esp178_coeff_filtration')}} %" 
      
            - obj: "p1b151"
              properties:
                "val": >
                  {% set st = states('select.esp178_mode_fonctionnement_filtration')%}
                  {% for text,num in [('Palier',0),('Classique',1),('Abaque',2),('Horaire',3),('Ma_f',4),('At_f',5) ] %}
                  {% if st == text %}
                    {{ num }}
                  {%endif%}
                  {% endfor %}
              event:
                "changed":
                  - service: select.select_option
                    target:
                      entity_id: select.esp178_mode_fonctionnement_filtration
                    data:
                      option: >
                        {% if text == "Palier" -%}
                        Palier
                        {% elif text == 'Classique' -%}
                        Classique
                        {% elif text == 'Abaque' -%}
                        Abaque
                        {% elif text == 'Horaire' -%}
                        Horaire
                        {% elif text == 'Ma_f' -%}
                        Ma_f
                        {% elif text == 'At_f' -%}
                        At_f
                        {% endif -%}
            - obj: "p1b222"
              properties:
                "text": "{{ states('sensor.esp178_pression_filtre') }} b"       
            - obj: "p1b224"
              properties:
                "text": "{{ states('sensor.esp178_orp_ezo') }} ms"                      
            - obj: "p1b226"
              properties:
                "text": "{{ states('sensor.pzem_pisc_puissance') }} W"
            - obj: "p1b231"
              properties:
                "text": "{{ states('sensor.compteur_energie_piscine_jour_hp_hc') }} kWh"
      # Page2
      
            - obj: "p2b121"  
              properties:
                "val": '{{ 1 if states("switch.esp178_cde_pompe_filtration") == "on" else 0 }}'
                "text": '{{ "\uE12C" if is_state("switch.esp178_cde_pompe_filtration", "on") else "\uE156" | e }}'
                "text_color": "{{ '#00ff00' if is_state('switch.esp178_cde_pompe_filtration', 'on') else '#ff0000' }}" 
              event:
                "up":
                  - service: homeassistant.toggle
                    entity_id: "switch.esp178_cde_pompe_filtration"
      
            - obj: "p2b122"  
              properties:
                "val": '{{ 1 if states("switch.esp178_cde_ppe_ph_moins") == "on" else 0 }}'
                "text": '{{ "\uE12C" if is_state("switch.esp178_cde_ppe_ph_moins", "on") else "\uE156" | e }}'
                "text_color": "{{ '#00ff00' if is_state('switch.esp178_cde_ppe_ph_moins', 'on') else '#ff0000' }}"          
              event:
                "up":
                  - service: homeassistant.toggle
                    entity_id: "switch.esp178_cde_ppe_ph_moins"   
      
            - obj: "p2b123"
              properties:
                "val": '{{ 1 if states("switch.esp178_cde_ppe_chlore") == "on" else 0 }}'
                "text": '{{ "\uE12C" if is_state("switch.esp178_cde_ppe_chlore", "on") else "\uE156" | e }}'
                "text_color": "{{ '#00ff00' if is_state('switch.esp178_cde_ppe_chlore', 'on') else '#ff0000' }}"
              event:
                "up":
                  - service: homeassistant.toggle
                    entity_id: "switch.esp178_cde_ppe_chlore"   
      
            - obj: "p2b124"  
              properties:
                "val": '{{ 1 if states("switch.esp178_cde_volet_ouverture") == "on" else 0 }}'
                "text": '{{ "\uE12C" if is_state("switch.esp178_cde_volet_ouverture", "on") else "\uE156" | e }}'
                "text_color": "{{ '#00ff00' if is_state('switch.esp178_cde_volet_ouverture', 'on') else '#ff0000' }}"
              event:
                "up":
                  - service: homeassistant.toggle
                    entity_id: "switch.esp178_cde_volet_ouverture"
      
            - obj: "p2b125"  
              properties:
                "val": '{{ 1 if states("switch.esp178_cde_volet_fermeture") == "on" else 0 }}'
                "text": '{{ "\uE12C" if is_state("switch.esp178_cde_volet_fermeture", "on") else "\uE156" | e }}'
                "text_color": "{{ '#00ff00' if is_state('switch.esp178_cde_volet_fermeture', 'on') else '#ff0000' }}"
              event:
                "up":
                  - service: homeassistant.toggle
                    entity_id: "switch.esp178_cde_volet_fermeture"
      
            - obj: "p2b126"  
              properties:
                "val": '{{ 1 if states("switch.esp178_cde_eclairage") == "on" else 0 }}'
                "text": '{{ "\uE12C" if is_state("switch.esp178_cde_eclairage", "on") else "\uE156" | e }}'
                "text_color": "{{ '#00ff00' if is_state('switch.esp178_cde_eclairage', 'on') else '#ff0000' }}"          
              event:
                "up":
                  - service: homeassistant.toggle
                    entity_id: "switch.esp178_cde_eclairage"   
      
            - obj: "p2b127"  
              properties:
                "val": '{{ 1 if states("switch.esp178_cde_ev_eau") == "on" else 0 }}'
                "text": '{{ "\uE12C" if is_state("switch.esp178_cde_ev_eau", "on") else "\uE156" | e }}'
                "text_color": "{{ '#00ff00' if is_state('switch.esp178_cde_ev_eau', 'on') else '#ff0000' }}"          
              event:
                "up":
                  - service: homeassistant.toggle
                    entity_id: "switch.esp178_cde_ev_eau"   
      
            - obj: "p2b151"
              event:
                "up":
                  - service: number.decrement
                    target:
                      entity_id: number.esp178_coeff_filtration
      
            - obj: "p2b152"
              properties:
                "text": "{{'%.0f' | format (states('number.esp178_coeff_filtration') | round(0)) }}%"
      
            - obj: "p2b153"
              event:
                "up":
                  - service: number.increment
                    target:
                      entity_id: number.esp178_coeff_filtration
      
                      # Page 3
            - obj: "p3b102"                  
              properties:
                "val": >
                  {% set st = states('select.esp178_mode_fonctionnement_regul_ph')%}
                  {% for text,num in [('Auto',0),('Ma_f',1),('At_f',2) ] %}
                  {% if st == text %}
                    {{ num }}
                  {%endif%}
                  {% endfor %}
              event:
                "changed":
                  - service: select.select_option
                    target:
                      entity_id: select.esp178_mode_fonctionnement_regul_ph
                    data:
                      option: >
                        {% if text == "Auto" -%}
                        Auto
                        {% elif text == 'Ma_f' -%}
                        Ma_f
                        {% elif text == 'At_f' -%}
                        At_f
                        {% endif -%}
      
            - obj: "p3b112"                  
              properties:
                "val": >
                  {% set st = states('select.esp178_mode_fonct_regul_chlore')%}
                  {% for text,num in [('Auto',0),('Ma_f',1),('At_f',2) ] %}
                  {% if st == text %}
                    {{ num }}
                  {%endif%}
                  {% endfor %}
              event:
                "changed":
                  - service: select.select_option
                    target:
                      entity_id: select.esp178_mode_fonct_regul_chlore
                    data:
                      option: >
                        {% if text == "Auto" -%}
                        Auto
                        {% elif text == 'Ma_f' -%}
                        Ma_f
                        {% elif text == 'At_f' -%}
                        At_f
                        {% endif -%}
      
            - obj: "p3b122"                  
              properties:
                "val": >
                  {% set st = states('select.esp178_mode_fonct_appoint_eau')%}
                  {% for text,num in [('Auto',0),('Ma_f',1),('At_f',2) ] %}
                  {% if st == text %}
                    {{ num }}
                  {%endif%}
                  {% endfor %}
              event:
                "changed":
                  - service: select.select_option
                    target:
                      entity_id: select.esp178_mode_fonct_appoint_eau
                    data:
                      option: >
                        {% if text == "Auto" -%}
                        Auto
                        {% elif text == 'Ma_f' -%}
                        Ma_f
                        {% elif text == 'At_f' -%}
                        At_f
                        {% endif -%}
      
            - obj: "p3b132"                  
              properties:
                "val": >
                  {% set st = states('select.esp178_mode_hors_gel')%}
                  {% for text,num in [('Desactivé',0),('Activé',1) ] %}
                  {% if st == text %}
                    {{ num }}
                  {%endif%}
                  {% endfor %}
              event:
                "changed":
                  - service: select.select_option
                    target:
                      entity_id: select.esp178_mode_hors_gel
                    data:
                      option: >
                        {% if text == "Desactivé" -%}
                        Auto
                        {% elif text == 'Activé' -%}
                        Activé
                        {% endif -%}
                        
            - obj: "p3b151"  
              properties:
                "text": "{{'%.0f' | format (states('sensor.esp178_temps_galet_chlore') | round(0)) }}h"
              event:
                "up":
                  - service: button.press
                    target:
                      entity_id: button.esp178_bp_raz_tps_galet_chlore
      
      
      

      Laisser un commentaire

      Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *