From 188671fd7e1a424dab5c3fe1932aa71f7b6a819e Mon Sep 17 00:00:00 2001 From: Bastian Schnorbus Date: Sun, 4 May 2025 15:46:15 +0200 Subject: [PATCH] update --- .gitignore | 4 +- .../automation/MacSiem/door_presence.yaml | 180 ++++++++++++++++ ...omematicip_local-actions-for-6-button.yaml | 158 ++++++++++++++ .../advanced_motion_automation.yaml | 193 ++++++++++++++++++ .../homeassistant/inverted_binary_sensor.yaml | 27 +++ pyscript/example.py | 12 ++ pyscript/rollo_sommermodus.py | 65 ++++++ 7 files changed, 637 insertions(+), 2 deletions(-) create mode 100644 blueprints/automation/MacSiem/door_presence.yaml create mode 100644 blueprints/automation/SukramJ/homematicip_local-actions-for-6-button.yaml create mode 100644 blueprints/automation/iainsmacleod/advanced_motion_automation.yaml create mode 100644 blueprints/template/homeassistant/inverted_binary_sensor.yaml create mode 100644 pyscript/example.py create mode 100644 pyscript/rollo_sommermodus.py diff --git a/.gitignore b/.gitignore index b7b8827..179b427 100755 --- a/.gitignore +++ b/.gitignore @@ -13,7 +13,7 @@ themes/ # logs OZW_Log.txt -home-assistant.log +home-assistant.log* # docker volumes zwave-js/ @@ -22,4 +22,4 @@ zbdata/ nodered_backup/ mosq_config/ -custom_components/ \ No newline at end of file +custom_components/ diff --git a/blueprints/automation/MacSiem/door_presence.yaml b/blueprints/automation/MacSiem/door_presence.yaml new file mode 100644 index 0000000..9089b3a --- /dev/null +++ b/blueprints/automation/MacSiem/door_presence.yaml @@ -0,0 +1,180 @@ +blueprint: + name: Track presence based on door + SSID + GPS + description: 'Detect whether a person has entered or left home using a door sensor, + Wi-Fi SSID, and GPS tracking (via Home Assistant Companion App). This automation + optionally logs presence tracking and sends notifications. + + ' + domain: automation + author: MacSiem + source_url: https://gist.github.com/MacSiem/1b1f80b4b2d9f1836c22ac562028cd66 + input: + person_name: + name: Person name + description: Used in notifications and logbook entries. + selector: + text: {} + door_sensor: + name: Door sensor + description: Trigger entity for door opening (any binary_sensor). + selector: + entity: + domain: + - binary_sensor + multiple: false + ssid_sensor: + name: Wi-Fi SSID sensor + description: Entity that provides current SSID (requires Companion App). + selector: + entity: + domain: + - sensor + multiple: false + gps_tracker: + name: GPS tracker + description: Device Tracker entity (typically from Companion App). + selector: + entity: + domain: + - device_tracker + multiple: false + home_ssid: + name: Home Wi-Fi SSID + description: Your exact home network SSID (case-sensitive). + selector: + text: {} + notify_target: + name: Notification service + description: Choose or enter a notify service to send alerts. + selector: + select: + options: + - notify.mobile_app_johns_iphone(example) + custom_value: true + multiple: false + sort: false + enable_logbook: + name: Enable Logbook logging + description: If enabled, presence tracking events will be logged. + default: true + selector: + boolean: {} +trigger: +- platform: state + entity_id: !input door_sensor + to: 'on' +variables: + person_name: !input person_name + ssid_entity: !input ssid_sensor + gps_entity: !input gps_tracker + notify_target: !input notify_target + ssid_home: !input home_ssid + logbook_enabled: !input enable_logbook + ssid_before: '{{ states(ssid_entity) == ssid_home }}' + gps_before: '{{ states(gps_entity) }}' +action: +- choose: + - conditions: + - condition: template + value_template: '{{ logbook_enabled }}' + sequence: + - service: logbook.log + data: + name: Presence Tracker - {{ person_name }} + message: '3 minutes before door opened - SSID: {{ ssid_before }}, GPS: {{ + gps_before }}' +- service: homeassistant.update_entity + target: + entity_id: + - '{{ ssid_entity }}' + - '{{ gps_entity }}' +- service: '{{ notify_target }}' + data: + message: request_location_update +- delay: 00:00:05 +- variables: + ssid_now: '{{ states(ssid_entity) == ssid_home }}' + gps_now: '{{ states(gps_entity) }}' +- choose: + - conditions: + - condition: template + value_template: '{{ logbook_enabled }}' + sequence: + - service: logbook.log + data: + name: Presence Tracker - {{ person_name }} + message: 'At door opening - SSID: {{ ssid_now }}, GPS: {{ gps_now }}' +- repeat: + count: 90 + sequence: + - delay: 00:00:10 + - service: homeassistant.update_entity + target: + entity_id: + - '{{ ssid_entity }}' + - '{{ gps_entity }}' + - service: '{{ notify_target }}' + data: + message: request_location_update + - delay: 00:00:05 + - variables: + ssid_after: '{{ states(ssid_entity) == ssid_home }}' + gps_after: '{{ states(gps_entity) }}' + - choose: + - conditions: + - condition: template + value_template: '{{ logbook_enabled }}' + sequence: + - service: logbook.log + data: + name: Presence Tracker - {{ person_name }} + message: 'After {{ repeat.index }} min - SSID: {{ ssid_after }}, GPS: + {{ gps_after }}' + - choose: + - conditions: + - condition: template + value_template: '{{ ssid_before and not ssid_after }}' + sequence: + - delay: 00:00:30 + - condition: template + value_template: '{{ states(ssid_entity) != ssid_home }}' + - service: '{{ notify_target }}' + data: + message: '{{ person_name }} has left home (Wi-Fi)' + - stop: Automation stopped - Exit detected + - conditions: + - condition: template + value_template: '{{ not ssid_before and ssid_after }}' + sequence: + - service: '{{ notify_target }}' + data: + message: '{{ person_name }} has arrived home (Wi-Fi)' + - stop: Automation stopped - Entry detected + - conditions: + - condition: template + value_template: '{{ gps_before == ''home'' and gps_after == ''not_home'' + }}' + sequence: + - service: '{{ notify_target }}' + data: + message: '{{ person_name }} has left home (GPS)' + - stop: Automation stopped - Exit detected + - conditions: + - condition: template + value_template: '{{ gps_before == ''not_home'' and gps_after == ''home'' + }}' + sequence: + - service: '{{ notify_target }}' + data: + message: '{{ person_name }} has arrived home (GPS)' + - stop: Automation stopped - Entry detected +- choose: + - conditions: + - condition: template + value_template: '{{ logbook_enabled }}' + sequence: + - service: logbook.log + data: + name: Presence Tracker - {{ person_name }} + message: Automation completed +mode: restart diff --git a/blueprints/automation/SukramJ/homematicip_local-actions-for-6-button.yaml b/blueprints/automation/SukramJ/homematicip_local-actions-for-6-button.yaml new file mode 100644 index 0000000..af76f5c --- /dev/null +++ b/blueprints/automation/SukramJ/homematicip_local-actions-for-6-button.yaml @@ -0,0 +1,158 @@ +blueprint: + name: Actions for 6-Button Homematic(IP) device + description: When a button is pressed, the defined actions will be executed. Please + keep in mind, that long-press actions might be executed multiple times, according + to your configured minimum duration for long press. This can be configured in + your CCU. Tested with HmIP-WRC6. Should work with other device too. + domain: automation + source_url: https://github.com/SukramJ/custom_homematic/blob/789b37f30e07eefe9edefae6d774590e17f21bf4/blueprints/automation/homematicip_local-actions-for-6-button.yaml + input: + remote: + name: 6-Button Device + description: Please select a 6-Button device of your Homematic(IP) Local integration. + selector: + device: + integration: homematicip_local + multiple: false + action_left_top_short: + name: Action + description: Left-Top-Button, Short Press + default: [] + selector: + action: {} + action_left_top_long: + name: Action + description: Left-Top-Button, Long Press + default: [] + selector: + action: {} + action_right_top_short: + name: Action + description: Right-Top-Button, Short Press + default: [] + selector: + action: {} + action_right_top_long: + name: Action + description: Right-Top-Button, Long Press + default: [] + selector: + action: {} + action_left_middle_short: + name: Action + description: Left-Middle-Button, Short Press + default: [] + selector: + action: {} + action_left_middle_long: + name: Action + description: Left-Middle-Button, Long Press + default: [] + selector: + action: {} + action_right_middle_short: + name: Action + description: Right-Middle-Button, Short Press + default: [] + selector: + action: {} + action_right_middle_long: + name: Action + description: Right-Middle-Button, Long Press + default: [] + selector: + action: {} + action_left_bottom_short: + name: Action + description: Left-Bottom-Button, Short Press + default: [] + selector: + action: {} + action_left_bottom_long: + name: Action + description: Left-Bottom-Button, Long Press + default: [] + selector: + action: {} + action_right_bottom_short: + name: Action + description: Right-Bottom-Button, Short Press + default: [] + selector: + action: {} + action_right_bottom_long: + name: Action + description: Right-Bottom-Button, Long Press + default: [] + selector: + action: {} +trigger: +- platform: event + event_type: homematic.keypress + event_data: + device_id: !input remote +condition: [] +action: +- choose: + - conditions: + - condition: template + value_template: '{{ trigger.event.data.type == ''press_short'' and trigger.event.data.subtype == + 1 }}' + sequence: !input action_left_top_short + - conditions: + - condition: template + value_template: '{{ trigger.event.data.type == ''press_long'' and trigger.event.data.subtype == + 1 }}' + sequence: !input action_left_top_long + - conditions: + - condition: template + value_template: '{{ trigger.event.data.type == ''press_short'' and trigger.event.data.subtype == + 2 }}' + sequence: !input action_right_top_short + - conditions: + - condition: template + value_template: '{{ trigger.event.data.type == ''press_long'' and trigger.event.data.subtype == + 2 }}' + sequence: !input action_right_top_long + - conditions: + - condition: template + value_template: '{{ trigger.event.data.type == ''press_short'' and trigger.event.data.subtype == + 3 }}' + sequence: !input action_left_middle_short + - conditions: + - condition: template + value_template: '{{ trigger.event.data.type == ''press_long'' and trigger.event.data.subtype == + 3 }}' + sequence: !input action_left_middle_long + - conditions: + - condition: template + value_template: '{{ trigger.event.data.type == ''press_short'' and trigger.event.data.subtype == + 4 }}' + sequence: !input action_right_middle_short + - conditions: + - condition: template + value_template: '{{ trigger.event.data.type == ''press_long'' and trigger.event.data.subtype == + 4 }}' + sequence: !input action_right_middle_long + - conditions: + - condition: template + value_template: '{{ trigger.event.data.type == ''press_short'' and trigger.event.data.subtype == + 5 }}' + sequence: !input action_left_bottom_short + - conditions: + - condition: template + value_template: '{{ trigger.event.data.type == ''press_long'' and trigger.event.data.subtype == + 5 }}' + sequence: !input action_left_bottom_long + - conditions: + - condition: template + value_template: '{{ trigger.event.data.type == ''press_short'' and trigger.event.data.subtype == + 6 }}' + sequence: !input action_right_bottom_short + - conditions: + - condition: template + value_template: '{{ trigger.event.data.type == ''press_long'' and trigger.event.data.subtype == + 6 }}' + sequence: !input action_right_bottom_long +mode: parallel +max: 10 diff --git a/blueprints/automation/iainsmacleod/advanced_motion_automation.yaml b/blueprints/automation/iainsmacleod/advanced_motion_automation.yaml new file mode 100644 index 0000000..dbdd59d --- /dev/null +++ b/blueprints/automation/iainsmacleod/advanced_motion_automation.yaml @@ -0,0 +1,193 @@ +blueprint: + name: Motion-activated Light with Conditions, Exceptions, Optional Settings, and + Sun Offset + description: Turn on lights when motion is detected, with optional brightness and + color settings, conditional entity state check, and sun position check with offset. + domain: automation + input: + motion_sensors: + name: Motion Sensors + description: Select one or more motion sensors. + selector: + entity: + domain: + - binary_sensor + device_class: + - motion + multiple: true + light_targets: + name: Lights + description: Select one or more lights to control. + selector: + target: + entity: + - domain: + - light + no_motion_wait: + name: Wait Time + description: Time to leave the light on after last motion is detected. + default: 120 + selector: + number: + min: 0.0 + max: 3600.0 + unit_of_measurement: seconds + mode: slider + step: 1.0 + use_custom_settings: + name: Use Custom Brightness and Color + description: Enable to use custom brightness and color settings. + default: false + selector: + boolean: {} + brightness: + name: Brightness + description: Set the brightness level (0-255). + default: 255 + selector: + number: + min: 0.0 + max: 255.0 + mode: slider + step: 1.0 + color: + name: Color + description: Set the color (in RGB format). + default: + - 255 + - 255 + - 255 + selector: + color_rgb: {} + condition_entity: + name: Condition Entity (Optional) + description: Select an entity to check its state (optional). If no entity is + defined, this condition is not evaluated. + default: + selector: + entity: {} + condition_states: + name: Allowed States for Condition Entity + description: Enter the states that the condition entity should be in (comma-separated). + If a Condition Entity is not defined these values are ignored. + default: + selector: + text: {} + sun_condition: + name: Sun Condition (Optional) + description: Select the sun condition to check. + default: none + selector: + select: + options: + - none + - day + - night + multiple: false + custom_value: false + sort: false + sun_offset: + name: Sun Offset (Optional) + description: Offset from sunrise/sunset in format 'HH:MM' (e.g., '01:00' or + '-01:00') + default: 00:00 + selector: + text: {} + blocking_entity: + name: Blocking Entity (Optional) + description: Select an entity that will prevent the automation from running + when in specified states. + default: + selector: + entity: {} + blocking_states: + name: Blocking States + description: Enter the states that will prevent the automation from running + (comma-separated). + default: + selector: + text: {} + source_url: https://github.com/iainsmacleod/Home-Assistant-Blueprints/blob/main/advanced_motion_automation.yaml +mode: restart +max_exceeded: silent +trigger: +- platform: state + entity_id: !input motion_sensors + to: 'on' +variables: + use_custom_settings: !input use_custom_settings + condition_entity: !input condition_entity + condition_states: !input condition_states + sun_condition: !input sun_condition + sun_offset: !input sun_offset + blocking_entity: !input blocking_entity + blocking_states: !input blocking_states +condition: +- condition: and + conditions: + - condition: or + conditions: + - condition: template + value_template: '{{ blocking_entity == None or blocking_entity == '''' }}' + - condition: template + value_template: '{% set blocking_states_list = blocking_states.split('','') + | map(''trim'') | list %} {{ states(blocking_entity) not in blocking_states_list + }} + + ' + - condition: or + conditions: + - condition: template + value_template: '{{ condition_entity == None or condition_entity == '''' }}' + - condition: template + value_template: '{% set states_list = condition_states.split('','') | map(''trim'') + | list %} {{ condition_entity != None and condition_entity != '''' and states_list + | length > 0 and states(condition_entity) in states_list }} + + ' + - condition: or + conditions: + - condition: template + value_template: '{{ sun_condition == ''none'' }}' + - condition: and + conditions: + - condition: template + value_template: '{{ sun_condition == ''day'' }}' + - condition: sun + after: sunrise + after_offset: !input sun_offset + before: sunset + before_offset: !input sun_offset + - condition: and + conditions: + - condition: template + value_template: '{{ sun_condition == ''night'' }}' + - condition: or + conditions: + - condition: sun + after: sunset + after_offset: !input sun_offset + - condition: sun + before: sunrise + before_offset: !input sun_offset +action: +- choose: + - conditions: + - condition: template + value_template: '{{ use_custom_settings }}' + sequence: + - service: light.turn_on + target: !input light_targets + data: + brightness: !input brightness + rgb_color: !input color + default: + - service: light.turn_on + target: !input light_targets +- wait_for_trigger: + platform: state + entity_id: !input motion_sensors + to: 'off' +- delay: !input no_motion_wait +- service: light.turn_off + target: !input light_targets diff --git a/blueprints/template/homeassistant/inverted_binary_sensor.yaml b/blueprints/template/homeassistant/inverted_binary_sensor.yaml new file mode 100644 index 0000000..5be1840 --- /dev/null +++ b/blueprints/template/homeassistant/inverted_binary_sensor.yaml @@ -0,0 +1,27 @@ +blueprint: + name: Invert a binary sensor + description: Creates a binary_sensor which holds the inverted value of a reference binary_sensor + domain: template + source_url: https://github.com/home-assistant/core/blob/dev/homeassistant/components/template/blueprints/inverted_binary_sensor.yaml + input: + reference_entity: + name: Binary sensor to be inverted + description: The binary_sensor which needs to have its value inverted + selector: + entity: + domain: binary_sensor +variables: + reference_entity: !input reference_entity +binary_sensor: + state: > + {% if states(reference_entity) == 'on' %} + off + {% elif states(reference_entity) == 'off' %} + on + {% else %} + {{ states(reference_entity) }} + {% endif %} + # delay_on: not_used in this example + # delay_off: not_used in this example + # auto_off: not_used in this example + availability: "{{ states(reference_entity) not in ('unknown', 'unavailable') }}" diff --git a/pyscript/example.py b/pyscript/example.py new file mode 100644 index 0000000..97b7d8f --- /dev/null +++ b/pyscript/example.py @@ -0,0 +1,12 @@ +@service +def hello_world(action=None, id=None, brt=None): + """hello_world example using pyscript.""" + log.info(f"hello world: got action {action} id {id}") + w = state.get("weather.forecast_home") + attr = state.getattr("weather.forecast_home") + log.info(f"hello world: got action {w} - attributes {attr}") + log.info(f"hello world: cloudcoverage {attr.get('cloud_coverage')}") + if action == "turn_on" and id is not None: + light.turn_on(entity_id=id, brightness=brt) + elif action == "fire" and id is not None: + event.fire(id, param1=12, param2=80) diff --git a/pyscript/rollo_sommermodus.py b/pyscript/rollo_sommermodus.py new file mode 100644 index 0000000..cbe2445 --- /dev/null +++ b/pyscript/rollo_sommermodus.py @@ -0,0 +1,65 @@ +#sensor.sun_elevation + +@state_trigger("sensor.sun_elevation") +def sun_change(trigger_type=None, var_name=None, value=None): + """Sun is above horizon.""" + + if value is None: + return + + rollo_kinderzimmer_expected_pos = 50 + rollo_kinderzimmer_elevation_threshold = 15 + + rollo_schlafzimmer_elevation_threshold = 48 + + # sun_change: trigger_type state var_name sensor.sun_elevation value 18.04 + log.info(f"sun_change: trigger_type {trigger_type} var_name {var_name} value {value}") + # weather.forecast_home + + sonnenschutz = state.get("input_boolean.sonnenschutz") + if sonnenschutz == "off": + log.info(f"sun_change: sonnenschutz {sonnenschutz}, exiting") + return + + if float(value) < 0: + log.info("sun_change: sun is below horizon, exiting") + + + # fenster und rollo zustände auslesen + fenster_kinderzimmer = state.get("binary_sensor.neq0632846_state") + fenster_schlafzimmer_l = state.get("binary_sensor.neq0629114_state") + fenster_schlafzimmer_r = state.get("binary_sensor.neq0627526_state") + rollo_kinderzimmer = state.get("cover.00115a498e0439") + rollo_kinderzimmer_attribs = state.getattr("cover.00115a498e0439") + rollo_kinderzimmer_position = rollo_kinderzimmer_attribs['current_position'] + + log.info(f"Fenster: kinderzimmer {fenster_kinderzimmer}, szl {fenster_schlafzimmer_l}, szr {fenster_schlafzimmer_r}") + log.info(f"Rollos: kinderzimmer {rollo_kinderzimmer}, ({rollo_kinderzimmer_position}%)") + + # wettervorhersage: temperatur, wolken, condition + forecast_temp = state.get("sensor.daily_forecast") + forecast_attribs = state.getattr("sensor.daily_forecast") + forecast_cloudcoverage = forecast_attribs['cloud_coverage'] + forecast_condition = forecast_attribs['condition'] + + log.info(f"sun_change: forecast_temp {forecast_temp}, cloudcoverage {forecast_cloudcoverage}, condition {forecast_condition}") + + if float(forecast_temp) <= 15 and forecast_cloudcoverage > 50: + log.info("sun_change: weather not nice, not taking care of covers") + return + + + if float(value) > rollo_kinderzimmer_elevation_threshold: + # wenn fenster geschlossen und rollo oben + if fenster_kinderzimmer == 'off' and rollo_kinderzimmer_position > rollo_kinderzimmer_expected_pos: + log.info("nu würde ich was runterfahren im kinderzimmer") + + if float(value) > rollo_schlafzimmer_elevation_threshold: + if fenster_schlafzimmer_l == 'off' and fenster_schlafzimmer_r == 'off': + log.info("nu würde ich was runterfahren im schlafzimmer") + + if trigger_type == "state": + if var_name == "sensor.sun_elevation": + log.info(f"sun_change: sun elevation changed to {value}") + if float(value) < 0: + log.info("sun_change: sun is below horizon, exiting") \ No newline at end of file