Détection début / fin de douche sans rien mettre dans la salle de bains

A la lecture de plusieurs sujets sur la question, j’ai placé un capteur ALPSTUGA sur le tuyau d’évacuation de la salle de bains. Il est donc placé dans la pièce qui se situe sous la salle de bains.

Voici le résultat pendant une douche:

Comme prévu, la température du tuyau PVC monte pendant la douche … et son corollaire, l’humidité autour du tuyau chute (cela a l’air d’être une loi de la physique, augmenter la température sans ajouter d’eau diminue l’humidité relative).

Entre les 2 courbes, je trouve la chute de l’humidité plus franche, alors que la montée en température semble plus « arrondie ». J’ai demandé à copilot de me générer tout ce qu’il faut pour détecter le début et la fin de douche, basé sur l’humidité du capteur ALPSTUGA sur le tuyau d’évacuation. A toutes fins utiles, voici sa réponse:

Je te donne des valeurs initiales qui collent à l’objectif :

  • Début (chute franche) : shower_start_drop_pct = 4.0
  • Fin :
    • shower_end_stable_pct = 0.45 → “la chute sur 2 min est redevenue faible”
    • shower_end_rise_pct = 0.15 → “on a rebondi au moins de 0,15% au-dessus du minimum 5 min”
    • for: 45 seconds → filtre court pour viser ~30–60 s après l’arrêt
    • pente humidité : humidity_rate > 0.30 (%/min) → garantit une vraie inversion de tendance (pas un micro-bruit)

Ces choix sont cohérents avec le fait que tes valeurs changent souvent toutes ~10 s pendant la phase de transition, donc une validation sur 45 s couvre plusieurs points.

1) Helpers (UI) à créer

Dans Paramètres → Appareils & services → Assistants :

A. État

  • input_boolean.shower_active (Douche en cours)

B. Timestamps

  • input_datetime.shower_last_start (Date+heure)
  • input_datetime.shower_last_end (Date+heure)

C. Seuils

  • input_number.shower_start_drop_pct (min 1, max 15, step 0.5, unité %) → 4.0
  • input_number.shower_end_stable_pct (min 0.05, max 2, step 0.05, unité %) → 0.45
  • input_number.shower_end_rise_pct (min 0.05, max 2, step 0.05, unité %) → 0.15
  • (recommandé) input_number.shower_min_duration_min (min 0, max 20, step 1, unité min) → 2

2) Sensors (YAML) : statistiques + pente + templates

À mettre dans configuration.yaml (ou un package). Les entités proviennent de ton export : sensor.alpstuga_air_quality_monitor_humidity.

2.1 Statistics sensors (min/max sur fenêtre)

YAML


sensor:

- platform: statistics

name: "ALPSTUGA Humidity Max 2m"

entity_id: sensor.alpstuga_air_quality_monitor_humidity

state_characteristic: max

max_age:

minutes: 2

- platform: statistics

name: "ALPSTUGA Humidity Min 2m"

entity_id: sensor.alpstuga_air_quality_monitor_humidity

state_characteristic: min

max_age:

minutes: 2

- platform: statistics

name: "ALPSTUGA Humidity Min 5m"

entity_id: sensor.alpstuga_air_quality_monitor_humidity

state_characteristic: min

max_age:

minutes: 5

2.2 Derivative sensor (pente humidité en %/min)

YAML

sensor:

- platform: derivative

name: "ALPSTUGA Humidity Rate"

source: sensor.alpstuga_air_quality_monitor_humidity

unit_time: min

time_window: "00:01:00"

2.3 Template sensors (chute 2m + rebond depuis min 5m)

YAML

template:

- sensor:

- name: "Shower Humidity Drop 2m"

unit_of_measurement: "%"

state: >

{% set hmax = states('sensor.alpstuga_humidity_max_2m')|float(none) %}

{% set hmin = states('sensor.alpstuga_humidity_min_2m')|float(none) %}

{% if hmax is none or hmin is none %}

unknown

{% else %}

{{ (hmax - hmin) | round(2) }}

{% endif %}

- name: "Shower Humidity Rise From Min 5m"

unit_of_measurement: "%"

state: >

{% set h = states('sensor.alpstuga_air_quality_monitor_humidity')|float(none) %}

{% set hmin5 = states('sensor.alpstuga_humidity_min_5m')|float(none) %}

{% if h is none or hmin5 is none %}

unknown

{% else %}

{{ (h - hmin5) | round(2) }}

{% endif %}

3) Automations : événements shower_start et shower_end

3.1 Début de douche (chute franche, maître = humidité)

YAML

automation:

- id: shower_start_by_humidity_drop

alias: "Douche - Début (maître: humidité)"

mode: single

trigger:

- platform: numeric_state

entity_id: sensor.shower_humidity_drop_2m

above: input_number.shower_start_drop_pct

condition:

- condition: state

entity_id: input_boolean.shower_active

state: "off"

action:

- service: input_boolean.turn_on

target:

entity_id: input_boolean.shower_active

- service: input_datetime.set_datetime

target:

entity_id: input_datetime.shower_last_start

data:

datetime: "{{ now().strftime('%Y-%m-%d %H:%M:%S') }}"

- service: event.fire

data:

event_type: shower_start

event_data:

source: "alpstuga_humidity"

humidity: "{{ states('sensor.alpstuga_air_quality_monitor_humidity') }}"

drop_2m: "{{ states('sensor.shower_humidity_drop_2m') }}"

at: "{{ now().isoformat() }}"

3.2 Fin de douche (profil A : au plus près de l’arrêt, 30–60 s)

:backhand_index_pointing_right: Ici, on déclenche quand :

  • la chute sur 2 min devient faible (drop2m < 0.45)
  • la pente devient franchement positive (rate > 0.30 %/min)
  • on a rebondi d’au moins 0.15 au-dessus du minimum des 5 dernières minutes
  • et on valide ça sur 45 secondes
  • en plus d’une durée minimale depuis début (2 min par défaut)

YAML

- id: shower_end_by_humidity_trend_reversal_fast

alias: "Douche - Fin (maître: humidité, profil A ~30-60s)"

mode: single

trigger:

- platform: template

value_template: >

{% set drop2m = states('sensor.shower_humidity_drop_2m')|float(999) %}

{% set rate = states('sensor.alpstuga_humidity_rate')|float(0) %}

{% set rise5m = states('sensor.shower_humidity_rise_from_min_5m')|float(0) %}

{% set stable = states('input_number.shower_end_stable_pct')|float(0.45) %}

{% set rise = states('input_number.shower_end_rise_pct')|float(0.15) %}

{{ drop2m < stable and rate > 0.30 and rise5m > rise }}

for:

seconds: 45

condition:

- condition: state

entity_id: input_boolean.shower_active

state: "on"

- condition: template

value_template: >

{% set min_dur = states('input_number.shower_min_duration_min')|float(0) %}

{% set t = states('input_datetime.shower_last_start') %}

{% if min_dur == 0 or t in ['unknown','unavailable','none',''] %}

true

{% else %}

{{ (as_timestamp(now()) - as_timestamp(t)) >= (min_dur*60) }}

{% endif %}

action:

- service: input_boolean.turn_off

target:

entity_id: input_boolean.shower_active

- service: input_datetime.set_datetime

target:

entity_id: input_datetime.shower_last_end

data:

datetime: "{{ now().strftime('%Y-%m-%d %H:%M:%S') }}"

- service: event.fire

data:

event_type: shower_end

event_data:

source: "alpstuga_humidity"

humidity: "{{ states('sensor.alpstuga_air_quality_monitor_humidity') }}"

drop_2m: "{{ states('sensor.shower_humidity_drop_2m') }}"

rise_from_min_5m: "{{ states('sensor.shower_humidity_rise_from_min_5m') }}"

humidity_rate_pct_per_min: "{{ states('sensor.alpstuga_humidity_rate') }}"

at: "{{ now().isoformat() }}"

4) Vérification / debug rapide

  1. Outils développeur → Événements → Écouter des événements
  • shower_start
  • shower_end
  1. Pendant une douche :
  • observe sensor.alpstuga_humidity_rate (pente)
  • observe sensor.shower_humidity_drop_2m

5) Ajustements ultra rapides (si besoin)

Si “fin” déclenche encore trop tard

  • for: 45s30s
  • rate > 0.300.20
  • rise_pct 0.150.10

Si “fin” déclenche trop tôt (rebond parasite)

  • for: 45s60s
  • rate > 0.300.40
  • rise_pct 0.150.25

Bonjour,
Merci de bien mettre les codes YAML avec indentation, ils sont tous sans indentation (respecte pas les espaces).

Afin de rendre un peu plus “humaine” ta contribution, ce serait vraiment intéressant d’avoir la suite:

  • As tu testé cette solution chez toi ?
  • Ca marche ?
  • Ton retour d’expérience ?

Et comme @WarC0zes au dessus, demande à copilot d’utiliser les bonnes balises <\> lorsqu’il poste du code sur le forum. :rofl:

Bonjour à tous les HAnautes,

Mais c’est une super idée ça , je réfléchissais a mettre un capteur d’humidité dans toutes mes pièces d’eau car ma double flux consomme trop c’est 100 w par heure et l’hiver je l’ai programmé pour fonctionner qu’aux heures de cuisine, par contre pour les salles de bain de l’étage et la douche du RDC c’était difficile de prévoir l’heure d’utilisation de la douche ou de la baignoire.

Il se trouve que j’ai plusieurs ESP32 proche de la trappe du vide sanitaire et le tuyau de vidange de l’étage passe a 1 mètre et celui de la douche du RDC a 2 mètres. Je vais pouvoir ajouter des capteurs de température DS18B20 sur chaque tuyau plus 1 pour connaitre la température du vide sanitaire.

Avec un automatisme basique du genre si la température d’un tuyau est supérieur de X dégrée par rapport a la température du vide sanitaire pendant x secondes alors j’allume la double flux jusqu’a 20 minutes après le retour à l’équilibre.

Un peu de manip et 8 € d’investissement

Génial, merci pour ce partage d’idée

Cordialement,

Jean-Luc

Pour être honnête j’ai repris l’idée qu’on peut trouver par-ci, par-là sur des forums. Ma contribution consiste à dire que l’humidité, qui diminue autour du tuyau lors d’une douche (dérivée de la température) peut-être une valeur intéressante à monitorer.

Non pas encore testé, mais je viens de me rendre compte que l’humidité sur le tuyau peut brutalement chuter pour d’autres raisons, par exemple quand j’ouvre la porte entre la buanderie (sous la douche) et le garage (à croire que l’air y est plus sec, ou alors c’est juste l’appel d’air suite à l’ouverture de la porte).

Donc la bonne méthode, même si je pars sur un trigger à la variation de l’humidité, serait aussi de voir si dans le même temps la température du tuyau varie dans le bon sens et dans les bonnes proportions, afin d’éviter des faux positifs.

Pense à éditer ton sujet et à mettre à jour tous les codes YAML bien indentés.

sensor:
  - platform: derivative
    name: "ALPSTUGA Humidity Rate"
    source: sensor.alpstuga_air_quality_monitor_humidity
    unit_time: min
    time_window: "00:01:00"

Du coup quel est l’objet de ton post ?

Ton code n’est pas récupérable comme expliqué par @WarC0zes donc on ne peut même pas le tester à ta place…

Pas trop compris, si c’est un tuto ou une demande d’aide…

Une démonstration de copilot peut être…

3 « J'aime »

Alors pour le coup je vois très bien l’intérêt! J’avais essayé de faire quelque chose de similaire mais je n’utilisais que la température et ça ne marchait pas, je prends bonnes notes du comportement sur l’humidité !
Pour ceux qui se demandent à quoi ca peut bien servir :
Identifier la quantité d’eau chaude consommée quand on a pas de debit mètre, et en déduire la prévision de consommation électrique du chauffe eau. Coucou ceux avec des panneaux solaires.
Ça reste de l’à peu près mais c’est toujours mieux que rien !
Pour le coup pour le début de la douche j’utilise un détecteur de vibration fixé sur le tuyau d’eau chaude àla cave en sortie de chauffe eau, mais il ne fait que le début des vibrations, pas la fin / la période où ça vibre, du coup c’était galère pour connaître la durée de la douche
J’ai aussi mis une sonde thermohygro dans la salle de bain comme ca quand l’humidité augmente je suis sûr que c’est bien une douche qui est en cours. Et je démarre aussi la vmc en fonction de ça.
Pas utile pour tout le monde mais ça peut servir

Oula attention je ne critique pas l’idée.

Bien au contraire.

Je critique le code non testé…

J’ai mis le code (non testé) pour montrer comment l’idée peut se traduire dans HA (selon copilot) ça permet d’aller plus loin dans le concept. Mon but n’est pas de faire une démonstration copilot, mais de montrer comment cela peut se traduire en code. Désolé pour les balises, j’ai fait du copier coller depuis copilot, mais toutes les lignes de code sont visibles, non ?

Oui, mais c’est mal formaté (indentation mauvaise, ne respecte pas les espaces et des espaces entre les lignes). En l’état ce n’est pas utilisable.

j’ai mis un exemple, le deuxième code que j’ai bien formaté.