shklth
(Shklth)
December 12, 2024, 9:44am
1
Hi there,
I have 22 blinds that I would like to control using ESPHome. My system is centralized, with all the blinds connected to a central box in the house. For this setup, I’ve utilized one ESPHome board and MCP23017 GPIO expanders.
I have successfully created a working program for a few blinds, but now I need to scale it up to control all 22. While copying and pasting the code 22 times is an option, I prefer to do it in a more modular way.
I’ve tried using substitutions, and this is where I am currently. I have two files: one is the main configuration file, and the other is a general configuration file. In cover component, I do multiple includes and set proper variables for each include.
main.yaml
substitutions:
open_duration: 10s
close_duration: 10s
mcp23017_adr_1: '20'
mcp23017_adr_2: '21'
esphome:
name: roletar
friendly_name: roletar
esp32:
board: denky32
#board: esp32dev
framework:
type: arduino
# Enable logging
logger:
# Enable Home Assistant API
api:
encryption:
ota:
platform: esphome
wifi:
ssid: !secret wifi_ssid
password: !secret wifi_password
# Enable fallback hotspot (captive portal) in case wifi connection fails
ap:
ssid: "Roletar Fallback Hotspot"
captive_portal:
i2c:
sda: 21
scl: 22
scan: true
id: bus_a
# MCP Config
### MCP pini 0-3 & 8-11 so INPUT, pini 4-7 & 12-15 so OUTPUT ###
mcp23017:
- id: "mcp23017_1"
address: ${mcp23017_adr_1}
- id: "mcp23017_2"
address: ${mcp23017_adr_2}
# Cover with !include parameters
cover:
platform: time_based
- !include
file: roleta.yaml
vars:
roleta_id: 1
roleta_name: "Roleta 1"
pin_rele_up: 4
pin_rele_down: 5
pin_key_up: 0
pin_key_down: 1
open_duration: ${open_duration}
close_duration: ${close_duration}
mcp23017_address: ${mcp23017_adr_1}
- !include
file: roleta.yaml
vars:
roleta_id: 2
roleta_name: "Roleta 2"
pin_rele_up: 6
pin_rele_down: 7
pin_key_up: 2
pin_key_down: 3
open_duration: ${open_duration}
close_duration: ${close_duration}
mcp23017_address: ${mcp23017_adr_1}
- !include
file: roleta.yaml
vars:
roleta_id: 3
roleta_name: "Roleta 3"
pin_rele_up: 12
pin_rele_down: 13
pin_key_up: 8
pin_key_down: 9
open_duration: ${open_duration}
close_duration: ${close_duration}
mcp23017_address: ${mcp23017_adr_1}
And general file roleta.yaml
esphome:
name: roleta
esp32:
board: denky32
#board: esp32dev
framework:
type: arduino
substitutions: #this gets replaced with include vars
roleta_id: '1'
roleta_name: "Roleta 1"
pin_rele_up: '4'
pin_rele_down: '5'
pin_key_up: '0'
pin_key_down: '1'
open_duration: 10s
close_duration: 10s
mcp23017_address: '20'
cover:
- id: "roleta_${roleta_id}"
platform: time_based
name: "${roleta_name}"
open_action:
- switch.turn_on: "rele_${roleta_id}_up"
open_duration: ${open_duration}
close_action:
- switch.turn_on: "rele_${roleta_id}_down"
close_duration: ${close_duration}
stop_action:
- switch.turn_off: "rele_${roleta_id}_up"
- switch.turn_off: "rele_${roleta_id}_down"
on_closed:
then:
- switch.turn_on: "rele_${roleta_id}_down"
- delay: 2s
- switch.turn_off: "rele_${roleta_id}_down"
switch:
- id: "rele_${roleta_id}_up"
platform: gpio
name: "Rele Gor ${roleta_id}"
pin:
mcp23xxx: ${mcp23017_address}
number: ${pin_rele_up}
inverted: false
- id: "rele_${roleta_id}_down"
platform: gpio
name: "Rele Dol ${roleta_id}"
pin:
mcp23xxx: ${mcp23017_address}
number: ${pin_rele_down}
inverted: false
binary_sensor:
- id: "tipka_${roleta_id}_up"
platform: gpio
name: "Tipka Gor ${roleta_id}"
pin:
mcp23xxx: ${mcp23017_address}
number: ${pin_key_up}
inverted: false
on_click:
then:
- cover.open: "roleta_${roleta_id}"
- id: "tipka_${roleta_id}_down"
platform: gpio
name: "Tipka Dol ${roleta_id}"
pin:
mcp23xxx: ${mcp23017_address}
number: ${pin_key_down}
inverted: false
on_click:
then:
- cover.close: "roleta_${roleta_id}"
I’m brain-dead at this point, tried too many things, could not get it to validate. I even used chatgpt.
Main question for me now is, is it even possible to do this on ESPHome?
shklth
(Shklth)
December 15, 2024, 1:01pm
3
Thank you! I saw it before, but I dismissed it as a variant of substitutions. Since I’m weak in coding, the sample provided didn’t give me enough info. However, after revisiting it, I tried again, and after a few days it’s working now. I’ve pasted the code below in case it might be useful for someone else.
substitutions:
open_duration: 10s
close_duration: 10s
mcp23017_adr_1: "0x20" # 1st MCP23017
mcp23017_adr_2: "0x21" # 2nd MCP23017
esphome:
name: roletar
friendly_name: roletar
esp32:
board: denky32
#board: esp32dev
framework:
type: arduino
# Enable logging
logger:
# Enable Home Assistant API
api:
ota:
platform: esphome
wifi:
ssid: !secret wifi_ssid
password: !secret wifi_password
# Enable fallback hotspot (captive portal) in case wifi connection fails
ap:
ssid: "Roletar Fallback Hotspot"
captive_portal:
i2c:
sda: 21
scl: 22
scan: true
id: bus_a
# MCP Config
### MCP pini 0-3 & 8-11 so INPUT, pini 4-7 & 12-15 so OUTPUT ###
mcp23017:
- id: "mcp23017_1"
address: ${mcp23017_adr_1}
- id: "mcp23017_2"
address: ${mcp23017_adr_2}
# Packages (cover) with !include parameters
packages:
roleta_1: !include
file: packages/roleta.yaml
vars:
roleta_id: 1
roleta_name: "Roleta 1"
pin_key_up: 0
pin_key_down: 1
pin_rele_up: 4
pin_rele_down: 5
open_duration: ${open_duration}
close_duration: ${close_duration}
mcp23017_id: mcp23017_1
roleta_2: !include
file: packages/roleta.yaml
vars:
roleta_id: 2
roleta_name: "Roleta 2"
pin_key_up: 2
pin_key_down: 3
pin_rele_up: 6
pin_rele_down: 7
open_duration: ${open_duration}
close_duration: ${close_duration}
mcp23017_id: mcp23017_1
roleta_3: !include
file: packages/roleta.yaml
vars:
roleta_id: 3
roleta_name: "Roleta 3"
pin_key_up: 8
pin_key_down: 9
pin_rele_up: 12
pin_rele_down: 13
open_duration: ${open_duration}
close_duration: ${close_duration}
mcp23017_id: mcp23017_1
roleta_4: !include
file: packages/roleta.yaml
vars:
roleta_id: 4
roleta_name: "Roleta 4"
pin_key_up: 10
pin_key_down: 11
pin_rele_up: 14
pin_rele_down: 15
open_duration: ${open_duration}
close_duration: ${close_duration}
mcp23017_id: mcp23017_1
roleta_5: !include
file: packages/roleta.yaml
vars:
roleta_id: 5
roleta_name: "Roleta 5"
pin_key_up: 0
pin_key_down: 1
pin_rele_up: 4
pin_rele_down: 5
open_duration: ${open_duration}
close_duration: ${close_duration}
mcp23017_id: mcp23017_2
roleta_6: !include
file: packages/roleta.yaml
vars:
roleta_id: 6
roleta_name: "Roleta 6"
pin_key_up: 2
pin_key_down: 3
pin_rele_up: 6
pin_rele_down: 7
open_duration: ${open_duration}
close_duration: ${close_duration}
mcp23017_id: mcp23017_2
roleta_7: !include
file: packages/roleta.yaml
vars:
roleta_id: 7
roleta_name: "Roleta 7"
pin_key_up: 8
pin_key_down: 9
pin_rele_up: 12
pin_rele_down: 13
open_duration: ${open_duration}
close_duration: ${close_duration}
mcp23017_id: mcp23017_2
roleta_8: !include
file: packages/roleta.yaml
vars:
roleta_id: 8
roleta_name: "Roleta 8"
pin_key_up: 10
pin_key_down: 11
pin_rele_up: 14
pin_rele_down: 15
open_duration: ${open_duration}
close_duration: ${close_duration}
mcp23017_id: mcp23017_2
And roleta.yaml
substitutions:
roleta_id: '0'
roleta_name: "Default Roleta"
pin_rele_up: '0'
pin_rele_down: '1'
pin_key_up: '2'
pin_key_down: '3'
open_duration: 10s
close_duration: 10s
mcp23017_id: mcp23017_1
cover:
- id: "cover_roleta_${roleta_id}"
platform: time_based
name: "${roleta_name}"
open_action:
- switch.turn_on: "rele_up_roleta_${roleta_id}"
open_duration: ${open_duration}
close_action:
- switch.turn_on: "rele_down_roleta_${roleta_id}"
close_duration: ${close_duration}
stop_action:
- switch.turn_off: "rele_up_roleta_${roleta_id}"
- switch.turn_off: "rele_down_roleta_${roleta_id}"
on_closed: #for making sure that it is closed
then:
- switch.turn_on: "rele_down_roleta_${roleta_id}"
- delay: 2s
- switch.turn_off: "rele_down_roleta_${roleta_id}"
switch:
- id: "rele_up_roleta_${roleta_id}"
platform: gpio
name: "Rele Gor Roleta ${roleta_id}"
pin:
mcp23xxx: ${mcp23017_id}
number: ${pin_rele_up}
inverted: false
restore_mode: RESTORE_DEFAULT_OFF
interlock: ["rele_down_roleta_${roleta_id}"]
- id: "rele_down_roleta_${roleta_id}"
platform: gpio
name: "Rele Dol Roleta ${roleta_id}"
pin:
mcp23xxx: ${mcp23017_id}
number: ${pin_rele_down}
inverted: false
restore_mode: RESTORE_DEFAULT_OFF
interlock: ["rele_up_roleta_${roleta_id}"]
binary_sensor:
- id: "tipka_up_roleta_${roleta_id}"
platform: gpio
name: "Tipka Gor Roleta ${roleta_id}"
pin:
mcp23xxx: ${mcp23017_id}
number: ${pin_key_up}
mode:
input: true
pullup: true
inverted: false
on_click:
min_length: 50ms
max_length: 500ms
then:
- cover.open: "cover_roleta_${roleta_id}"
on_multi_click:
- timing:
- ON for at least 500ms
then:
- cover.open: "cover_roleta_${roleta_id}"
- wait_until:
condition:
binary_sensor.is_off: "tipka_up_roleta_${roleta_id}"
- cover.stop: "cover_roleta_${roleta_id}"
- id: "tipka_down_roleta_${roleta_id}"
platform: gpio
name: "Tipka Dol Roleta ${roleta_id}"
pin:
mcp23xxx: ${mcp23017_id}
number: ${pin_key_down}
mode:
input: true
pullup: false
inverted: false
on_click:
min_length: 50ms
max_length: 500ms
then:
- cover.close: "cover_roleta_${roleta_id}"
on_multi_click:
- timing:
- ON for at least 500ms
then:
- cover.close: "cover_roleta_${roleta_id}"
- wait_until:
condition:
binary_sensor.is_off: "tipka_down_roleta_${roleta_id}"
- cover.stop: "cover_roleta_${roleta_id}"
1 Like