Here is my Shelly UNI Garage door controller with states.
Wanted a more advanced garage opener with more states than two.
This reports 5 states with text and icons:
Fully Open
Fully Closed
Partially Open
Door is Closing
Door is Opening
Shelly UNI is very small, good specs, can be powered with 12V – 36V DC.
Hörmann ProMatic 3 operates in 24V DC. No need of extra converters, just plug & play…
Shelly downsides:
- Difficult to flash, the pins on the board are small.
- ADC Power measurement is not good in my oppinion.
To get this to work, I had to create a virtual sensor (template sensor) in configuration.yaml (Homeassistant).
A real cover in ESPHome just to control garagedoor from Android Auto and other frontends.
I tried to create a template cover in configuration.yaml, but I did not like it because the icon color did not work right, sometimes it changed color in wrong states, and I had to expose relay to frontend.
How:
Simple text_sensor with states from sensors, homeassistant uses these “states” in template sensor that masquerades as a real Garage Cover with icons.
States come from magnet reed switches and voltage reading from ADC.
Some small issues:
Status changes to wrong status sometimes for a short period of time while opening or closing.
ADC sensor floods log
Time to start the project!
Hardware:
1x Shelly UNI
2x Magnet Reed Switch
1x DHT22 Sensor
1x Hörmann ProMatic3
Cables
Old ATX PCIe power connector
Connections:
DHT22
UNI pin4 Yellow to DHT VCC+
UNI pin5 Blue to DHT Data
UNI pin6 Green to DHT GND-
Magnet Reed Switch
Contact sensor top - GPIO12, UNI pin8 Light Brown and UNI pin1 Red (VCC Main)
Contact sensor bottom - GPIO13, UNI pin7 Dark Brown and UNI pin1 Red (VCC Main)
Relay 1 to Hörmann 20 & 21
Relay 2 to Hörmann 20 & 23 - for partial opening - Optional
Power UNI from backup battery pins.
Cut out one row with 2 connectors from ATX PCIe power connector, if you don’t have better connectors.
Middle pin positive (+), pin closest to the lamp negative (-)
UNI pin3 White to red wire on the motor
I used thick wire and pushed it in the connector, I will make a better Wago connection “later”.
ADC sensor has to be calibrated to your motor, check the vaues when you have commented lamda “filter” disabled.
Now to the Code!
ESPHome code, Flash to Shelly UNI
substitutions:
devicename: garage-2-uni
friendly_name: Garage 2
update_slow: '60s' ## Wifi, Uptime...
dht22_update: '60s'
button_delay: '0.7s'
timeout_reboot: '15min'
sensor_invert_top: 'true' ## NO Contact set to 'true' , NC contact set to 'false'
sensor_invert_bottom: 'true' ## NO Contact set to 'true' , NC contact set to 'false'
hide_relay1: 'true' ## Hide from frontend 'true', Show in frontend 'false'
hide_relay2: 'true' ## Hide from frontend 'true', Show in frontend 'false'
hide_cover: 'false' ## Hide from frontend 'true', Show in frontend 'false'
esphome:
name: ${devicename}
friendly_name: $friendly_name
esp8266:
board: esp01_1m
logger:
level: DEBUG
logs:
component: ERROR
## Common settings
wifi:
ssid: !secret wifi_iot_ssid
password: !secret wifi_iot_password
power_save_mode: none
reboot_timeout: $timeout_reboot
ap:
ssid: $friendly_name Fallback Hotspot
password: !secret fallback_ap_password
captive_portal:
web_server:
port: 80
auth:
username: !secret admin_user
password: !secret fallback_ap_password
api:
encryption:
key: !secret esphome_api_key
reboot_timeout: $timeout_reboot
ota:
password: !secret esphome_api_password
packages:
switch: !include include/switch_reboot.yaml
sensor: !include include/sensor_wifi_uptime.yaml
text_sensor: !include include/text_sensor_wifi_uptime.yaml
binary_sensor: !include include/binary_sensor_status.yaml
#### Shelly UNI PIN Guide ####
## Onboard Internal LED, Status LED # GPIO00
## Onboard Relay 2 # GPIO04
## Onboard Relay 1 # GPIO15
## UNI pin1 Red VCC IN
## UNI pin2 Black GND / N
## UNI pin3 White ADC_IN, analog PIN, ADC Range # GPIO17
## UNI pin4 Yellow VCC 3.3VDC Output, VCC Sensor
## UNI pin5 Blue Data, AM2301 # GPIO05
## UNI pin6 Green Internal GND
## UNI pin7 Light Brown Input 1, Switch_n1 # GPIO12
## UNI pin8 Dark Brown Input 2, Switch_n2 # GPIO13
light:
## Enable onboard LED
- platform: status_led
name: "Status LED"
pin: GPIO00
internal: true
sensor:
## Temperature and Humidity,
## UNI pin4 Yellow to DHT VCC+
## UNI pin5 Blue to DHT Data
## UNI pin6 Green to DHT GND-
- platform: dht
pin: GPIO05
model: DHT22
update_interval: $dht22_update
temperature:
name: "Temperature"
id: temperature
accuracy_decimals: 1
humidity:
name: "Humidity"
id: humidity
accuracy_decimals: 0
## Analog Sensor ADC_IN, Filter to states
## GPIO17, UNI pin3 White ADC_IN
## Values: 2 = Closing, 4 = Idle, 6 = Opening
- platform: adc
pin: GPIO17
name: "Door Motion Sensor"
id: door_motion
update_interval: 2s
filters:
- multiply: 10
- lambda: |-
if (x > 6.6) {
return 6;
} else if (x < 6.1) {
return 2;
} else {
return 4;
}
internal: true
binary_sensor:
## Contact sensor top
## GPIO12, UNI pin8 Light Brown and UNI pin1 Red (VCC Main)
- platform: gpio
pin:
number: 12
inverted: $sensor_invert_top
name: "End Sensor Top"
id: end_sensor_top
on_state:
then:
- component.update: cover_state
internal: true
## Contact sensor bottom
## GPIO13, UNI pin7 Dark Brown and UNI pin1 Red (VCC Main)
- platform: gpio
pin:
number: 13
inverted: $sensor_invert_bottom
name: "End Sensor Bottom"
id: end_sensor_bottom
on_state:
then:
- component.update: cover_state
internal: true
switch:
## Button relay 1
- platform: gpio
pin: GPIO15
name: "Relay 1"
id: relay1
internal: $hide_relay1
## Prevent relay1 and relay2 from being activated at the same time.
# interlock: &interlock_group [relay1, relay2]
on_turn_on:
- delay: $button_delay
- switch.turn_off: relay1
## Button relay 2
- platform: gpio
pin: GPIO04
name: "Relay 2"
id: relay2
internal: $hide_relay2
## Prevent relay1 and relay2 from being activated at the same time.
# interlock: *interlock_group
on_turn_on:
- delay: $button_delay
- switch.turn_off: relay2
text_sensor:
## State to HomeAssistant, to create template sensor or template cover
- platform: template
name: Cover State
icon: mdi:garage
id: cover_state
# update_interval: 2s
lambda: |-
if ((id(end_sensor_bottom).state == 0) && (id(end_sensor_top).state == 1)) {
return {"Fully Open"};
} else if ((id(end_sensor_bottom).state == 1) && (id(end_sensor_top).state == 0)) {
return {"Fully Closed"};
} else if ((id(end_sensor_bottom).state == 0) && (id(end_sensor_top).state == 0) && (id(door_motion).state == 4)) {
return {"Partially Open"};
} else if ((id(end_sensor_bottom).state == 0) && (id(end_sensor_top).state == 0) && (id(door_motion).state == 2)) {
return {"Door is Closing"};
} else if ((id(end_sensor_bottom).state == 0) && (id(end_sensor_top).state == 0) && (id(door_motion).state == 6)) {
return {"Door is Opening"};
} else {
return {"Loading"};
}
cover:
## Garage Cover, use in Android Auto, and other frontends, cloud solutions...
- platform: template
device_class: garage
name: "Door"
id: door_2
internal: $hide_cover
lambda: |-
if ((id(end_sensor_bottom).state == 1) && (id(end_sensor_top).state == 0) && (id(door_motion).state == 4)) {
return COVER_CLOSED;
} else {
return COVER_OPEN;
}
open_action:
- switch.turn_on: relay1
close_action:
- switch.turn_on: relay1
Template sensor in configuration.yaml or sensor.yaml
to include sensors from sensor.yaml add sensor: !include sensor.yaml to configuration.yaml.
# Garage 2 State Icons and State Text
- platform: template
sensors:
garage_2_cover_state:
friendly_name: Garage 2 Cover
# Set state based on the state of a seperate sensor
value_template: >-
{{ states('sensor.garage_2_uni_cover_state') }}
# Set the icon based on state of a seperate sensor
icon_template: >-
{% if is_state("sensor.garage_2_cover_state", "Fully Open") -%}
mdi:garage-open
{% elif is_state("sensor.garage_2_cover_state", "Fully Closed") -%}
mdi:garage
{% elif is_state("sensor.garage_2_cover_state", "Partially Open") -%}
mdi:garage-alert
{% elif is_state("sensor.garage_2_cover_state", "Door is Closing") -%}
mdi:arrow-down-thick
{% elif is_state("sensor.garage_2_cover_state", "Door is Opening") -%}
mdi:arrow-up-thick
{% else -%}
mdi:alert-circle
{% endif %}
If you want to use cover instead of sensor you can create a cover in configuration.yaml
I was not happy with the status color change, it changed randomly.
Don’t forget to expose relay to frontend.
- platform: template
covers:
garage_door:
device_class: garage
friendly_name: "Garage2 Door"
open_cover:
service: switch.toggle
target:
entity_id: switch.garage_2_relay_1
close_cover:
service: switch.toggle
target:
entity_id: switch.garage_2_relay_1
stop_cover:
service: switch.toggle
target:
entity_id: switch.garage_2_relay_1
icon_template: >-
{% if is_state("sensor.garage_2_cover_state", "Fully Open") -%}
mdi:garage-open
{% elif is_state("sensor.garage_2_cover_state", "Fully Closed") -%}
mdi:garage
{% elif is_state("sensor.garage_2_cover_state", "Partially Open") -%}
mdi:garage-alert
{% elif is_state("sensor.garage_2_cover_state", "Door is Closing") -%}
mdi:arrow-down-thick
{% elif is_state("sensor.garage_2_cover_state", "Door is Opening") -%}
mdi:arrow-up-thick
{% else -%}
mdi:alert-circle
{% endif %}