Last active
June 27, 2024 11:54
-
-
Save lukasvice/b364724d84c3ac4e160f7a7d8fa37066 to your computer and use it in GitHub Desktop.
Home Assistant script to control venetian blinds with Shelly
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Have a look at the blog post about this script: | |
# https://medium.com/@lukasvice/a-utility-script-for-controlling-venetian-blinds-with-shelly-in-home-assistant-2e5cbf2d8d5f | |
script: | |
cover_position_tilt: | |
mode: parallel | |
fields: | |
entity_id: | |
description: "The cover entity" | |
example: "cover.X" | |
position: | |
description: "Position of the cover" | |
example: 100 | |
tilt_position: | |
description: "Tilt position (optional)" | |
example: 100 | |
sequence: | |
- alias: "Set variables" | |
variables: | |
# Time in ms for a full tilt | |
tilt_time_ms: 1800 | |
# Time between blinds move commands | |
cmd_wait_time_ms: 500 | |
_original_position: "{{ state_attr(entity_id, 'current_position') }}" | |
- alias: "Open/Close tilt depending on current position" | |
choose: | |
# When closing | |
- conditions: "{{ state_attr(entity_id, 'current_position') > position|int }}" | |
sequence: | |
# Move to the desired position | |
- service: cover.set_cover_position | |
data_template: | |
entity_id: "{{ entity_id }}" | |
position: "{{ position|int }}" | |
# Blinds have to be tilted, if tilt_position is set and tilt_position is not fully closed | |
- alias: "Check if blinds should be tilted" | |
condition: template | |
value_template: "{{ tilt_position is defined and tilt_position != none and tilt_position|int > 0 }}" | |
# Wait for the blinds to stop (Shelly updates current_position on start/stop) | |
# Cancel the script if the position was not received after 100 seconds | |
- wait_for_trigger: | |
- platform: template | |
value_template: "{% if state_attr(entity_id, 'current_position') != _original_position %}true{% endif %}" | |
timeout: 100 | |
continue_on_timeout: false | |
# If it's not the desired position, the blinds were stopped manually (in this case cancel the script) | |
- alias: "Check if blinds have reached desired position" | |
condition: template | |
value_template: "{% if is_state_attr(entity_id, 'current_position', position|int) %}true{% endif %}" | |
- delay: | |
milliseconds: "{{ cmd_wait_time_ms }}" | |
# Move the blinds the required time for tilting in the original direction | |
- service: cover.close_cover | |
data_template: | |
entity_id: "{{ entity_id }}" | |
- delay: | |
milliseconds: "{{ tilt_time_ms / 100 * tilt_position|int }}" | |
- service: cover.stop_cover | |
data_template: | |
entity_id: "{{ entity_id }}" | |
- delay: | |
milliseconds: "{{ cmd_wait_time_ms }}" | |
# Move the blinds the required time for tilting in the opposite direction | |
- service: cover.open_cover | |
data_template: | |
entity_id: "{{ entity_id }}" | |
- delay: | |
milliseconds: "{{ tilt_time_ms / 100 * tilt_position|int }}" | |
- service: cover.stop_cover | |
data_template: | |
entity_id: "{{ entity_id }}" | |
# When opening | |
- conditions: "{{ state_attr(entity_id, 'current_position') < position|int }}" | |
sequence: | |
# Move to the desired position | |
- service: cover.set_cover_position | |
data_template: | |
entity_id: "{{ entity_id }}" | |
position: "{{ position|int }}" | |
# Blinds have to be tilted, if tilt_position is set and tilt_position is not fully open | |
- alias: "Check if blinds should be tilted" | |
condition: template | |
value_template: "{{ tilt_position is defined and tilt_position != none and tilt_position|int < 100 }}" | |
# Wait for the blinds to stop (Shelly updates current_position on start/stop) | |
# Cancel the script if the position was not received after 100 seconds | |
- wait_for_trigger: | |
- platform: template | |
value_template: "{% if state_attr(entity_id, 'current_position') != _original_position %}true{% endif %}" | |
timeout: 100 | |
continue_on_timeout: false | |
# If it's not the desired position, the blinds were stopped manually (in this case cancel the script) | |
- alias: "Check if blinds have reached desired position" | |
condition: template | |
value_template: "{% if is_state_attr(entity_id, 'current_position', position|int) %}true{% endif %}" | |
- delay: | |
milliseconds: "{{ cmd_wait_time_ms }}" | |
# Move the blinds the required time for tilting in the original direction | |
- service: cover.open_cover | |
data_template: | |
entity_id: "{{ entity_id }}" | |
- delay: | |
milliseconds: "{{ tilt_time_ms / 100 * (100 - tilt_position|int) }}" | |
- service: cover.stop_cover | |
data_template: | |
entity_id: "{{ entity_id }}" | |
- delay: | |
milliseconds: "{{ cmd_wait_time_ms }}" | |
# Move the blinds the required time for tilting in the opposite direction | |
- service: cover.close_cover | |
data_template: | |
entity_id: "{{ entity_id }}" | |
- delay: | |
milliseconds: "{{ tilt_time_ms / 100 * (100 - tilt_position|int) }}" | |
- service: cover.stop_cover | |
data_template: | |
entity_id: "{{ entity_id }}" | |
# Special case: the blinds are already in the desired position | |
default: | |
- alias: "Continue only if blinds are not fully opened or closed" | |
condition: template | |
value_template: "{{ state_attr(entity_id, 'current_position') > 0 and state_attr(entity_id, 'current_position') < 100 }}" | |
- choose: | |
# When the blinds are almost closed, move up for the tilt time | |
- conditions: "{{ state_attr(entity_id, 'current_position') < 10 }}" | |
sequence: | |
- service: cover.open_cover | |
data_template: | |
entity_id: "{{ entity_id }}" | |
- delay: | |
milliseconds: "{{ tilt_time_ms }}" | |
- service: cover.stop_cover | |
data_template: | |
entity_id: "{{ entity_id }}" | |
# When the blinds are open, move down for the tilt time | |
default: | |
- service: cover.close_cover | |
data_template: | |
entity_id: "{{ entity_id }}" | |
- delay: | |
milliseconds: "{{ tilt_time_ms }}" | |
- service: cover.stop_cover | |
data_template: | |
entity_id: "{{ entity_id }}" | |
- delay: | |
milliseconds: "{{ cmd_wait_time_ms }}" | |
# Trigger event to restart the script with the original parameters | |
- event: start_cover_position_tilt | |
event_data: | |
entity_id: "{{ entity_id }}" | |
position: "{{ position }}" | |
tilt_position: "{{ tilt_position }}" | |
automation: | |
# Automation triggered by a custom event to restart the script | |
- id: start_cover_position_tilt | |
alias: "Start Cover Position Tilt" | |
mode: parallel | |
trigger: | |
- platform: event | |
event_type: "start_cover_position_tilt" | |
action: | |
- service: script.cover_position_tilt | |
data_template: | |
entity_id: "{{ trigger.event.data.entity_id }}" | |
position: "{{ trigger.event.data.position }}" | |
tilt_position: "{{ trigger.event.data.tilt_position }}" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
service: script.cover_position_tilt | |
data: | |
entity_id: cover.shelly_XXX | |
position: 70 | |
tilt_position: 50 |
today i had some time to play with this script, but in my case it is not working as expected. the problem I think is that my venetian blinds do need different times for a full tilt upwards (1400ms) and downwards (1000ms). Do you have the same issue and just took the middle value? if you send tilt position 50 should the blinds stop at around 45deg?
@u20p17 Hmm, my blinds always take the same amount of time regardless of the direction. Maybe you could modify the script so that you have two variables, tilt_time_opening_ms
and tilt_time_closing_ms
. You can then use these variables in the "opening" or "closing" condition of the script. This might work.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
danke, hatte es tatsächlich falsch^^ jetzt funktionierts (Y)