Hey guys,
I have a simple garage operating with a hacked sonoff (on both sw and hw) inside the machine.
The operation is pretty straightforward, just one click to alternate between moves.
I tried to find a solution to calculate my garage door’s approximate position based on time.
I know, I know, I should have hooked up a magnetic sensor but I was too lazy so I came up with a code that works for me and here it is:
(original community post here)
Some info:
- The sonoff is located within the garage machine box.
- It is running Tasmota firmware.
- It has been (hw) modified in this way in order to be able to close/open any circuit and not just provide 230ac to its output end.
- So it is powered by the garage doors main power and on the other end I hooked up the signal pins of the garage control board which will control the door whenever the two pins are shorted.
- The door is operated by some 25y old Faac model which has a 3rd party control board on it as I was asked €600 to replace the original board a couple of years ago. It does work on the original board too though.
- Usual high voltage precautions, warnings, and waivers of liability apply here.
So, despite everyone’s understandable disagreement, 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.
Going to share for comments and to, perhaps, help someone out.
notes:
- the
up
part in naming is due to me having two doors, one is namedup
, the otherdn
, 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 caseswitch.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 the previous state)
- Signal while closing -> stop (will start opening on next signal)
- Signal while stopped in the middle -> start opening (depending on the previous state)
- Signal while open -> start closing.
Code:
- An
input_select
to state the 6 different states of the door:
This should go in yourconfiguration.yaml
underinput_select:
or in yourinput_select
.yaml if you haveinput_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 inconfiguration.yaml
undervariable:
or invariables.yaml
if you havevariable: !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.)
Insidesensors.yaml
or undersensor:
inconfiguration.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.
The main flaw is that I’m using UNIX timestamp to do my calculations which means I’m 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 endpoint (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 an 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. If this happens you need to manually reset the input_select
to the correct state afterward.
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
And of course this, for extra bragging rights on my friends:
could.yaml
:
google_actions:
filter:
include_entities:
- script.garage_up_operation
entity_config:
script.garage_up_operation:
name: "Garage Up"
alexa:
filter:
include_entities:
- script.garage_up_operation
entity_config:
script.garage_up_operation:
name: "Garage Up"
display_categories: SWITCH
Hope this helps someone out who’s in the same need as me and doesn’t want or cannot install additional sensors.
Now ill go grease the doors cause they screech like harpies
k.