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.0input_number.shower_end_stable_pct(min 0.05, max 2, step 0.05, unité%) → 0.45input_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)
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.15au-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
- Outils développeur → Événements → Écouter des événements
shower_startshower_end
- 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: 45s→ 30srate > 0.30→ 0.20rise_pct 0.15→ 0.10
Si “fin” déclenche trop tôt (rebond parasite)
for: 45s→ 60srate > 0.30→ 0.40rise_pct 0.15→ 0.25

