esphome lounge switches and scene control
This commit is contained in:
@@ -91,7 +91,6 @@ substitutions:
|
||||
device_usr_button: GPIO04 # this is just a fake/safeish choice so it compiles with my generic yaml
|
||||
device_fading_led: GPIO13 # this is just a fake/safeish choice so it compiles with my generic yaml
|
||||
|
||||
|
||||
##########################################################################################
|
||||
# PACKAGES: Included Common Packages
|
||||
# https://esphome.io/components/packages.html
|
||||
@@ -125,26 +124,22 @@ packages:
|
||||
|
||||
#### DIAGNOSTICS Sensors ####
|
||||
diag_basic: !include common/include_basic_diag_sensors.yaml
|
||||
diag_more: !include common/include_more_diag_sensors.yaml
|
||||
diag_debug: !include common/include_debug_diag_sensors.yaml
|
||||
diag_resetcount: !include common/include_resetcount_diag_sensors.yaml
|
||||
#diag_more: !include common/include_more_diag_sensors.yaml
|
||||
#diag_debug: !include common/include_debug_diag_sensors.yaml
|
||||
#diag_resetcount: !include common/include_resetcount_diag_sensors.yaml
|
||||
|
||||
##########################################################################################
|
||||
# ESPHome CORE CONFIGURATION
|
||||
# https://esphome.io/components/esphome.html
|
||||
##########################################################################################
|
||||
esphome:
|
||||
platformio_options:
|
||||
build_flags:
|
||||
- -DVTABLES_IN_FLASH
|
||||
- -DPIO_FRAMEWORK_ARDUINO_LWIP2_LOW_MEMORY
|
||||
name: "${device_name}"
|
||||
friendly_name: "${friendly_name}"
|
||||
comment: "${description_comment}"
|
||||
area: "${device_area}"
|
||||
on_boot:
|
||||
# Run later so everything is initialised before we touch states.
|
||||
priority: 150
|
||||
priority: 200
|
||||
then:
|
||||
# Keep the HA dropdown in sync with the stored mode
|
||||
- lambda: |-
|
||||
@@ -184,6 +179,9 @@ esphome:
|
||||
# Boot complete: allow OFF handlers again
|
||||
- lambda: 'id(booting) = false;'
|
||||
|
||||
# NEW: force indicator OFF after boot logic
|
||||
- output.turn_off: green_led_out
|
||||
|
||||
# Only if you want to play with build flags...
|
||||
# platformio_options:
|
||||
# build_unflags:
|
||||
@@ -208,7 +206,7 @@ mdns:
|
||||
disabled: true # Disabling will make the build file smaller (and device is still available via static IP)
|
||||
|
||||
preferences:
|
||||
flash_write_interval: 10sec # enough time to update values for reboots, but not enough to wear flash
|
||||
flash_write_interval: 2min # enough time to update values for reboots, but not enough to wear flash
|
||||
|
||||
##########################################################################################
|
||||
# GLOBAL VARIABLES
|
||||
@@ -274,11 +272,6 @@ globals:
|
||||
type: int
|
||||
restore_value: false
|
||||
initial_value: '0'
|
||||
# last non-zero actual 0..100 used, for stable "Restore Brightness"
|
||||
- id: last_nonzero_brightness_pct
|
||||
type: float
|
||||
restore_value: true
|
||||
initial_value: '0.0'
|
||||
# target for "Restore Brightness" scripted ramp
|
||||
- id: restore_target_pct
|
||||
type: float
|
||||
@@ -289,17 +282,12 @@ globals:
|
||||
type: bool
|
||||
restore_value: false
|
||||
initial_value: 'false'
|
||||
# volatile (non-persistent) last non-zero brightness during ramps
|
||||
- id: last_nonzero_tmp
|
||||
type: float
|
||||
restore_value: false
|
||||
initial_value: '0.0'
|
||||
# guards OFF persistence during startup caused by restore_mode: ALWAYS_OFF
|
||||
- id: booting
|
||||
type: bool
|
||||
restore_value: false
|
||||
initial_value: 'true'
|
||||
# true only while we are performing a ramp-down that briefly turns the light ON to hit the floor
|
||||
# true only while we are performing a ramp-down that briefly turns the light ON to hit the floor
|
||||
- id: ramping_for_off
|
||||
type: bool
|
||||
restore_value: false
|
||||
@@ -328,7 +316,6 @@ status_led:
|
||||
# This adds device-specific MQTT command triggers to the common MQTT configuration.
|
||||
##########################################################################################
|
||||
mqtt:
|
||||
reboot_timeout: 0s
|
||||
on_message:
|
||||
# Light control to ramp up
|
||||
- topic: "${mqtt_local_command_topic}/light/set"
|
||||
@@ -402,8 +389,6 @@ button:
|
||||
# Stop any pending scripts (and their delayed actions)
|
||||
- script.stop: ramp_on_script
|
||||
- script.stop: ramp_off_script
|
||||
- script.stop: led_flash_up
|
||||
- script.stop: led_flash_down
|
||||
- output.turn_off: green_led_out
|
||||
- lambda: |-
|
||||
// We are no longer ramping (up or down)
|
||||
@@ -420,14 +405,14 @@ button:
|
||||
call.perform();
|
||||
}
|
||||
|
||||
// Persist the exact frozen level so "Restore Brightness" survives a reboot
|
||||
// Persist the exact frozen level so restore survives a reboot
|
||||
if (cv.is_on()) {
|
||||
float pct = cv.get_brightness() * 100.0f;
|
||||
id(last_brightness_pct) = pct;
|
||||
if (pct > 0.5f) id(last_nonzero_brightness_pct) = pct;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#########################################################################################
|
||||
# SELECT COMPONENT
|
||||
# https://esphome.io/components/select/index.html
|
||||
@@ -468,8 +453,8 @@ binary_sensor:
|
||||
pullup: true
|
||||
inverted: true
|
||||
filters:
|
||||
- delayed_on: 20ms
|
||||
- delayed_off: 20ms
|
||||
- delayed_on: 30ms
|
||||
- delayed_off: 30ms
|
||||
on_press:
|
||||
- if:
|
||||
condition:
|
||||
@@ -500,29 +485,16 @@ sensor:
|
||||
unit_of_measurement: "%"
|
||||
icon: mdi:percent
|
||||
accuracy_decimals: 0
|
||||
update_interval: 500ms # consider higher if you want fewer updates
|
||||
update_interval: 1s # consider 200ms if you want fewer updates
|
||||
lambda: |-
|
||||
const auto &cv = id(mosfet_leds).current_values;
|
||||
return cv.is_on() ? (cv.get_brightness() * 100.0f) : 0.0f;
|
||||
on_value:
|
||||
then:
|
||||
- lambda: |-
|
||||
const auto &cv_now = id(mosfet_leds).current_values;
|
||||
|
||||
// Only persist exact last brightness while actually ON,
|
||||
// and not during the OFF ramp's brief floor-kick.
|
||||
if (cv_now.is_on()) {
|
||||
if (x > 0.5f) {
|
||||
if (!id(is_ramping)) id(last_nonzero_brightness_pct) = x;
|
||||
id(last_nonzero_tmp) = x;
|
||||
}
|
||||
} else {
|
||||
if (x > 0.5f) id(last_nonzero_tmp) = x;
|
||||
}
|
||||
|
||||
// If not suppressing sync, update the 0..100 slider only when its INT changes
|
||||
if (!id(suppress_slider_sync)) {
|
||||
float actual = x;
|
||||
float actual = x; // x is current Output (%)
|
||||
float minp = (float) id(min_brightness_pct);
|
||||
float maxp = (float) id(max_brightness_pct);
|
||||
if (maxp <= minp) maxp = minp + 1.0f;
|
||||
@@ -536,13 +508,14 @@ sensor:
|
||||
id(led_output_set_pct).publish_state(pos_i);
|
||||
}
|
||||
}
|
||||
|
||||
- platform: template
|
||||
id: mosfet_output_pwm_pct
|
||||
name: "${friendly_name} Output PWM (%)"
|
||||
unit_of_measurement: "%"
|
||||
icon: mdi:square-wave
|
||||
accuracy_decimals: 1
|
||||
update_interval: 500ms
|
||||
update_interval: 1s
|
||||
lambda: |-
|
||||
const auto &cv = id(mosfet_leds).current_values;
|
||||
if (!cv.is_on()) return 0.0f;
|
||||
@@ -553,6 +526,7 @@ sensor:
|
||||
if (pwm > 1.0f) pwm = 1.0f;
|
||||
return pwm * 100.0f;
|
||||
|
||||
|
||||
##########################################################################################
|
||||
# OUTPUT COMPONENT
|
||||
# https://esphome.io/components/light/index.html
|
||||
@@ -738,7 +712,7 @@ number:
|
||||
float out_pct = minp + (pos * (maxp - minp) / 100.0f);
|
||||
if (out_pct > maxp) out_pct = maxp;
|
||||
return out_pct / 100.0f;
|
||||
transition_length: 500ms
|
||||
transition_length: 250ms
|
||||
- lambda: |-
|
||||
id(ramp_switch_target_on) = true;
|
||||
float pos = id(led_output_set_pct).state; // 1..100
|
||||
@@ -747,11 +721,7 @@ number:
|
||||
if (maxp <= minp) maxp = minp + 1.0f;
|
||||
float out_pct = minp + (pos * (maxp - minp) / 100.0f);
|
||||
if (out_pct > maxp) out_pct = maxp;
|
||||
id(last_brightness_pct) = out_pct; // persist exact target now
|
||||
if (out_pct > 0.5f) {
|
||||
id(last_nonzero_brightness_pct) = out_pct;
|
||||
id(last_nonzero_tmp) = out_pct;
|
||||
}
|
||||
id(last_brightness_pct) = out_pct; // persist exact target now
|
||||
- delay: 400ms
|
||||
- lambda: 'id(suppress_slider_sync) = false;'
|
||||
|
||||
@@ -791,42 +761,14 @@ number:
|
||||
# Scripts can be executed nearly anywhere in your device configuration with a single call.
|
||||
##########################################################################################
|
||||
script:
|
||||
# Blink pattern while ramping UP: quick double-blink, pause, repeat
|
||||
- id: led_flash_up
|
||||
mode: restart
|
||||
then:
|
||||
- repeat:
|
||||
count: 1000000000 # effectively forever, but cancellable
|
||||
then:
|
||||
- output.turn_on: green_led_out
|
||||
- delay: 100ms
|
||||
- output.turn_off: green_led_out
|
||||
- delay: 100ms
|
||||
- output.turn_on: green_led_out
|
||||
- delay: 100ms
|
||||
- output.turn_off: green_led_out
|
||||
- delay: 400ms
|
||||
# Blink pattern while ramping DOWN: steady slow blink
|
||||
- id: led_flash_down
|
||||
mode: restart
|
||||
then:
|
||||
- while:
|
||||
condition:
|
||||
lambda: 'return true;'
|
||||
then:
|
||||
- output.turn_on: green_led_out
|
||||
- delay: 250ms
|
||||
- output.turn_off: green_led_out
|
||||
- delay: 250ms
|
||||
|
||||
# Script: ramp up from current level. Obey global max.
|
||||
# Script: ramp up from current level. Obey global max. (LED ON while ramping)
|
||||
- id: ramp_on_script
|
||||
mode: restart
|
||||
then:
|
||||
- lambda: 'id(is_ramping) = true;'
|
||||
- script.stop: ramp_off_script
|
||||
- script.stop: led_flash_down
|
||||
- script.execute: led_flash_up
|
||||
- output.turn_on: green_led_out
|
||||
# Ensure we start at at least the floor without a visible "pop".
|
||||
- if:
|
||||
condition:
|
||||
@@ -863,25 +805,22 @@ script:
|
||||
id(last_ramp_ms) = (int) (id(ramp_up_ms) * frac);
|
||||
return (uint32_t) id(last_ramp_ms);
|
||||
- delay: !lambda 'return (uint32_t) id(last_ramp_ms);'
|
||||
- script.stop: led_flash_up
|
||||
- output.turn_off: green_led_out
|
||||
- lambda: |-
|
||||
id(is_ramping) = false;
|
||||
const auto &cv = id(mosfet_leds).current_values;
|
||||
if (cv.is_on()) {
|
||||
float pct = cv.get_brightness() * 100.0f;
|
||||
id(last_brightness_pct) = pct; // persist final level
|
||||
if (pct > 0.5f) id(last_nonzero_brightness_pct) = pct;
|
||||
id(last_brightness_pct) = pct; // persist final level
|
||||
}
|
||||
|
||||
# Script: ramp to a specific target (Restore Brightness path)
|
||||
# Script: ramp to a specific target (Restore Brightness path). (LED ON while ramping)
|
||||
- id: ramp_to_target_script
|
||||
mode: restart
|
||||
then:
|
||||
- lambda: 'id(is_ramping) = true;'
|
||||
- script.stop: ramp_off_script
|
||||
- script.stop: led_flash_down
|
||||
- script.execute: led_flash_up
|
||||
- output.turn_on: green_led_out
|
||||
# Ensure we start at the floor cleanly.
|
||||
- if:
|
||||
condition:
|
||||
@@ -924,18 +863,17 @@ script:
|
||||
id(last_ramp_ms) = (int) (id(ramp_up_ms) * frac);
|
||||
return (uint32_t) id(last_ramp_ms);
|
||||
- delay: !lambda 'return (uint32_t) id(last_ramp_ms);'
|
||||
- script.stop: led_flash_up
|
||||
- output.turn_off: green_led_out
|
||||
- lambda: |-
|
||||
id(is_ramping) = false;
|
||||
const auto &cv = id(mosfet_leds).current_values;
|
||||
if (cv.is_on()) {
|
||||
float pct = cv.get_brightness() * 100.0f;
|
||||
id(last_brightness_pct) = pct; // persist final level
|
||||
if (pct > 0.5f) id(last_nonzero_brightness_pct) = pct;
|
||||
id(last_brightness_pct) = pct; // persist final level
|
||||
}
|
||||
|
||||
# Script: ramp down from current level to floor, then cleanly cut to OFF
|
||||
|
||||
# Script: ramp down from current level to floor, then cleanly cut to OFF. (LED ON while ramping)
|
||||
- id: ramp_off_script
|
||||
mode: restart
|
||||
then:
|
||||
@@ -943,8 +881,7 @@ script:
|
||||
id(is_ramping) = true;
|
||||
id(ramping_for_off) = true;
|
||||
- script.stop: ramp_on_script
|
||||
- script.stop: led_flash_up
|
||||
- script.execute: led_flash_down
|
||||
- output.turn_on: green_led_out
|
||||
- light.turn_on:
|
||||
id: mosfet_leds
|
||||
brightness: !lambda 'return id(min_brightness_pct) / 100.0f;'
|
||||
@@ -965,7 +902,6 @@ script:
|
||||
id: mosfet_leds
|
||||
transition_length: 150ms
|
||||
- delay: 150ms
|
||||
- script.stop: led_flash_down
|
||||
- output.turn_off: green_led_out
|
||||
- lambda: |-
|
||||
id(is_ramping) = false;
|
||||
@@ -1026,3 +962,5 @@ script:
|
||||
- light.turn_off:
|
||||
id: mosfet_leds
|
||||
transition_length: 0s
|
||||
- output.turn_off: green_led_out # make sure LED is off if no ramp
|
||||
|
||||
|
||||
Reference in New Issue
Block a user