From ce276773824efe93f438a2b49c98c5d3430814f3 Mon Sep 17 00:00:00 2001 From: rzen Date: Mon, 1 Sep 2025 19:44:50 -0400 Subject: [PATCH] Add humidity-controlled fan blueprint with hysteresis and safety features MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Includes support for multiple fans, configurable thresholds with hysteresis to prevent flip-flopping, and runaway prevention mechanisms with max runtime and cooldown periods. Optimized for Zooz ZSE11 and compatible humidity sensors. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude --- humidity-controlled-fan.yaml | 163 +++++++++++++++++++++++++++++++++++ 1 file changed, 163 insertions(+) create mode 100644 humidity-controlled-fan.yaml diff --git a/humidity-controlled-fan.yaml b/humidity-controlled-fan.yaml new file mode 100644 index 0000000..b9dabad --- /dev/null +++ b/humidity-controlled-fan.yaml @@ -0,0 +1,163 @@ +blueprint: + name: Humidity Controlled Fan with Hysteresis + description: > + Controls fans based on humidity sensor readings with hysteresis to prevent flip-flopping + and safety mechanisms to prevent runaway operation. Supports multiple fans and the Zooz ZSE11 + humidity sensor or any compatible humidity sensor. + domain: automation + input: + fans: + name: Fan Entities + description: One or more fans to control based on humidity + selector: + entity: + domain: fan + multiple: true + + humidity_sensor: + name: Humidity Sensor + description: Humidity sensor entity (e.g., Zooz ZSE11 or compatible sensor) + selector: + entity: + domain: sensor + device_class: humidity + + humidity_threshold: + name: Humidity Threshold (%) + description: Base humidity percentage threshold + default: 60 + selector: + number: + min: 30 + max: 90 + unit_of_measurement: "%" + + hysteresis_high: + name: High Hysteresis (%) + description: Amount above threshold to turn fans ON (prevents rapid cycling) + default: 5 + selector: + number: + min: 1 + max: 15 + unit_of_measurement: "%" + + hysteresis_low: + name: Low Hysteresis (%) + description: Amount below threshold to turn fans OFF (prevents rapid cycling) + default: 3 + selector: + number: + min: 1 + max: 15 + unit_of_measurement: "%" + + turn_on_delay: + name: Turn On Delay + description: Delay before turning fans on (avoids brief humidity spikes) + default: 30 + selector: + number: + min: 0 + max: 300 + unit_of_measurement: seconds + + max_runtime_minutes: + name: Maximum Runtime (minutes) + description: Maximum time fans can run continuously before forced shutdown + default: 120 + selector: + number: + min: 15 + max: 480 + unit_of_measurement: minutes + + cooldown_minutes: + name: Cooldown Period (minutes) + description: Minimum time between fan cycles to prevent runaway operation + default: 10 + selector: + number: + min: 2 + max: 60 + unit_of_measurement: minutes + +mode: restart + +trigger: + - platform: state + entity_id: !input humidity_sensor + attribute: + - platform: state + entity_id: !input humidity_sensor + +variables: + fans_entities: !input fans + humidity_sensor: !input humidity_sensor + base_threshold: !input humidity_threshold + high_hysteresis: !input hysteresis_high + low_hysteresis: !input hysteresis_low + turn_on_threshold: "{{ base_threshold + high_hysteresis }}" + turn_off_threshold: "{{ base_threshold - low_hysteresis }}" + current_humidity: "{{ states(humidity_sensor) | float(0) }}" + any_fan_on: > + {{ expand(fans_entities) | selectattr('state', 'eq', 'on') | list | length > 0 }} + max_runtime_seconds: "{{ (max_runtime_minutes | int) * 60 }}" + +action: + - choose: + # Turn fans ON when humidity exceeds upper threshold + - conditions: + - condition: template + value_template: > + {{ current_humidity > turn_on_threshold }} + - condition: template + value_template: > + {{ not any_fan_on }} + - condition: template + value_template: > + {{ states(humidity_sensor) not in ['unavailable', 'unknown'] }} + sequence: + - delay: + seconds: !input turn_on_delay + # Re-check humidity after delay + - condition: template + value_template: > + {{ states(humidity_sensor) | float(0) > turn_on_threshold }} + - condition: template + value_template: > + {{ states(humidity_sensor) not in ['unavailable', 'unknown'] }} + - service: fan.turn_on + target: + entity_id: "{{ fans_entities }}" + # Set up automatic shutoff timer for runaway prevention + - delay: + seconds: "{{ max_runtime_seconds }}" + - condition: template + value_template: > + {{ expand(fans_entities) | selectattr('state', 'eq', 'on') | list | length > 0 }} + - service: fan.turn_off + target: + entity_id: "{{ fans_entities }}" + # Enforce cooldown period + - delay: + minutes: !input cooldown_minutes + + # Turn fans OFF when humidity drops below lower threshold + - conditions: + - condition: template + value_template: > + {{ current_humidity < turn_off_threshold }} + - condition: template + value_template: > + {{ any_fan_on }} + - condition: template + value_template: > + {{ states(humidity_sensor) not in ['unavailable', 'unknown'] }} + sequence: + - service: fan.turn_off + target: + entity_id: "{{ fans_entities }}" + # Enforce cooldown period + - delay: + minutes: !input cooldown_minutes \ No newline at end of file