From b68e9ec3d2da1c21049598e53137a63a4ecf9ee2 Mon Sep 17 00:00:00 2001 From: rzen Date: Fri, 4 Jul 2025 20:16:15 +0000 Subject: [PATCH] initial commit --- battery-monitor.yaml | 75 +++++++++ fan-management.yaml | 107 +++++++++++++ hvac-failure-monitor.yaml | 165 ++++++++++++++++++++ indication.yaml | 119 ++++++++++++++ multi-tap-automation-homeseer-and-zooz.yaml | 90 +++++++++++ multi-tap-automation.yaml | 83 ++++++++++ power-monitoring.yaml | 80 ++++++++++ simulated-presence.yaml | 77 +++++++++ state-opposite.yaml | 75 +++++++++ 9 files changed, 871 insertions(+) create mode 100644 battery-monitor.yaml create mode 100644 fan-management.yaml create mode 100644 hvac-failure-monitor.yaml create mode 100644 indication.yaml create mode 100644 multi-tap-automation-homeseer-and-zooz.yaml create mode 100644 multi-tap-automation.yaml create mode 100644 power-monitoring.yaml create mode 100644 simulated-presence.yaml create mode 100644 state-opposite.yaml diff --git a/battery-monitor.yaml b/battery-monitor.yaml new file mode 100644 index 0000000..36e5b4d --- /dev/null +++ b/battery-monitor.yaml @@ -0,0 +1,75 @@ +blueprint: + name: Battery Monitor + description: Monitors battery levels of selected entities and exposes a low battery summary + domain: automation + input: + battery_sensors: + name: Battery Sensors + description: List of battery level sensors to monitor + selector: + entity: + domain: sensor + multiple: true + threshold: + name: Low Battery Threshold + description: Battery percentage threshold to consider "low" + default: 20 + selector: + number: + min: 1 + max: 100 + step: 1 + unit_of_measurement: "%" + notify_service: + name: Notification Service (Optional) + description: Service to call if any battery is low (e.g., notify.mobile_app_pixel) + default: "" + selector: + text: + +mode: single + +trigger: + - platform: time_pattern + minutes: "/30" # Check every 30 minutes + +variables: + threshold: !input threshold + battery_sensors: !input battery_sensors + notify_service: !input notify_service + +condition: [] + +action: + - variables: + low_batteries: > + {% set low = namespace(devices=[]) %} + {% for entity_id in battery_sensors %} + {% set level = states(entity_id) | int(100) %} + {% if level <= threshold %} + {% set name = state_attr(entity_id, 'friendly_name') or entity_id %} + {% set low.devices = low.devices + [name ~ ' (' ~ level ~ '%)'] %} + {% endif %} + {% endfor %} + {{ low.devices }} + + - choose: + - conditions: "{{ low_batteries | length > 0 }}" + sequence: + - service: input_text.set_value + target: + entity_id: input_text.devices_with_low_battery + data: + value: "{{ low_batteries | join(', ') }}" + - condition: "{{ notify_service != '' }}" + - service: "{{ notify_service }}" + data: + message: > + Low battery detected: {{ low_batteries | join(', ') }} + default: + - service: input_text.set_value + target: + entity_id: input_text.devices_with_low_battery + data: + value: "All batteries healthy" + diff --git a/fan-management.yaml b/fan-management.yaml new file mode 100644 index 0000000..31f60dd --- /dev/null +++ b/fan-management.yaml @@ -0,0 +1,107 @@ +blueprint: + name: Bathroom Fan Controller + description: > + Turns on the fan when any bathroom light is on (after a delay), keeps it on + after all lights are off for a specified time, and also runs the fan on a + regular cadence (e.g., every hour for 5 minutes). + domain: automation + input: + fan_entity: + name: Bathroom Fan + description: The fan to control + selector: + entity: + domain: fan + bathroom_lights: + name: Bathroom Lights + description: One or more lights in the bathroom + selector: + entity: + domain: light + multiple: true + delay_after_light_on: + name: Delay After Light On + description: Delay before turning on the fan once any light is turned on + default: 0 + selector: + duration: + time_fan_stays_on_after_lights_off: + name: Duration Fan Stays On After Lights Off + description: How long the fan should stay on after all lights are off + default: 00:05:00 + selector: + duration: + cadence_enabled: + name: Enable Cadence Mode + description: Enable periodic fan activation + default: true + selector: + boolean: + cadence_interval: + name: Cadence Interval + description: Time between fan activations + default: 01:00:00 + selector: + duration: + cadence_duration: + name: Cadence Duration + description: How long the fan stays on during each cadence + default: 00:05:00 + selector: + duration: + +mode: parallel +max: 5 + +trigger: + - platform: state + entity_id: !input bathroom_lights + from: 'off' + to: 'on' + - platform: state + entity_id: !input bathroom_lights + to: 'off' + for: !input time_fan_stays_on_after_lights_off + - platform: time_pattern + minutes: "/5" + +condition: [] + +action: + - choose: + - conditions: + - condition: template + value_template: > + {{ trigger.platform == 'state' and + trigger.to_state.state == 'on' }} + sequence: + - delay: !input delay_after_light_on + - service: fan.turn_on + target: + entity_id: !input fan_entity + + - conditions: + - condition: template + value_template: > + {{ trigger.platform == 'state' and + trigger.to_state.state == 'off' and + expand(inputs.bathroom_lights) | selectattr('state','eq','on') | list | count == 0 }} + sequence: + - delay: !input time_fan_stays_on_after_lights_off + - service: fan.turn_off + target: + entity_id: !input fan_entity + + - conditions: + - condition: template + value_template: > + {{ trigger.platform == 'time_pattern' and cadence_enabled }} + sequence: + - service: fan.turn_on + target: + entity_id: !input fan_entity + - delay: !input cadence_duration + - service: fan.turn_off + target: + entity_id: !input fan_entity + diff --git a/hvac-failure-monitor.yaml b/hvac-failure-monitor.yaml new file mode 100644 index 0000000..45b0c8d --- /dev/null +++ b/hvac-failure-monitor.yaml @@ -0,0 +1,165 @@ +blueprint: + name: HVAC Failure Monitor + description: > + Detects HVAC underperformance and hard failure by monitoring temperature trends when heating or cooling is active. + Uses differential between setpoint and outdoor temp to dynamically adjust expectations. + domain: automation + input: + thermostat: + name: Thermostat + description: The climate entity to monitor (must support hvac_action and setpoint attributes). + selector: + entity: + domain: climate + + heating_temp_sensors: + name: Heating Temperature Sensors + description: One or more temperature sensors to monitor during heating (e.g. upstairs). + default: [] + selector: + target: + entity: + domain: sensor + device_class: temperature + + cooling_temp_sensors: + name: Cooling Temperature Sensors + description: One or more temperature sensors to monitor during cooling (e.g. downstairs). + default: [] + selector: + target: + entity: + domain: sensor + device_class: temperature + + outdoor_sensor: + name: Outdoor Temperature Source + description: Outdoor temperature source (e.g. from a weather entity). + selector: + entity: + domain: weather + + monitoring_interval: + name: Monitoring Interval (minutes) + description: How long after HVAC starts to evaluate temperature change. + default: 20 + selector: + number: + min: 5 + max: 120 + unit_of_measurement: minutes + mode: slider + + notify_target: + name: Notification Target + description: Who to notify on potential HVAC failure (e.g. mobile app). + default: [] + selector: + target: + entity: + domain: notify + +mode: single + +trigger: + - platform: state + entity_id: !input thermostat + attribute: hvac_action + to: + - heating + - cooling + +variables: + thermostat: !input thermostat + heating_temp_sensors: !input heating_temp_sensors + cooling_temp_sensors: !input cooling_temp_sensors + outdoor_sensor: !input outdoor_sensor + interval: !input monitoring_interval + hvac_action: "{{ state_attr(thermostat, 'hvac_action') }}" + direction: > + {{ 'rising' if hvac_action == 'heating' else 'falling' }} + selected_sensors: > + {{ heating_temp_sensors if hvac_action == 'heating' else cooling_temp_sensors }} + +condition: [] + +action: + - variables: + indoor_start: > + {{ expand(selected_sensors) | map(attribute='state') | map('float') | select('defined') | list | average }} + + - delay: + minutes: "{{ interval }}" + + - variables: + indoor_now: > + {{ expand(selected_sensors) | map(attribute='state') | map('float') | select('defined') | list | average }} + outdoor_now: > + {{ state_attr(outdoor_sensor, 'temperature') | float }} + setpoint: > + {{ state_attr(thermostat, 'temperature') | float }} + delta: > + {{ abs(setpoint - outdoor_now) }} + required_rate: > + {% set d = delta %} + {{ [0.01, [0.10, 0.10 - (d * 0.004)] | min] | max }} + observed_rate: > + {{ ((indoor_now - indoor_start) / interval) | round(3) }} + trend_ok: > + {% if direction == 'rising' %} + {{ observed_rate >= required_rate }} + {% else %} + {{ observed_rate <= -required_rate }} + {% endif %} + hard_failure: > + {% if direction == 'rising' %} + {{ observed_rate < 0 }} + {% else %} + {{ observed_rate > 0 }} + {% endif %} + hvac_state_icon: > + {% if hard_failure %} + mdi:close-circle-outline + {% elif not trend_ok %} + mdi:alert-circle-outline + {% else %} + mdi:check-circle-outline + {% endif %} + hvac_state_text: > + {% if hard_failure %} + HVAC Failure + {% elif not trend_ok %} + Possible HVAC underperformance + {% else %} + Normal operation + {% endif %} + + - choose: + - conditions: "{{ not trend_ok }}" + sequence: + - choose: + - conditions: "{{ notify_target | length > 0 }}" + sequence: + - service: notify.{{ notify_target }} + data: + message: > + HVAC '{{ hvac_action }}' action for {{ interval }} minutes showed ineffective operation. + Indoor temp started at: {{ indoor_start }}°, now: {{ indoor_now }}° + Outdoor temp: {{ outdoor_now }}° + Setpoint: {{ setpoint }}° + Required rate: {{ required_rate }}°/min + Observed rate: {{ observed_rate }}°/min + Status: {{ hvac_state_text }} {{ hvac_state_icon }} + default: + - service: persistent_notification.create + data: + title: HVAC Alert + message: > + HVAC '{{ hvac_action }}' action for {{ interval }} minutes showed ineffective operation. + Indoor temp started at: {{ indoor_start }}°, now: {{ indoor_now }}° + Outdoor temp: {{ outdoor_now }}° + Setpoint: {{ setpoint }}° + Required rate: {{ required_rate }}°/min + Observed rate: {{ observed_rate }}°/min + Status: {{ hvac_state_text }} {{ hvac_state_icon }} + diff --git a/indication.yaml b/indication.yaml new file mode 100644 index 0000000..de86717 --- /dev/null +++ b/indication.yaml @@ -0,0 +1,119 @@ +blueprint: + name: HS-WD200+ LED State Indicator + description: Set a specific LED on a HomeSeer WD200+ dimmer based on entity state. + domain: automation + input: + target_device: + name: HS-WD200+ Device + selector: + device: + integration: zwave_js + + monitored_entity: + name: Entity to Monitor + selector: + entity: {} + + expected_state: + name: State to Match + description: Select a common state or enter a custom one below. + selector: + select: + options: + - "on" + - "off" + - "home" + - "away" + - "cool" + - "heat" + - "idle" + - "open" + - "closed" + - "locked" + - "unlocked" + + custom_expected_state: + name: Custom State (optional) + description: Use this if the expected state is not in the list above. + default: "" + selector: + text: {} + + led_number: + name: LED Number + selector: + select: + options: + - label: "LED 1 (Top)" + value: "1" + - label: "LED 2" + value: "2" + - label: "LED 3" + value: "3" + - label: "LED 4" + value: "4" + - label: "LED 5" + value: "5" + - label: "LED 6" + value: "6" + - label: "LED 7 (Bottom)" + value: "7" + + led_color: + name: LED Color + selector: + select: + options: + - label: "Off" + value: "0" + - label: "Red" + value: "1" + - label: "Green" + value: "2" + - label: "Blue" + value: "3" + - label: "Magenta" + value: "4" + - label: "Yellow" + value: "5" + - label: "Cyan" + value: "6" + - label: "White" + value: "7" + + blink_mode: + name: Blink Mode + selector: + select: + options: + - label: "Solid" + value: "0" + - label: "Fast Blink" + value: "1" + - label: "Slow Blink" + value: "2" + +mode: single + +trigger: + - platform: state + entity_id: !input monitored_entity + +action: + - variables: + actual_state: "{{ states[ (input.monitored_entity) ].state }}" + target_state: > + {{ iif(input.custom_expected_state | length > 0, input.custom_expected_state, input.expected_state) }} + matched: "{{ actual_state == target_state }}" + - variables: + color: "{{ iif(matched, (input.led_color | int(0)), 0) }}" + blink: "{{ iif(matched, (input.blink_mode | int(0)), 0) }}" + led_value: "{{ (color * 16) + blink }}" + led_param: "{{ 20 + (input.led_number | int(1)) }}" + - service: zwave_js.set_config_parameter + target: + device_id: !input target_device + data: + parameter: "{{ led_param }}" + value: "{{ led_value }}" + diff --git a/multi-tap-automation-homeseer-and-zooz.yaml b/multi-tap-automation-homeseer-and-zooz.yaml new file mode 100644 index 0000000..e7572a7 --- /dev/null +++ b/multi-tap-automation-homeseer-and-zooz.yaml @@ -0,0 +1,90 @@ +blueprint: + name: Multi-Tap Scene Controller (Zooz & HomeSeer) + description: > + Control lights or switches based on single, double, or triple tap + up/down events from a Z-Wave switch (e.g., Zooz or HomeSeer). + domain: automation + input: + master_device: + name: Master Device(s) + selector: + device: + multiple: true + + slave_entities: + name: Slave Lights or Switches + selector: + target: + entity: + domain: + - light + - switch + + tap_types: + name: Tap Type(s) + selector: + select: + multiple: true + options: + - KeyPressed + - KeyPressed2x + - KeyPressed3x + + tap_up: + name: Trigger on Tap Up? + default: true + selector: + boolean: {} + + tap_down: + name: Trigger on Tap Down? + default: true + selector: + boolean: {} + +trigger: + - platform: event + event_type: zwave_js_value_notification + +variables: + tap_types: !input tap_types + tap_up: !input tap_up + tap_down: !input tap_down + master_device_ids: !input master_device + +condition: + - condition: template + value_template: > + {% set evt = trigger.event.data %} + {{ evt.command_class_name == 'Central Scene' and + evt.value in tap_types and + ( + (tap_up and evt.property_key == 0) or + (tap_down and evt.property_key == 1) + ) and + evt.device_id in master_device_ids }} + +action: + - choose: + - conditions: + - condition: template + value_template: "{{ trigger.event.data.property_key == 0 }}" + sequence: + - service: homeassistant.turn_on + target: !input slave_entities + - conditions: + - condition: template + value_template: "{{ trigger.event.data.property_key == 1 }}" + sequence: + - service: homeassistant.turn_off + target: !input slave_entities + + # Optional: Log the event data for troubleshooting + - service: system_log.write + data: + message: > + Multi-Tap Triggered: {{ trigger.event.data }} + level: info + +mode: single + diff --git a/multi-tap-automation.yaml b/multi-tap-automation.yaml new file mode 100644 index 0000000..8ade605 --- /dev/null +++ b/multi-tap-automation.yaml @@ -0,0 +1,83 @@ +blueprint: + name: Multi-Tap Scene Controller + description: > + Control lights or switches based on single, double, or triple tap + up/down events from a Z-Wave switch (e.g., Zooz or HomeSeer). + domain: automation + input: + master_device: + name: Master Device(s) + selector: + device: + multiple: true + + slave_entities: + name: Slave Lights or Switches + selector: + target: + entity: + domain: + - light + - switch + + tap_types: + name: Tap Type(s) + selector: + select: + multiple: true + options: + - KeyPressed + - KeyPressed2x + - KeyPressed3x + + tap_up: + name: Trigger on Tap Up? + default: true + selector: + boolean: {} + + tap_down: + name: Trigger on Tap Down? + default: true + selector: + boolean: {} + +trigger: + - platform: event + event_type: zwave_js_value_notification + +variables: + tap_types: !input tap_types + tap_up: !input tap_up + tap_down: !input tap_down + master_device_ids: !input master_device + +condition: + - condition: template + value_template: > + {% set evt = trigger.event.data %} + {{ evt.command_class_name == 'Central Scene' and + evt.value in tap_types and + ( + (tap_up and evt.property_key_name == '001') or + (tap_down and evt.property_key_name == '002') + ) and + evt.device_id in master_device_ids }} + +action: + - choose: + - conditions: + - condition: template + value_template: "{{ trigger.event.data.property_key_name == '001' }}" + sequence: + - service: homeassistant.turn_on + target: !input slave_entities + - conditions: + - condition: template + value_template: "{{ trigger.event.data.property_key_name == '002' }}" + sequence: + - service: homeassistant.turn_off + target: !input slave_entities + +mode: single + diff --git a/power-monitoring.yaml b/power-monitoring.yaml new file mode 100644 index 0000000..60b448c --- /dev/null +++ b/power-monitoring.yaml @@ -0,0 +1,80 @@ +blueprint: + name: Power Spike Logger + description: > + Logs significant power spikes (positive or negative) from an energy meter, typically used to identify when major appliances are turned on or off. + domain: automation + input: + phase1_power: + name: Phase 1 Power Sensor + selector: + entity: + domain: sensor + phase2_power: + name: Phase 2 Power Sensor + selector: + entity: + domain: sensor + total_power: + name: Total Power Sensor + selector: + entity: + domain: sensor + delta_power: + name: Power Delta Sensor + selector: + entity: + domain: sensor + spike_threshold: + name: Spike Threshold (W) + description: Minimum power change (positive or negative) to trigger logging + default: 1500 + selector: + number: + min: 100 + max: 10000 + unit_of_measurement: W + mode: box + log_target: + name: Notification or Log Target + description: Where to send spike logs (e.g., notify.persistent_notification) + default: [] + selector: + target: + entity: + domain: notify + +trigger: + - platform: numeric_state + entity_id: !input delta_power + above: !input spike_threshold + - platform: template + value_template: > + {% set threshold = states('input_number.spike_threshold') | float(1500) %} + {% set delta = states(input('delta_power')) | float(0) %} + {{ delta < (0 - threshold) }} + +condition: + - condition: template + value_template: > + {{ states(input('total_power')) | float(0) > 1000 }} + +variables: + phase1: "{{ states(input('phase1_power')) }}" + phase2: "{{ states(input('phase2_power')) }}" + total: "{{ states(input('total_power')) }}" + delta: "{{ states(input('delta_power')) }}" + time: "{{ now().strftime('%Y-%m-%d %H:%M:%S') }}" + +action: + - service: notify.persistent_notification + data: + title: "Power Spike Detected" + message: > + Power spike at {{ time }}:\n + Phase 1: {{ phase1 }} W\n + Phase 2: {{ phase2 }} W\n + Total: {{ total }} W\n + Δ: {{ delta }} W + +mode: queued + diff --git a/simulated-presence.yaml b/simulated-presence.yaml new file mode 100644 index 0000000..adac295 --- /dev/null +++ b/simulated-presence.yaml @@ -0,0 +1,77 @@ +blueprint: + name: Simulated Presence - Random Lights + description: > + Randomly toggles lights when a thermostat attribute equals a specified value + and it's nighttime (sun below horizon). + domain: automation + input: + lights: + name: Light Entities + description: Select the lights to simulate presence + selector: + entity: + domain: light + multiple: true + + thermostat: + name: Thermostat Entity + description: The climate entity to check for the specified attribute + selector: + entity: + domain: climate + + attribute_name: + name: Thermostat Attribute + description: Attribute of the thermostat to check (e.g., preset_mode) + default: preset_mode + selector: + text: + + expected_value: + name: Expected Attribute Value + description: The value that triggers this automation (e.g., away_indefinitely) + default: away_indefinitely + selector: + text: + + interval: + name: Randomization Interval (minutes) + description: How often to randomly toggle lights + default: 10 + selector: + number: + min: 1 + max: 60 + unit_of_measurement: minutes + +mode: restart + +trigger: + - platform: state + entity_id: sun.sun + to: "below_horizon" + +condition: + - condition: template + value_template: > + {{ state_attr(thermostat, attribute_name) == expected_value }} + +action: + - repeat: + while: + - condition: state + entity_id: sun.sun + state: "below_horizon" + - condition: template + value_template: > + {{ state_attr(thermostat, attribute_name) == expected_value }} + sequence: + - variables: + selected_lights: "{{ lights | random }}" + - service: > + {{ ['light.turn_on', 'light.turn_off'] | random }} + target: + entity_id: "{{ selected_lights }}" + - delay: + minutes: !input interval + diff --git a/state-opposite.yaml b/state-opposite.yaml new file mode 100644 index 0000000..abffa3f --- /dev/null +++ b/state-opposite.yaml @@ -0,0 +1,75 @@ +blueprint: + name: Opposite State Synchronizer + description: > + Keeps two entities in opposite states. If entity 1 turns on, entity 2 turns off, and vice versa. + domain: automation + input: + entity_1: + name: Entity 1 + selector: + entity: + domain: + - light + - switch + entity_2: + name: Entity 2 + selector: + entity: + domain: + - light + - switch + +trigger: + - platform: state + entity_id: !input entity_1 + id: entity_1 + - platform: state + entity_id: !input entity_2 + id: entity_2 + +condition: [] + +action: + - choose: + - conditions: + - condition: trigger + id: entity_1 + - condition: state + entity_id: !input entity_1 + state: "on" + sequence: + - service: homeassistant.turn_off + target: + entity_id: !input entity_2 + - conditions: + - condition: trigger + id: entity_1 + - condition: state + entity_id: !input entity_1 + state: "off" + sequence: + - service: homeassistant.turn_on + target: + entity_id: !input entity_2 + - conditions: + - condition: trigger + id: entity_2 + - condition: state + entity_id: !input entity_2 + state: "on" + sequence: + - service: homeassistant.turn_off + target: + entity_id: !input entity_1 + - conditions: + - condition: trigger + id: entity_2 + - condition: state + entity_id: !input entity_2 + state: "off" + sequence: + - service: homeassistant.turn_on + target: + entity_id: !input entity_1 +mode: single +