telemetry
Quoi de neuf

Tasmota/esphome - ESP32

  • Forum Electricité - Domotique
  • Auteur du sujet Auteur du sujet belgotux
  • Date de début Date de début
  • #21
Tasmota essayé sur un esp32-H2 supermini, ca n'a pas l'air au point pour cette architecture (core dump à gogo).
 
  • #22
Petit projet du jour, mon horloge DCF77 est passée l'arme à gauche les baigneurs rouspètent qu'il ne peuvent plus connaitre l'heure ...

Donc

ESP8266 D1 mini
Connexion Wifi
Interface avec ntp pour obtenir l'heure
Interface KNX pour avoir la température de la piscine
Interface avec un TM1637 pour afficher, sur un 7 segments, tout ça aux bienheureux dans l'eau.
 
Dernière édition:
  • #23
T-Sim 7670E, petit module (42€ aux Pays-Bas) avec ESP32 Wroom, un SOC A7670E, un support pour carte SD et un support de batterie.

Vraiment chouette comme module, mis une carte SIM prépayée et le bidule connecte en mqtt mon serveur mosquitto via la 4G.

Avec un petit serveur web connecté via WiFi pour interagir, les fichiers du serveur sont téléchargés sur la carte SD via une page Web du serveur donc pas besoin de régénérer le firmware quand on veut changer une page.
 
Dernière édition:
  • #24
@jcoenen
Ce "YouTubeur" va bientôt en faire un projet sympa

Il faudrait qu'EspHome intègre ce genre de carte (Tout comme celle en Lora) pour que cela soit facilement accessible à tout le monde.
 
Dernière édition:
  • #25
Ce serait effectivement plus accessible avec EspHome/Tasmota.
 
  • #26
Pas eu beaucoup de temps aujourd'hui, mais j'avance (lentement).

Le module est maintenant capable de servir des clients websocket sur demande.

Pour l'instant 3 commandes sont programmées (dans l'ESP32)

GPS state: Lecture de l'état de l'alimentation du module GPS (On/Off)
is GPS Valid: lecture de l'état du GPS, celui-ci mets un certaine temps à acquérir sa position.
Get GNSS Data: Lecture de la dernière mise à jour de la position

Quand un client fait une requête, tout les autres clients sont prévenu de la réponse, mais cela pourrait très bien être une réponse individuelle.

Pour l'instant tout les clients ont le même code, celui-ci est définit dans un fichier html qui est lui-même sur la carte SD de l'ESP, ce fichier (page web) est lu par les navigateurs (Safari/Firefox/Chrome) qui accèdent au module.
Pour faire simple j'ai mis des boutons location/Get State/Upload to SD/SD Dir/Home qui génèrent directement du code HTML qui est injecté dans une DIV de la page, c'est du HTTP.

En ce qui concerne le WebSocket, le bouton envoi un message au serveur et le serveur répond en envoyant le message à tout les clients (à la différence du HTTP qui ne répond qu'à celui qui en a fait la requête).

Voiçi un exemple avec Safari/Firefox et chrome, les réponse HTML

Screenshot 2025-11-17 at 22.38.07.png


Et ensuite un des navigateur fait une demande et tous reçoivent la réponse (dans ce cas ci la position).

Screenshot 2025-11-17 at 22.38.30.png


On voit donc très bien comment à partir d'un de ces modules on peut faire ce que le youtubeur à la belle casquette se propose de faire (par ailleurs, je me demande bien pourquoi tous ces youtubeurs s'habillent comme des amateurs de foot-balles, serait-ce pour ressembler à leur public ?).

Au cas où le websocket est le mode de communication privilégié par ESPHome, c'est pas mal comme truc tant que le client et le serveur peuvent communiquer, en cela mqtt est supérieur car il ne requiert pas de connexion en direct.

Je vous l'avais bien dit, des heuuuuuures de plaisir.
 
  • #27
Exemple de commande via le module 7670.
Lorsque le module gps a obtenu les infos de géolocalisation des satellites, il envoie via websocket l'état gpsreading:valide.

Le javascript sur le navigateur autorise alors l'usage d'un bouton qu'il met en vert.

L'utilisateur peut alors demander les info de position au module via le bouton.

Les infos sont retournées en javascript et mise dans une boite texte HTML
Screenshot 2025-11-18 at 11.41.54.png



Après on peut faire un peu se qu'on veut, par exemple une page avec les positions sur une carte et mettre a jour en temps réel.
Voiçi un exemple réalisé avec le T-Sim 7600

Screenshot 2025-11-18 at 11.48.41.png
 
  • #28
https://www.action.com/fr-be/p/3202088/prise-connectee-avec-suivi-consommation-lsc-smart-connect/

Inspiré de ce tuto:
https://forum.hacf.fr/t/tuto-lsc-action-power-plug-methode-pour-les-passer-sous-esphome/55780
Mais beaucoup plus simple de les ajouter directement dans ESPhome plutôt que bricoler comme lui...
J'ai customisé le code aussi ;)

https://esphome.io/components/libretiny/

1000041014.jpg

  • A démonter avec un petit tournevis plat.
  • Souder les fil sur les 4 pins
  • Prévoir un double GND et étamer la pin CEN pour faire un pont lors du flash
  • Raccorder à l'usb série en croisant RX/TX
  • Dans ESPhome faire un nouveau device avec bk72xx et cb2s
  • Faire le pont entre GND et CEN quand ESPhome le demande
  • Code à ajouter à la configuration de base:
Code:
# Code pour la prise LSC:

substitutions:
  voltage_divider: '795'
  current_resistor: '0.001'
  current_multiply: '0.450'
# Calibrer selon https://esphome.io/components/sensor/hlw8012/

globals:
  - id: timer_remaining_seconds
    type: int
    initial_value: '0'
    restore_value: no

button:
  - platform: restart
    name: Restart

  - platform: template
    name: "Démarrer Timer"
    id: start_timer_btn
    icon: mdi:timer-play
    on_press:
      - script.stop: timer_logic
      - script.execute: timer_logic

number:
  - platform: template
    name: "Durée Timer (min)"
    id: timer_duration_input
    optimistic: true
    min_value: 1
    max_value: 240
    step: 1
    mode: box
    initial_value: 30
    icon: mdi:timer-cog

sensor:
  # Timer Display
  - platform: template
    name: "Temps Restant"
    id: timer_remaining_display
    icon: mdi:timer-sand
    unit_of_measurement: "min"
    accuracy_decimals: 0
    lambda: |-
       return (id(timer_remaining_seconds) > 0) ? (id(timer_remaining_seconds) / 60.0) : 0;
    update_interval: never

  # Power Monitoring (BL0937)
  - platform: hlw8012
    model: BL0937
    update_interval: 500ms
    change_mode_every: 2
    cf_pin:
      number: P26
      inverted: true
    cf1_pin:
      number: P24
      inverted: true
    sel_pin:
      number: P11
      inverted: true
    current:
      name: Current
      id: current
      accuracy_decimals: 3
      on_value:
        component.update: apparent_power
      filters:
        - multiply: ${current_multiply}
        - sliding_window_moving_average:
            window_size: 4
            send_every: 2
    voltage:
      name: Voltage
      id: voltage
      on_value:
        component.update: apparent_power
      filters:
        - sliding_window_moving_average:
            window_size: 4
            send_every: 2
    power:
      name: Power
      id: power
      on_value:
        component.update: power_factor
      filters:
        - sliding_window_moving_average:
            window_size: 4
            send_every: 2
    energy:
      name: Energy
    voltage_divider: ${voltage_divider}
    current_resistor: ${current_resistor}

  # Template Sensors (Calculs)
  - platform: template
    name: "Apparent power"
    id: apparent_power
    unit_of_measurement: VA
    device_class: apparent_power
    lambda: |-
      return id(voltage).state * id(current).state;
    update_interval: never
    on_value:
        component.update: power_factor
  - platform: template
    name: "Power factor"
    id: power_factor
    unit_of_measurement: ''
    device_class: power_factor
    lambda: |-
      return id(power).state / id(apparent_power).state;
    filters:
      - clamp:
          min_value: 0
          max_value: 1
    update_interval: never
 
  - platform: uptime
    name: Uptime

# --- TEXT SENSORS ---
text_sensor:
  - platform: debug
    reset_reason:
      name: Reset Reason
  - platform: libretiny
    version:
      name: LibreTiny Version

# --- DEBUG ---
debug:
  update_interval: 30s

# --- SWITCH & OUTPUTS ---
binary_sensor:
  - platform: gpio
    id: binary_switch_1
    pin:
      number: P7
      inverted: true
      mode: INPUT_PULLUP
    filters:
      - delayed_on: 10ms
    on_press:
      then:
        - switch.toggle: switch_1

switch:
  - platform: gpio
    id: switch_1
    name: none
    pin: P8
    restore_mode: ALWAYS_OFF
    on_turn_on:
      script.execute: set_status_led
    on_turn_off:
      script.execute: set_status_led

light:
  - platform: status_led
    id: light_red
    name: "Red led"
    pin: P6
    restore_mode: RESTORE_DEFAULT_OFF
  - platform: binary
    name: "Status led"
    id: blue_led
    output: output_blue_led
    restore_mode: RESTORE_DEFAULT_OFF
    internal: true

output:
  - platform: gpio
    id: output_blue_led
    pin: P10

select:
  - platform: template
    name: "Status led mode"
    id: status_led_mode
    optimistic: true
    restore_value: True
    entity_category: CONFIG
    update_interval: never
    options:
      - "Normal"
      - "Invert"
      - "Off"
    initial_option: "Normal"
    on_value:
      script.execute: set_status_led

# --- SCRIPTS ---
script:
  - id: set_status_led
    then:
      - if:
          condition:
            lambda: |-
              return strcmp(id(status_led_mode).state.c_str(), "Normal") == 0;
          then:
            if:
              condition:
                switch.is_on: switch_1
              then:
                light.turn_on: blue_led
              else:
                light.turn_off: blue_led
      - if:
          condition:
            lambda: |-
              return strcmp(id(status_led_mode).state.c_str(), "Invert") == 0;
          then:
            if:
              condition:
                switch.is_on: switch_1
              then:
                light.turn_off: blue_led
              else:
                light.turn_on: blue_led
      - if:
          condition:
            lambda: |-
              return strcmp(id(status_led_mode).state.c_str(), "Off") == 0;
          then:
            light.turn_off: blue_led

  - id: timer_logic
    then:
      - lambda: 'id(timer_remaining_seconds) = id(timer_duration_input).state * 60;'
      - component.update: timer_remaining_display
     
      - switch.turn_on: switch_1
     
      - while:
          condition:
            lambda: 'return id(timer_remaining_seconds) > 0;'
          then:
            - delay: 1s
            - lambda: 'id(timer_remaining_seconds) -= 1;'
           
            - if:
                condition:
                  lambda: 'return (id(timer_remaining_seconds) % 60 == 0) || (id(timer_remaining_seconds) < 60);'
                then:
                  - component.update: timer_remaining_display

            - if:
                condition:
                  switch.is_off: switch_1
                then:
                  - lambda: 'id(timer_remaining_seconds) = 0;'
                  - component.update: timer_remaining_display
                  - script.stop: timer_logic

      - switch.turn_off: switch_1
      - lambda: 'id(timer_remaining_seconds) = 0;'
      - component.update: timer_remaining_display

Méthode pour calibrer au besoin:
https://esphome.io/components/sensor/hlw8012/
 
Dernière édition:
  • #29
Joli, quel firmware utilises tu ?
 
  • #30
Joli, quel firmware utilises tu ?
ESPhome
Je termine le tuto rapide :D

Edit, ajout de fonctions sympas....

Code:
# Code Prise LSC

substitutions:
  voltage_divider: '795'
  current_resistor: '0.001'
  current_multiply: '0.450'
# Calibrer selon [https://esphome.io/components/sensor/hlw8012/](https://esphome.io/components/sensor/hlw8012/)

globals:
  - id: timer_remaining_seconds
    type: int
    initial_value: '0'
    restore_value: no

button:
  - platform: restart
    name: Restart

  - platform: template
    name: "Démarrer Timer"
    id: start_timer_btn
    icon: mdi:timer-play
    on_press:
      - script.stop: timer_logic
      - script.execute: timer_logic

number:
  - platform: template
    name: "Durée Timer (min)"
    id: timer_duration_input
    optimistic: true
    min_value: 1
    max_value: 240
    step: 1
    mode: box
    initial_value: 30
    icon: mdi:timer-cog

sensor:
  # Timer Display
  - platform: template
    name: "Temps Restant"
    id: timer_remaining_display
    icon: mdi:timer-sand
    unit_of_measurement: "min"
    accuracy_decimals: 0
    lambda: |-
       return (id(timer_remaining_seconds) > 0) ? (id(timer_remaining_seconds) / 60.0) : 0;
    update_interval: never

  # Power Monitoring (BL0937)
  - platform: hlw8012
    model: BL0937
    update_interval: 500ms
    change_mode_every: 2
    cf_pin:
      number: P26
      inverted: true
    cf1_pin:
      number: P24
      inverted: true
    sel_pin:
      number: P11
      inverted: true
    current:
      name: Current
      id: current
      accuracy_decimals: 3
      on_value:
        component.update: apparent_power
      filters:
        - multiply: ${current_multiply}
        - sliding_window_moving_average:
            window_size: 4
            send_every: 2
    voltage:
      name: Voltage
      id: voltage
      on_value:
        component.update: apparent_power
      filters:
        - sliding_window_moving_average:
            window_size: 4
            send_every: 2
    power:
      name: Power
      id: power
      on_value:
        component.update: power_factor
      filters:
        - sliding_window_moving_average:
            window_size: 4
            send_every: 2
    
    energy:
      name: Energy
    voltage_divider: ${voltage_divider}
    current_resistor: ${current_resistor}

  # Template Sensors (Calculs)
  - platform: template
    name: "Apparent power"
    id: apparent_power
    unit_of_measurement: VA
    device_class: apparent_power
    lambda: |-
      return id(voltage).state * id(current).state;
    update_interval: never
    on_value:
        component.update: power_factor
  - platform: template
    name: "Power factor"
    id: power_factor
    unit_of_measurement: ''
    device_class: power_factor
    lambda: |-
      if (id(apparent_power).state == 0) return 0;
      return id(power).state / id(apparent_power).state;
    filters:
      - clamp:
          min_value: 0
          max_value: 1
    update_interval: never
 
  - platform: uptime
    name: Uptime

# --- TEXT SENSORS ---
text_sensor:
  - platform: debug
    reset_reason:
      name: Reset Reason
  - platform: libretiny
    version:
      name: LibreTiny Version

# --- DEBUG ---
debug:
  update_interval: 30s

# --- SWITCH & OUTPUTS ---
binary_sensor:
  - platform: gpio
    id: binary_switch_1
    pin:
      number: P7
      inverted: true
      mode: INPUT_PULLUP
    filters:
      - delayed_on: 10ms
    on_multi_click:
      - timing:
          - ON for at most 1s
          - OFF for at most 1s
          - ON for at most 1s
        then:
          - logger.log: "Double Clic -> Timer !"
          - script.stop: timer_logic
          - script.execute: timer_logic
      - timing:
          - ON for at most 1s
          - OFF for at least 0.5s
        then:
          - switch.toggle: switch_1

switch:
  - platform: gpio
    id: switch_1
    name: none
    pin: P8
    restore_mode: ALWAYS_OFF
    on_turn_on:
      script.execute: set_status_led
    on_turn_off:
      script.execute: set_status_led
  - platform: template
    name: "Mode Fin de Charge Auto"
    id: auto_off_mode
    optimistic: true
    icon: mdi:battery-charging-100
    restore_mode: RESTORE_DEFAULT_OFF # Par défaut désactivé au démarrage pour sécurité

light:
  - platform: status_led
    id: light_red
    name: "Red led"
    pin: P6
    restore_mode: RESTORE_DEFAULT_OFF
  - platform: binary
    name: "Status led"
    id: blue_led
    output: output_blue_led
    restore_mode: RESTORE_DEFAULT_OFF
    internal: true

output:
  - platform: gpio
    id: output_blue_led
    pin: P10

select:
  - platform: template
    name: "Status led mode"
    id: status_led_mode
    optimistic: true
    restore_value: True
    entity_category: CONFIG
    update_interval: never
    options:
      - "Normal"
      - "Invert"
      - "Off"
    initial_option: "Normal"
    on_value:
      script.execute: set_status_led

# --- INTERVAL CHECK FOR AUTO OFF ---
interval:
  - interval: 10s
    then:
      - if:
          condition:
            and:
              - switch.is_on: auto_off_mode
              - switch.is_on: switch_1
              # On vérifie si la puissance est < 5W
              - lambda: 'return id(power).state < 5.0;'
          then:
             # Lancement du script de délai (qui s'arrête si condition fausse)
             - script.execute: check_low_power_shutdown
          else:
             # Si la puissance remonte ou mode désactivé, on annule
             - script.stop: check_low_power_shutdown

# --- SCRIPTS ---
script:
  - id: set_status_led
    then:
      - if:
          condition:
            lambda: |-
              return strcmp(id(status_led_mode).state.c_str(), "Normal") == 0;
          then:
            if:
              condition:
                switch.is_on: switch_1
              then:
                light.turn_on: blue_led
              else:
                light.turn_off: blue_led
      - if:
          condition:
            lambda: |-
              return strcmp(id(status_led_mode).state.c_str(), "Invert") == 0;
          then:
            if:
              condition:
                switch.is_on: switch_1
              then:
                light.turn_off: blue_led
              else:
                light.turn_on: blue_led
      - if:
          condition:
            lambda: |-
              return strcmp(id(status_led_mode).state.c_str(), "Off") == 0;
          then:
            light.turn_off: blue_led

  - id: timer_logic
    then:
      - lambda: 'id(timer_remaining_seconds) = id(timer_duration_input).state * 60;'
      - component.update: timer_remaining_display
      
      - switch.turn_on: switch_1
      
      - while:
          condition:
            lambda: 'return id(timer_remaining_seconds) > 0;'
          then:
            - delay: 1s
            - lambda: 'id(timer_remaining_seconds) -= 1;'
            
            - if:
                condition:
                  lambda: 'return (id(timer_remaining_seconds) % 60 == 0) || (id(timer_remaining_seconds) < 60);'
                then:
                  - component.update: timer_remaining_display

            - if:
                condition:
                  switch.is_off: switch_1
                then:
                  - lambda: 'id(timer_remaining_seconds) = 0;'
                  - component.update: timer_remaining_display
                  - script.stop: timer_logic

      - switch.turn_off: switch_1
      - lambda: 'id(timer_remaining_seconds) = 0;'
      - component.update: timer_remaining_display

  - id: check_low_power_shutdown
    mode: restart
    then:
      - delay: 2min
      - logger.log: "Charge terminée (<5W). Arrêt automatique."
      - switch.turn_off: switch_1
      - switch.turn_off: auto_off_mode
 
Dernière édition:
  • #31
@RobBZ Bonjour, tout ce que vous présentez suppose que Esphome est déjà utilisé. Moi, je serais intéressé par l'utilisation de la partie wattmetre (via interface web et MQTT je suppose). Serait-il possible de mettre le fichier UF2 à disposition?
 
  • #33
Je comprends, merci
 
  • #34
Firmware open BK ?

On peut configurer l’IP et les infos du broker mqtt sans devoir passer par esphome (qui soi dit en passant est natif en websocket).

On peut cependant configurer ESPhome pour accéder un broker mqtt, après pour la configuration publish/subscribe voir dans la doc.

ESPhome peut être installé hors de Homeassistant, sur winproute, OSX ou Linux, c'est du python donc ca s'installe facile avec pip.

On peut l'installer et ensuite le connecter à homeassistant c'est pratique quand on utilise HA dans une LXC.
 
Dernière édition:
  • #36
Je viens d'aller lire la doc ESPhome sur MQTT.
Il est effectivement possible de configurer esphome pour utiliser un broker mqtt (genre mosquitto) sans devoir passer par Homeassistant, il est possible de configurer des publish pour les infos à envoyer (lectures de puissance/voltage/courrant et les moyennes) ainsi que de configurer des subscribe pour les commandes (On/Off, reset statistics ...). Juste pour la bonne bouche, il est possible d'implémenter un broker mqtt sur un esp32.

Ce qui pourrait être intéressant pour distribuer des brokers dans la topologie du bâtiment, après on peut configurer le broker principal (mosquitto) de façon à filtrer les messages pour les brokers secondaires (l'ESP32 a quant même ses limites).
 
  • #37
Viens de recevoir un nouveau jouet, T-SIM 7670G S3
Je suis assez déçu du T-SIM 7670E, le GPS ne semble pas très précis et j'ai zingué le connecteur USB pour mettre à jour le firmware du module A7670, donc suis concé avec le firm installé que je soupçonne d'être responsable de la chose.

Après avoir comparé Ali et tinytronics, je me suis rendu compte qu'ils étaient quasi au même prix aux pays-bas, faut juste rajouter l'expédition, mais si on commande quelques pièces on s'y retrouve et on reçoit après deux jours.

Avec le firm installé je vois déjà une différence sur le temps de réponse de S3 par rapport au ESP32 classique, c'est quasi instantané alors que sur le classique on doit un peu attendre.

Par contre il semblerait y avoir un bug dans le firmware installé (mqtt do not Connect), donc je vais commencer par mettre ça à jour.
 
  • #38
Modem mis à jour, pénible la procédure mais au final successfull.

C'est un des problèmes. avec ces modules chinois, ils vont trop vite pour les sortir, donc pour le même genre de module la procédure est "presque" la même mais légèrement différente. Donc lors d'une mise à jour il faut y aller doucement. De plus le modem est mis a jour par un second port USB, et celui-ci n'est visible par Windproute que pendant quelques secondes. Le flasher doit être configuré pendant ces quelques secondes sinon le port disparait et n'est plus disponible dans la liste, ça on n'en parle pas trop, heureusement ils ont mis une video.

C'est quant même beaucoup plus simple quand open sait ce que l'on doit faire et à quoi on doit faire attention.

Voiçi ce que ça donne, j'avais la 2374B04SIM767XM5A et maintenant c'est la dernière stable 2374B05V01SIM767XM5A (il y en une nouvelle qui est en développement Latest: 2388B03SIM767XM5A Not recommended to use it; there are many problems :joy::joy::joy:.


Screenshot 2025-12-10 at 21.24.03.png
 
  • #39
Le S3 est vraiment un monstre de puissance. Je me demande si je vais pas mettre les éclairages au complet de ma maison dessus...
 
  • #40
Oui, il m'impressionne, le LX7 est donné 2x plus rapide que le LX6.


Mille pétards, la version des commandes AT du S3 est antérieure à celle du ESP32.

Les commandes ont changé, rontidjuuuu je dois réécrire le bazar.
 
Dernière édition:

Sujet semblables

Réponses
·
Affichages
215
yoshisdown
Réponses
10
Affichages
1K
koreon
Réponses
1
Affichages
437
baziles18
Réponses
·
Affichages
589
belgotux
Réponses
37
Affichages
2K
@lex

Nos articles

On a aimé dans le forum

Retour
Haut