Files
zorruno-homeassistant/esphome/esp-6buttontest-pmb.yaml
2025-08-06 16:17:14 +12:00

1021 lines
36 KiB
YAML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

##########################################################################################
##########################################################################################
# PMB Electronics 6 Button ESP32 Switch
#
# V1.1 2025-08-06 Various function updates, Ext V calibrated (for my unit)
# V1.0 2025-08-04 Initial Version
##########################################################################################
# PMB Product Details Page https://rcbeacon.com/blog/?p=5488
#
# DEVICE GPIO
# ------------------------------------------
# GPIO36 ADC1 (knob) GPIO39 ADC2 (Supply V)
# GPIO19 Button1 GPIO21 LED1
# GPIO35 Button2 GPIO25 LED2
# GPIO05 Button3 GPIO18 LED3
# GPIO33 Button4 GPIO26 LED4
# GPIO16 Button5 GPIO17 LED5
# GPIO12 Button6 GPIO13 LED6 (6 button/led may not be Populated)
#
# OPERATION (as at V1.1)
# 1. Buttons 1-3: These toggle a virtual relay (v_relay1 to 3) and also turn on the
# associated LED when pressed. Inputs are debounced.
# 2. Button 4: As with buttons1-3,but also if double pressed, the v_relay only
# stays on for a short period (default 30s) then switches off. The LED fast flashes.
# If it is held down, it stays on for longer (1hr default) and the LED slow flashes.
# 3. Button 5: As with Buttons1-3 BUT if double pressed, a different v_relay switches on
# (5B) and the LED slowly pulses. If held down for 2 seconds, a 3rd v_relay switches
# on (5C) and the LED fast pulses. The 3 v_relays are exclusive, only one can be
# on at a time.
# 4. The knob gives a reported value of 0-100% when turned (as well as the adc value).
# this can be calibrated in the substitutions section
# 5. The system supply voltage is reported (~10-20V).
# 6. Power Loss: LEDs and v_relays are restored on power loss (restore settings saved
# every 10s). If v_relay4 was turned on with a timer (double press or hold), the
# state isn't restored on power loss.
# 7. There is an overall brigntness slider/variable. This allows the LEDs (except when
# flashing) to have a maximum brightness (eg for night mode)
#
# NOTES
# 1. To Flash via ESPHome, you likely have to connect to the computer, start the flash
# then hold down I00 button. I think GPIO12 connection is preventing the flash process.
# 2. OTA flash to an Existing Tasmota device is likely a bit hard with and ESP32 as they
# expect a signed Tasmota binary... and partition layout needs to be fixed anyway
# 3. ESPHome warns on compiling: "legacy adc driver is deprecated, please migrate to use
# esp_adc/adc_oneshot.h and esp_adc/adc_continuous.h for oneshot mode and continuous mode
# drivers respectively" [-Wcpp]" (I'm not bothered with this)
# 4. Normally I'd include SNTP for timing/scheduling functions, and uptime diagnostics etc.
# I have commented this out in the packages section as not sure it is really needed here.
#
##########################################################################################
##########################################################################################
##########################################################################################
# SPECIFIC DEVICE VARIABLE SUBSTITUTIONS
# USUALLY YOU WILL ONLY NEED TO CHANGE VALUES UNDER THIS SECTION
# If NOT using a secrets file, just replace "!secret my_key" with the password etc (in quotes)
##########################################################################################
substitutions:
# Device Naming
device_name: "esp-6buttontest-pmb" # the filename should be the device_name.yaml
friendly_name: "PMB Light Switch Test"
description_comment: "Multi Button Wallswitch in standard AU/NZ flush size. In this case 5 Buttons with LEDs and one Knob"
device_area: "Lounge" # Allows ESP device to be automatically linked to an 'Area' in Home Assistant.
# Wifi details
wifi_ssid: !secret ha_wifi_ssid
wifi_password: !secret ha_wifi_password
fallback_ap_password: !secret fallback_ap_password # if it doesn't connect, it will create its own AP
# Passwords
api_key: !secret esp-api_key # unfortunately you can't use substitutions inside secrets names
ota_pass: !secret esp-ota_pass # unfortunately you can't use substitutions inside secrets names
static_ip_address: !secret esp-6buttontest-pmb_ip
# Add these if we are giving it a static ip, or remove them in the Wifi section
static_ip_subnet: !secret ha_wifi_subnet
static_ip_gateway: !secret ha_wifi_gateway
static_ip_dns1: !secret ha_wifi_dns1
static_ip_dns2: !secret ha_wifi_dns2
# MQTT Settings
mqtt_server: !secret ha_mqtt_server
mqtt_username: !secret ha_mqtt_username
mqtt_password: !secret ha_mqtt_password
mqtt_topic: "esphome" # main topic for the mqtt server, call it what you like
# Web Server Settings
web_server_username: !secret web_server_username
web_server_password: !secret web_server_password
# Switch Naming
switch_1_name: "Red"
switch_2_name: "White"
switch_3_name: "Green"
switch_4_name: "Orange"
switch_5_name: "Blue"
switch_5b_name: "Blue (Double)"
switch_5c_name: "Blue (Hold)"
# switch_6_name: "Spare"
variable_1_name: "Dimmer"
variable_1_full_scale: "3.14" # ADC reading when at 100% (adjust after calibration)
variable_1_min_scale: "0.14" # volts at ADC for 0% (adjust after calibration)
# Device Settings
log_level: "INFO" # Define logging level: NONE, ERROR, WARN, INFO, DEBUG (Default), VERBOSE, VERY_VERBOSE
update_interval: "60s" # update time for for general sensors etc
pwm_freq: "1000Hz" # ESPHome default is 1000Hz, but will go much higher... (not much point for a switch LED)
ledc_bits: "12" # ESPHome default resolution is 12 bits
# Network reconnect every x hours to ensure best access point
# This is my own script. No need to use if only one AP or it is always fixed.
base_interval_hours: "23" # Base interval in hours
random_offset_max_minutes: "59" # Max random offset in minutes
# Enables faster network connections, with last connected SSID being connected to and
# no full scan for SSID being undertaken
wifi_fast_connect: "false"
# Define a domain for this device to use. i.e. iot.home.lan (so device will appear as
# athom-smart-plug-v2.iot.home.lan in DNS/DHCP logs)
dns_domain: ".local"
# Automatically add the mac address to the name eg so you can use a single firmware for all devices
# I don't tend to like doing this, but good for many identical devices
add_mac_suffix: "false"
# Enable or disable the use of IPv6 networking on the device
ipv6_enable: "false"
##########################################################################################
# PACKAGES
# Included Common Packages from other files.
# https://esphome.io/components/packages.html
##########################################################################################
# NOTE: ALL COMMENTED AS FOR THIS TEST EVERYTHING IS IN ONE YAML FILE (except no SNTP)
##########################################################################################
#packages:
#common_wifi: !include
# file: common/network_common.yaml
# vars:
# local_device_name: "${device_name}"
# local_static_ip_address: "${static_ip_address}"
# local_ota_pass: "${ota_pass}"
#common_api: !include
# file: common/api_common.yaml
# vars:
# local_api_key: "${api_key}"
#common_webportal: !include
# file: common/webportal_common.yaml
#common_mqtt: !include
# file: common/mqtt_common.yaml
# vars:
# local_device_name: "${device_name}"
#common_sntp: !include
# file: common/sntp_common.yaml
#common_general_sensors: !include
# file: common/sensors_common.yaml
# vars:
# local_friendly_name: "${friendly_name}"
# local_update_interval: "${update_interval}"
##########################################################################################
# WIFI COMPONENT
# https://esphome.io/components/wifi.html
#
# Power Save mode (can reduce wifi reliability)
# NONE (least power saving, Default for ESP8266)
# LIGHT (Default for ESP32)
# HIGH (most power saving)
##########################################################################################
wifi:
ssid: ${wifi_ssid}
password: ${wifi_password}
#enable_rrm: true # (ESP32 only) enable 802.11k Radio Resource Management
#enable_btm: true # (ESP32 only) enable 802.11v BSS Transition Management
#power_save_mode: LIGHT # https://esphome.io/components/wifi.html#wifi-power-save-mode
manual_ip: # optional static IP address
static_ip: ${static_ip_address}
gateway: ${static_ip_gateway}
subnet: ${static_ip_subnet}
dns1: ${static_ip_dns1}
dns2: ${static_ip_dns2}
ap: # Details for fallback hotspot in case wifi connection fails https://esphome.io/components/wifi.html#access-point-mode
ssid: ${device_name} AP
password: ${fallback_ap_password}
ap_timeout: 10min # Time until it brings up fallback AP. default is 1min
# Allow rapid re-connection to previously connect WiFi SSID, skipping scan of all SSID
fast_connect: "${wifi_fast_connect}"
# Define dns domain / suffix to add to hostname
domain: "${dns_domain}"
#captive_portal: # extra fallback mechanism for when connecting if the configured WiFi fails
##########################################################################################
# ESPHome OTA UPDATES
# https://esphome.io/components/ota/esphome.html
##########################################################################################
ota:
- platform: esphome
password: ${ota_pass}
version: 2
##########################################################################################
# SAFE MODE
# Safe mode will detect boot loops
# https://esphome.io/components/safe_mode
##########################################################################################
safe_mode:
##########################################################################################
# NETWORK COMPONENT
# global configuration for all types of networks
# https://esphome.io/components/network.html
##########################################################################################
network:
enable_ipv6: ${ipv6_enable}
##########################################################################################
# MQTT CLIENT COMPONENT
# https://esphome.io/components/mqtt.html?highlight=mqtt
# MUST also have api enabled if you enable MQTT!
##########################################################################################
mqtt:
broker: ${mqtt_server}
topic_prefix: ${mqtt_topic}/${device_name}
username: ${mqtt_username}
password: ${mqtt_password}
discovery: False # enable entity discovery (true is default)
discover_ip: False # enable device discovery (true is default)
id: mqtt_client
reboot_timeout: 0s # same for MQTT
##########################################################################################
# WEB SERVER COMPONENT
# https://esphome.io/components/web_server.html
# Web Portal for display and monitoring
# Turning this off is maybe a good idea to save resources, especially on an esp8266.
##########################################################################################
web_server:
port: 80
auth:
username: ${web_server_username} # probably a good idea to secure it
password: ${web_server_password}
##########################################################################################
# NATIVE API COMPONENT
# Enable the Home Assistant API
# https://esphome.io/components/api.html
##########################################################################################
api:
encryption:
key: ${api_key}
reboot_timeout: 0s # disables watchdog reboot on API failure
##########################################################################################
# ESPHome CORE CONFIGURATION
# https://esphome.io/components/esphome.html
##########################################################################################
esphome:
name: ${device_name}
friendly_name: ${friendly_name}
comment: ${description_comment} # Appears on the ESPHome page in HA
area: ${device_area}
on_boot:
then:
- lambda: |-
// if the user had manually left it ON, re-apply it now
if (id(vrelay4_manual_state)) {
id(vrelay_4).turn_on();
}
// now restore all your _other_ relays as you already had them
if (id(vrelay_1_state)) id(vrelay_1).turn_on();
if (id(vrelay_2_state)) id(vrelay_2).turn_on();
if (id(vrelay_3_state)) id(vrelay_3).turn_on();
if (id(vrelay_5_state)) id(vrelay_5).turn_on();
if (id(vrelay_5b_state)) id(vrelay_5b).turn_on();
if (id(vrelay_5c_state)) id(vrelay_5c).turn_on();
##########################################################################################
# ESP PLATFORM AND FRAMEWORK
# https://esphome.io/components/esp32.html
##########################################################################################
# Suggest using ESP-IDF Framework. Changes might need need to be cable flashed here to
# reset the partitioning
##########################################################################################
esp32:
board: esp32dev
framework:
type: esp-idf # "esp-idf" OR "arduino".
version: recommended # recommended, latest or dev
preferences:
flash_write_interval: 10s # not too important but anything written for reboot mem will wear the flash
##########################################################################################
# GLOBAL VARIABLES
# https://esphome.io/components/globals.html
##########################################################################################
# We are using globals here to store the states of the virtual relays
# They will also be restored on power loss.
##########################################################################################
globals:
- id: vrelay_1_state
type: bool
restore_value: yes
initial_value: 'false'
- id: vrelay_2_state
type: bool
restore_value: yes
initial_value: 'false'
- id: vrelay_3_state
type: bool
restore_value: yes
initial_value: 'false'
- id: vrelay_4_state
type: bool
restore_value: yes
initial_value: 'false'
- id: vrelay4_manual_state
type: bool
restore_value: yes
initial_value: 'false'
- id: vrelay4_timer_state
type: bool
restore_value: no
initial_value: 'false'
- id: vrelay_5_state
type: bool
restore_value: yes
initial_value: 'false'
- id: vrelay_5b_state
type: bool
restore_value: yes
initial_value: 'false'
- id: vrelay_5c_state
type: bool
restore_value: yes
initial_value: 'false'
- id: max_led_brightness
type: float
restore_value: yes
initial_value: '1.0' # default to 100% on first run
##########################################################################################
# LOGGER COMPONENT
# https://esphome.io/components/logger.html
# Logs all log messages through the serial port and through MQTT topics.
##########################################################################################
logger:
level: ${log_level} #INFO Level suggested, or DEBUG for testing
##########################################################################################
# STATUS LED
# https://esphome.io/components/status_led.html
##########################################################################################
# This is usually the blue LED on the ESP32 Dev board
# Status_LED can show ESPHome errors and warnings
##########################################################################################
status_led:
pin:
number: GPIO2
inverted: yes
##########################################################################################
# SCRIPT COMPONENT
# https://esphome.io/components/script.html
# Scripts can be executednearly anywhere in your devices configuration with a single call.
##########################################################################################
script:
# Restart Networking every x hours + rand mins. Starts on reboot and always runs
# This ensure that the device is connected to the best AP, but no need for it
# if one AP and it is always reliable.
- id: random_reconnect
mode: restart
then:
- lambda: |-
// Compute total delay: base hours + random offset minutes
uint32_t extra;
#if defined(ESP32)
// ESP32 (both Arduino & IDF builds) uses esp_random()
extra = esp_random() % (${random_offset_max_minutes} + 1);
#elif defined(ESP8266)
// ESP8266 Arduino core
extra = os_random() % (${random_offset_max_minutes} + 1);
#else
// Fallback to esp_random() on other platforms
extra = esp_random() % (${random_offset_max_minutes} + 1);
#endif
uint32_t total_s = ${base_interval_hours} * 3600 + extra * 60;
ESP_LOGI("random_reconnect", "Next reconnect in %u seconds", total_s);
// Delay inside lambda (blocks script execution but OK for reconnect timing)
delay(total_s * 1000);
- logger.log: "network_check: performing reconnect"
- wifi.disable: {}
- delay: 1s
- wifi.enable: {}
- script.execute: random_reconnect
# Button 4: Double-press short timer (should NOT restore after power loss)
- id: button4_short
then:
- lambda: |-
// Timed mode (not manual) → will NOT be restored on reboot
id(vrelay4_manual_state) = false;
- switch.turn_off: vrelay_4 # keep the virtual relay OFF during timer
- lambda: |-
// Start 30 s fast-flash timer
id(vrelay4_timer_state) = true;
{
auto call = id(led4).turn_on();
call.set_brightness(id(max_led_brightness));
call.set_effect("Flash Fast");
call.perform();
}
- delay: 30s
- lambda: |-
// Timer expired → clear
id(vrelay4_timer_state) = false;
- light.turn_off: led4
# Button 4: Hold long timer (should NOT restore after power loss)
- id: button4_long
then:
- lambda: |-
// Timed mode (not manual) → will NOT be restored on reboot
id(vrelay4_manual_state) = false;
- switch.turn_off: vrelay_4 # keep the virtual relay OFF during timer
- lambda: |-
// Start 60 min slow-flash timer
id(vrelay4_timer_state) = true;
{
auto call = id(led4).turn_on();
call.set_brightness(id(max_led_brightness));
call.set_effect("Flash Slow");
call.perform();
}
- delay: 60min
- lambda: |-
// Timer expired → clear
id(vrelay4_timer_state) = false;
- light.turn_off: led4
##########################################################################################
# BINARY SENSORS
# https://esphome.io/components/binary_sensor/
##########################################################################################
# These are the input buttons on GPIO.
# No "mode: INPUT_PULLUP" needed as they have external pullups
# Switches pull to GND so "inverted:true" for ESPHome to report ON when pressed.
# They will toggle the virtual relays when pressed (the vrelays will toggle the LEDs)
##########################################################################################
binary_sensor:
- platform: gpio
pin:
number: GPIO19
mode: INPUT
inverted: true
name: "Button 1: ${switch_1_name}"
filters:
- delayed_on: 50ms
- delayed_off: 50ms
on_press:
- switch.toggle: vrelay_1
- platform: gpio
pin:
number: GPIO35
mode: INPUT
inverted: true
name: "Button 2: ${switch_2_name}"
filters:
- delayed_on: 50ms
- delayed_off: 50ms
on_press:
- switch.toggle: vrelay_2
- platform: gpio
pin:
number: GPIO05
mode: INPUT
inverted: true
name: "Button 3: ${switch_3_name}"
filters:
- delayed_on: 50ms
- delayed_off: 50ms
on_press:
- switch.toggle: vrelay_3
- platform: gpio
pin:
number: GPIO33
mode: INPUT
inverted: true
name: "Button 4: ${switch_4_name}"
filters:
- delayed_on: 50ms
- delayed_off: 50ms
on_multi_click:
# Single click: cancel timers, then toggle relay+LED
- timing:
- ON for 50ms to 400ms
- OFF for at least 250ms
then:
- script.stop: button4_short
- script.stop: button4_long
- switch.toggle: vrelay_4
# Double click → short sequence
- timing:
- ON for 50ms to 400ms
- OFF for 50ms to 300ms
- ON for 50ms to 400ms
then:
- script.stop: button4_long
- script.execute: button4_short
# Hold → long sequence
- timing:
- ON for at least 2s
then:
- script.stop: button4_short
- script.execute: button4_long
- platform: gpio
pin:
number: GPIO16
mode: INPUT
inverted: true
name: "Button 5: ${switch_5_name}"
filters:
- delayed_on: 30ms
- delayed_off: 30ms
on_multi_click:
# Single click: if any of 5/5B/5C is on → turn them all off; else turn on 5
- timing:
- ON for 50ms to 400ms
- OFF for at least 250ms
then:
- lambda: |-
if (id(vrelay_5_state) || id(vrelay_5b_state) || id(vrelay_5c_state)) {
id(vrelay_5).turn_off();
id(vrelay_5b).turn_off();
id(vrelay_5c).turn_off();
} else {
id(vrelay_5).turn_on();
}
# Double click → vrelay_5b
- timing:
- ON for 50ms to 400ms
- OFF for 50ms to 300ms
- ON for 50ms to 400ms
then:
- switch.toggle: vrelay_5b
# Hold → vrelay_5c
- timing:
- ON for at least 2s
then:
- switch.toggle: vrelay_5c
# FUTURE: Board allows for 6 buttons
#- platform: gpio
# pin:
# number: GPIO12
# mode: INPUT
# inverted: true
# name: "Button 6: ${switch_6_name}"
# filters:
# - delayed_on: 50ms
# - delayed_off: 50ms
# on_press:
# - switch.toggle: vrelay_6
## DIAGNOSTIC ONLY SENSORS BELOW ##
- platform: status
name: "Network Status"
icon: mdi:check-network-outline
entity_category: "diagnostic"
##########################################################################################
# OUTPUT COMPONENT
# https://esphome.io/components/light/index.html
##########################################################################################
# An OUTPUT can be binary (0,1) or float, which is any value between 0 and 1.
# PWM Outputs such as "ledc" are float. https://esphome.io/components/output/ledc.html
# We could change frequency: "100Hz" and/or resolution: "12", but these are the default.
##########################################################################################
output:
- platform: ledc
id: led1_output
pin: GPIO21
frequency: ${pwm_freq}
- platform: ledc
id: led2_output
pin: GPIO25
frequency: ${pwm_freq}
- platform: ledc
id: led3_output
pin: GPIO18
frequency: ${pwm_freq}
- platform: ledc
id: led4_output
pin: GPIO26
frequency: ${pwm_freq}
- platform: ledc
id: led5_output
pin: GPIO17
frequency: ${pwm_freq}
# FUTURE: Board allows for 6 buttons
#- platform: ledc
# id: led6_output
# pin: GPIO13
# frequency: ${pwm_freq}
##########################################################################################
# LIGHT COMPONENT
# https://esphome.io/components/light/index.html
##########################################################################################
light:
# We are just going to use simple monochromatic component as only one colour to PWM control
# This doesn't actually do anything by itself, you need to tied it to an OUTPUT component.
- platform: monochromatic
id: led1
output: led1_output
name: "LED 1: ${switch_1_name}"
- platform: monochromatic
id: led2
output: led2_output
name: "LED 2: ${switch_2_name}"
- platform: monochromatic
id: led3
output: led3_output
name: "LED 3: ${switch_3_name}"
- platform: monochromatic
id: led4
output: led4_output
name: "LED 4: ${switch_4_name}"
effects:
- strobe:
name: "Flash Slow"
colors:
- state: ON
duration: 1s
- state: OFF
duration: 0.5s
- strobe:
name: "Flash Fast"
colors:
- state: ON
duration: 500ms
- state: OFF
duration: 100ms
- platform: monochromatic
id: led5
output: led5_output
name: "LED 5: ${switch_5_name}"
effects:
# Pulse 0.5s: smooth ramp between 0% and current brightness
- pulse:
name: "Pulse 0.5s"
transition_length:
on_length: 0.5s
off_length: 0.5s
update_interval: 1s
# Pulse 0.1s: ramp up 0.5s / down 0.1s
- pulse:
name: "Pulse 0.1s"
transition_length:
on_length: 0.5s
off_length: 0.1s
update_interval: 600ms
# FUTURE: Board allows for 6 buttons
#- platform: monochromatic
# id: led6
# output: led6_output
# name: "LED 6: ${switch_6_name}"
##########################################################################################
# SWITCH COMPONENT
# https://esphome.io/components/switch/
##########################################################################################
switch:
# Normally SWITCH would be for things like a relay output and turning that on and off.
# We are using it for virtual relays, that show up in Home Assistant etc, and toggling
# them along with the LEDs when the buttons are pressed.
# Separating them from the LEDs as outputs means we can do thinks like light blinking etc
# but still leave the switch outputs toggled on or off.
- platform: template
name: "Output 1: ${switch_1_name}"
id: vrelay_1
optimistic: true
restore_mode: RESTORE_DEFAULT_OFF
lambda: |-
return id(vrelay_1_state);
turn_on_action:
- lambda: |-
auto call = id(led1).turn_on();
call.set_brightness(id(max_led_brightness));
call.perform();
- lambda: |-
id(vrelay_1_state) = true;
turn_off_action:
- light.turn_off: led1
- lambda: |-
id(vrelay_1_state) = false;
- platform: template
name: "Output 2: ${switch_2_name}"
id: vrelay_2
optimistic: true
restore_mode: RESTORE_DEFAULT_OFF
lambda: |-
return id(vrelay_2_state);
turn_on_action:
- lambda: |-
auto call = id(led2).turn_on();
call.set_brightness(id(max_led_brightness));
call.perform();
- lambda: |-
id(vrelay_2_state) = true;
turn_off_action:
- light.turn_off: led2
- lambda: |-
id(vrelay_2_state) = false;
- platform: template
name: "Output 3: ${switch_3_name}"
id: vrelay_3
optimistic: true
restore_mode: RESTORE_DEFAULT_OFF
lambda: |-
return id(vrelay_3_state);
turn_on_action:
- lambda: |-
auto call = id(led3).turn_on();
call.set_brightness(id(max_led_brightness));
call.perform();
- lambda: |-
id(vrelay_3_state) = true;
turn_off_action:
- light.turn_off: led3
- lambda: |-
id(vrelay_3_state) = false;
- platform: template
name: "Output 4: ${switch_4_name}"
id: vrelay_4
optimistic: true
restore_mode: RESTORE_DEFAULT_OFF
lambda: |-
// our single "source of truth" is vrelay_4_state
return id(vrelay_4_state);
turn_on_action:
- lambda: |-
// a true manual toggle
id(vrelay4_manual_state) = true;
// clear any leftover timer (shouldn't happen)
id(vrelay4_timer_state) = false;
id(vrelay_4_state) = true;
{
auto call = id(led4).turn_on();
call.set_brightness(id(max_led_brightness));
call.perform();
}
turn_off_action:
- lambda: |-
// manual switch-off
id(vrelay4_manual_state) = false;
id(vrelay4_timer_state) = false;
id(vrelay_4_state) = false;
- light.turn_off: led4
- platform: template
name: "Output 5: ${switch_5_name}"
id: vrelay_5
optimistic: true
restore_mode: RESTORE_DEFAULT_OFF
lambda: |-
return id(vrelay_5_state);
turn_on_action:
- switch.turn_off: vrelay_5b
- switch.turn_off: vrelay_5c
- lambda: |-
auto call = id(led5).turn_on();
call.set_brightness(id(max_led_brightness));
call.perform();
- lambda: |-
id(vrelay_5_state) = true;
turn_off_action:
- light.turn_off: led5
- lambda: |-
id(vrelay_5_state) = false;
- platform: template
name: "Output 5B: ${switch_5b_name}"
id: vrelay_5b
optimistic: true
restore_mode: RESTORE_DEFAULT_OFF
lambda: |-
return id(vrelay_5b_state);
turn_on_action:
- switch.turn_off: vrelay_5
- switch.turn_off: vrelay_5c
- lambda: |-
auto call = id(led5).turn_on();
call.set_brightness(id(max_led_brightness));
call.set_effect("Pulse 0.5s");
call.perform();
- lambda: |-
id(vrelay_5b_state) = true;
turn_off_action:
- light.turn_off: led5
- lambda: |-
id(vrelay_5b_state) = false;
- platform: template
name: "Output 5C: ${switch_5c_name}"
id: vrelay_5c
optimistic: true
restore_mode: RESTORE_DEFAULT_OFF
lambda: |-
return id(vrelay_5c_state);
turn_on_action:
- switch.turn_off: vrelay_5
- switch.turn_off: vrelay_5b
- lambda: |-
auto call = id(led5).turn_on();
call.set_brightness(id(max_led_brightness));
call.set_effect("Pulse 0.1s");
call.perform();
- lambda: |-
id(vrelay_5c_state) = true;
turn_off_action:
- light.turn_off: led5
- lambda: |-
id(vrelay_5c_state) = false;
# FUTURE: Board allows for 6 buttons
#- platform: template
# name: "Output 6: ${switch_6_name}"
# id: vrelay_6
# lambda: |-
# return id(vrelay_6_state);
# turn_on_action:
# - light.turn_on: led6
# - lambda: |-
# id(vrelay_6_state) = true;
# turn_off_action:
# - light.turn_off: led6
# - lambda: |-
# id(vrelay_6_state) = false;
##########################################################################################
# SENSOR COMPONENT
# https://esphome.io/components/sensor/
##########################################################################################
sensor:
# Raw ADC reading from GPIO36
# ADC Component https://esphome.io/components/sensor/adc.html
- platform: adc
pin: GPIO36
id: dimmer_raw
name: "${variable_1_name} Raw"
attenuation: 11db
update_interval: 0.5s
on_value:
then:
- lambda: |-
// Convert raw ADC (x) to volts
float volts = x;
// Apply min/max calibration
float min_v = ${variable_1_min_scale};
float max_v = ${variable_1_full_scale};
// Calculate percentage between min and max
float pct = ((volts - min_v) / (max_v - min_v)) * 100.0;
// Clamp result between 0 and 100
if (pct > 100.0) pct = 100.0;
if (pct < 0.0) pct = 0.0;
// Publish to percentage sensor
id(dimmer_percent).publish_state(pct);
# Percentage sensor derived from raw ADC
- platform: template
id: dimmer_percent
name: "${variable_1_name}"
unit_of_measurement: "%"
accuracy_decimals: 0
# External supply voltage from GPIO39
- platform: adc
pin: GPIO39
name: "External Supply Voltage"
id: supply_voltage
attenuation: 12db
update_interval: 2s
filters:
- calibrate_linear: # https://esphome.io/components/sensor/#calibrate-linear
# Format: raw_value -> real_voltage_at_pin
- 1.80 -> 20.00 # Example: ADC reads X when pin is -> actually Y
- 1.35 -> 15.00
- 0.89 -> 10.00
#- multiply: 4.00 # Voltage divider ratio
unit_of_measurement: "V"
## DIAGNOSTIC ONLY SENSORS BELOW ##
- platform: uptime # Uptime for this device in seconds
name: "Uptime (s):"
update_interval: ${update_interval}
id: uptime_sensor
entity_category: "diagnostic"
- platform: wifi_signal # Wifi Strength
name: "Wifi (dB):"
id: wifi_signal_db
update_interval: ${update_interval}
entity_category: "diagnostic"
- platform: copy # Reports the WiFi signal strength in %
source_id: wifi_signal_db
name: "WiFi (%):"
filters:
- lambda: return min(max(2 * (x + 100.0), 0.0), 100.0);
unit_of_measurement: "% Max"
entity_category: "diagnostic"
device_class: ""
##########################################################################################
# TEXT SENSOR COMPONENT
# https://esphome.io/components/text_sensor/index.html
##########################################################################################
text_sensor:
## DIAGNOSTIC ONLY SENSORS BELOW ##
- platform: version
name: "Version:"
entity_category: "diagnostic"
- platform: wifi_info
ip_address:
icon: mdi:ip-network
entity_category: diagnostic
name: "IP Address:"
ssid:
name: "Connected SSID"
icon: mdi:wifi-strength-2
entity_category: diagnostic
mac_address:
name: "MAC Address:"
icon: mdi:network-pos
entity_category: diagnostic
- platform: uptime # Uptime for this device human readable
name: "Uptime:"
icon: mdi:clock-start
update_interval: ${update_interval}
entity_category: "diagnostic"
##########################################################################################
# BUTTON COMPONENT
# https://esphome.io/components/button/
##########################################################################################
# Diagnostic buttons ued here and non-active by default, activated if needed in HA
##########################################################################################
button:
## DIAGNOSTIC ONLY BUTTONS BELOW ##
- platform: safe_mode
name: "Safe Mode Restart:"
entity_category: "diagnostic"
disabled_by_default: true # Need to activate them in HA
- platform: restart
name: "Restart:"
entity_category: "diagnostic"
disabled_by_default: true
- platform: factory_reset
name: "FACTORY RESET:"
entity_category: "diagnostic"
disabled_by_default: true
##########################################################################################
# NUMBER COMPONENT
# https://esphome.io/components/number/
##########################################################################################
number:
- platform: template
name: "LED Max Brightness"
id: led_max_brightness_number
optimistic: true
restore_value: true
initial_value: "1.0" # show 100% on first boot
min_value: 0.2
max_value: 1.0
step: 0.05
unit_of_measurement: "%"
set_action:
- lambda: |-
// store the new max
id(max_led_brightness) = x;
// if any LED is currently on, re-apply at new brightness
if (id(vrelay_1_state)) {
auto call = id(led1).turn_on();
call.set_brightness(x);
call.perform();
}
if (id(vrelay_2_state)) {
auto call = id(led2).turn_on();
call.set_brightness(x);
call.perform();
}
if (id(vrelay_3_state)) {
auto call = id(led3).turn_on();
call.set_brightness(x);
call.perform();
}
if (id(vrelay_4_state)) {
auto call = id(led4).turn_on();
call.set_brightness(x);
call.perform();
}
if (id(vrelay_5_state)) {
auto call = id(led5).turn_on();
call.set_brightness(x);
call.perform();
}