So, despites of everyone’s understandable disagreement, i think i’ve done it with code.
It’s not perfect but it works.
The main advantage is that i have an (unsafe) indication of where my garage doors are, in case i forget to close them when leaving the house.
Gonna share for comments and to, perhaps, help someone out.
notes:
- the
up
part in naming is due to me having two doors, one is named up
, the other dn
, so you can ignore it
- The only two things you need to change for this to work are the variable for total time the door takes to move from end to start (
garage_up_total_time
) and the name of the switch that toggles your garage, in my case switch.sonoff_garage_2
.
- The switch could also be an RF transmitter
So here it is:
Please keep in mind that my door works with the simple way possible with only one signal input:
- Signal while closed -> start opening.
- Signal while opening -> stop (will start closing on next signal)
- Signal while stopped in the middle -> start closing (depending on previous state)
- Signal while closing -> stop (will start opening on next signal)
- Signal while stopped in the middle -> start opening (depending on previous state)
- Signal while open -> start closing.
Code:
- An
input_select
to state the 6 different states of the door:
This should go in your configuration.yaml
under input_select:
or in your input_select
.yaml if you have input_select: !include input_select.yaml
already in your conf.
garage_up_state:
name: Garage UP State
initial: Closed
options:
- Closed
- Opening
- Stopped Next Closing
- Stopped Next Opening
- Closing
- Open
- I used this component to be able to store some variables (instead of input numbers and stuff)
hass-variables
With hass-variables, i created several variables to be able to track down times, the position of the door and the total time the door takes to open/close (starting from closed/open, respectively)
This goes in configuration.yaml
under variable:
or in variables.yaml
if you have variable: !include variables.yaml
already in your conf.
garage_up_total_time:
value: 16 #change this value accordingly
garage_up_position:
value: 0
garage_up_last_use:
value: 0
garage_up_prev_use:
value: 0
- A script to run different scripts depending on the state of the
input_select
above
garage_up_operation:
alias: "Garage Up Toggle"
sequence:
- service: variable.set_variable
data:
variable: "garage_up_prev_use"
value_template: "{{(states.variable.garage_up_last_use.state)| int}}"
- service: variable.set_variable
data:
variable: "garage_up_last_use"
value_template: "{{(as_timestamp(now())| round(0))+(2*60*60)| int}}"
- service: script.turn_on
data_template:
entity_id: >
{% if is_state("input_select.garage_up_state", "Closed") %}
script.garage_up_closed
{% elif is_state("input_select.garage_up_state", "Opening") %}
script.garage_up_opening
{% elif is_state("input_select.garage_up_state", "Stopped Next Closing") %}
script.garage_up_stopped_next_closing
{% elif is_state("input_select.garage_up_state", "Stopped Next Opening") %}
script.garage_up_stopped_next_opening
{% elif is_state("input_select.garage_up_state", "Closing") %}
script.garage_up_closing
{% elif is_state("input_select.garage_up_state", "Open") %}
script.garage_up_open
{% endif %}
- And then some more scripts that would handle the operation switch and change the
input_select
according to where the door is.
garage_up_closed:
alias: "When Garage Up Closed"
sequence:
- service: switch.turn_on
entity_id: switch.sonoff_garage_2
- service: input_select.select_option
data:
entity_id: input_select.garage_up_state
option: "Opening"
- delay:
seconds: "{{(states.variable.garage_up_total_time.state)| int}}"
- service: variable.set_variable
data:
variable: "garage_up_position"
value_template: "{{(states.variable.garage_up_total_time.state)| int}}"
- service: input_select.select_option
data:
entity_id: input_select.garage_up_state
option: "Open"
garage_up_opening:
alias: "When Garage Up Opening"
sequence:
- service: switch.turn_on
entity_id: switch.sonoff_garage_2
- service: script.turn_off
entity_id: script.garage_up_closed, script.garage_up_stopped_next_opening
- service: variable.set_variable
data:
variable: "garage_up_position"
value_template: "{{(states.variable.garage_up_position.state)| int +(states.variable.garage_up_last_use.state)| int-(states.variable.garage_up_prev_use.state)| int}}"
- service: input_select.select_option
data:
entity_id: input_select.garage_up_state
option: "Stopped Next Closing"
garage_up_stopped_next_closing: #was Opening
alias: "When Garage Up Stopped, next: Closing"
sequence:
- service: switch.turn_on
entity_id: switch.sonoff_garage_2
- service: input_select.select_option
data:
entity_id: input_select.garage_up_state
option: "Closing"
- delay:
seconds: "{{(states.variable.garage_up_position.state)| int}}"
- service: variable.set_variable
data:
variable: "garage_up_position"
value: "0" # set position 0
- service: input_select.select_option
data:
entity_id: input_select.garage_up_state
option: "Closed"
garage_up_stopped_next_opening: #was Closing
alias: "When Garage Up Stopped, next: Opening"
sequence:
- service: switch.turn_on
entity_id: switch.sonoff_garage_2
- service: input_select.select_option
data:
entity_id: input_select.garage_up_state
option: "Opening"
- delay:
seconds: "{{(states.variable.garage_up_total_time.state)| int - (states.variable.garage_up_position.state)| int}}"
- service: variable.set_variable
data:
variable: "garage_up_position"
value_template: "{{(states.variable.garage_up_total_time.state)| int}}"
- service: input_select.select_option
data:
entity_id: input_select.garage_up_state
option: "Open"
garage_up_closing:
alias: "When Garage Up Closing"
sequence:
- service: switch.turn_on
entity_id: switch.sonoff_garage_2
- service: script.turn_off
entity_id: script.garage_up_open, script.garage_up_stopped_next_closing
- service: variable.set_variable
data:
variable: "garage_up_position"
value_template: "{{(states.variable.garage_up_position.state)| int -((states.variable.garage_up_last_use.state)| int - (states.variable.garage_up_prev_use.state)| int)}}"
- service: input_select.select_option
data:
entity_id: input_select.garage_up_state
option: "Stopped Next Opening"
garage_up_open:
alias: "When Garage Up Open"
sequence:
- service: switch.turn_on
entity_id: switch.sonoff_garage_2
- service: input_select.select_option
data:
entity_id: input_select.garage_up_state
option: "Closing"
- delay:
seconds: "{{(states.variable.garage_up_total_time.state)| int}}"
- service: variable.set_variable
data:
variable: "garage_up_position"
value: "0"
- service: input_select.select_option
data:
entity_id: input_select.garage_up_state
option: "Closed"
The code needs some refactoring and could probably be re-written in a much more smart way but, that’s what I came up with - open to suggestions
- Lastly, for aesthetic reasons, i created a
template_sensor
to see the door state without being able to alter it. (I still keep the input_select editable in some other page of my frontend in case i need to manually reset the whole thing.)
Inside sensors.yaml
or under sensor:
in configuration.yaml
garage_up_state:
friendly_name: "Γκαράζ Πάνω" #ignore my greek :)
value_template: "{{ states.input_select.garage_up_state.state }}"
- And lastly v.2, a group to show them in my front-end:
door_switches:
control: hidden
entities:
- script.garage_up_operation
- sensor.garage_up_state
I just wrote this up but it seems to be working. Will keep testing and come back with comments.
Main flaw is that im using unix timestamp to do my calculations which means im working with seconds, not fragments of seconds. It does not pose a great threat but if say you open and close the door several times without reaching the end point (using the switch while the door is moving) you get an inaccurate reading of the precise position of the door between the two ends (open/closed
). Other than that, you still get accurate reading of the general state of the door.
Another flaw is that one of my doors is using a sensor when closing that will stop it if it finds an obstacle. This means it will change state (from closing
to stopped
) without HA knowing that. This needs to manually reset the input_select
to the correct state afterwards.
Next step would be an automation to send me a notification if the door is not closed for xx time, using the states of my new template sensor.
edit: and here it is.
- id: '1542799053404'
alias: Notify - Garage Up Open
trigger:
- entity_id: sensor.garage_up_state
for: 00:01:00
platform: state
to: Stopped Next Closing
- entity_id: sensor.garage_up_state
for: 00:01:00
platform: state
to: Stopped Next Opening
- entity_id: sensor.garage_up_state
for: 00:01:00
platform: state
to: Open
- entity_id: sensor.garage_dn_state
for: 00:01:00
platform: state
to: Opening #this is probably unnecessary but i just put it there to be sure
condition: []
action:
- data:
message: Garage UP left Open
title: Home Security
service: notify.notify_html5
Hope this helps someone out who’s in the same need as me and doesnt want or cannot install additional sensors.
Now ill go grease the doors cause they screech like harpies
k.