|
|
|
@@ -83,12 +83,12 @@ substitutions:
|
|
|
|
|
mqtt_local_device_command_OFF: "OFF"
|
|
|
|
|
|
|
|
|
|
# Device Specific Settings
|
|
|
|
|
log_level: "INFO" # Define logging level: NONE, ERROR, WARN, INFO, DEBUG (Default), VERBOSE, VERY_VERBOSE
|
|
|
|
|
update_interval: "20s" # update time for for general sensors etc
|
|
|
|
|
led_gamma: "1.2" # Gamma from 1.2 - 3 is sensible to normalise the lED fading vs PWM
|
|
|
|
|
minimum_led_output: "1" # % If at this value or below, we'll switch it completely off
|
|
|
|
|
maximum_led_output: "90" # % Maximum output, it is sometimes nice to limit the output for longevity or aesthetic
|
|
|
|
|
|
|
|
|
|
log_level: "NONE" # Define logging level: NONE, ERROR, WARN, INFO, DEBUG (Default), VERBOSE, VERY_VERBOSE
|
|
|
|
|
update_interval: "20s" # update time for for general sensors etc
|
|
|
|
|
led_gamma: "1.2" # Gamma from 1.2 - 3 is sensible to normalise the lED fading vs PWM
|
|
|
|
|
minimum_led_output: "1" # % If at this value or below, we'll switch it completely off
|
|
|
|
|
maximum_led_output: "90" # % Maximum output, it is sometimes nice to limit the output for longevity or aesthetic
|
|
|
|
|
max_on_default_hours: "6" # The max the LEDs will be on for, in case they get left on. 0 = no automatic turn-off
|
|
|
|
|
|
|
|
|
|
##########################################################################################
|
|
|
|
|
# PACKAGES: Included Common Packages
|
|
|
|
@@ -102,7 +102,8 @@ packages:
|
|
|
|
|
local_static_ip_address: "${static_ip_address}"
|
|
|
|
|
local_ota_pass: "${ota_pass}"
|
|
|
|
|
common_api: !include
|
|
|
|
|
file: common/api_common.yaml
|
|
|
|
|
#file: common/api_common.yaml
|
|
|
|
|
file: common/api_common_noencryption.yaml
|
|
|
|
|
vars:
|
|
|
|
|
local_api_key: "${api_key}"
|
|
|
|
|
#common_webportal: !include
|
|
|
|
@@ -114,7 +115,8 @@ packages:
|
|
|
|
|
#common_sntp: !include
|
|
|
|
|
# file: common/sntp_common.yaml
|
|
|
|
|
common_general_sensors: !include
|
|
|
|
|
file: common/sensors_common.yaml
|
|
|
|
|
#file: common/sensors_common.yaml
|
|
|
|
|
file: common/sensors_common_lite.yaml
|
|
|
|
|
vars:
|
|
|
|
|
local_friendly_name: "${friendly_name}"
|
|
|
|
|
local_update_interval: "${update_interval}"
|
|
|
|
@@ -190,6 +192,16 @@ esphome:
|
|
|
|
|
id: mosfet_leds
|
|
|
|
|
transition_length: 0s
|
|
|
|
|
- lambda: 'id(ramp_switch_target_on) = false;'
|
|
|
|
|
platformio_options:
|
|
|
|
|
build_unflags:
|
|
|
|
|
- -flto
|
|
|
|
|
build_flags:
|
|
|
|
|
- -fno-lto
|
|
|
|
|
- -Wl,--gc-sections
|
|
|
|
|
- -ffunction-sections
|
|
|
|
|
- -fdata-sections
|
|
|
|
|
- -DNDEBUG
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
##########################################################################################
|
|
|
|
|
# ESP PLATFORM AND FRAMEWORK
|
|
|
|
@@ -221,6 +233,11 @@ globals:
|
|
|
|
|
type: int
|
|
|
|
|
restore_value: false
|
|
|
|
|
initial_value: "${maximum_led_output}" # hard cap; never exceed this
|
|
|
|
|
# The maximum time the lights will stay on, in hours. Just in case they are left on. 0 = forever
|
|
|
|
|
- id: max_on_hours
|
|
|
|
|
type: int
|
|
|
|
|
restore_value: true
|
|
|
|
|
initial_value: '${max_on_default_hours}'
|
|
|
|
|
# Default Fading Up Time (Selectable and will be retained)
|
|
|
|
|
- id: ramp_up_ms # fade-in when turned ON
|
|
|
|
|
type: int
|
|
|
|
@@ -236,7 +253,7 @@ globals:
|
|
|
|
|
type: int
|
|
|
|
|
restore_value: true
|
|
|
|
|
initial_value: '0' # default = Fade Up to Full (so can be deployed with no other setup)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# Determine last fade direction.
|
|
|
|
|
# true when you asked the light to end up ON (Ramp Up)
|
|
|
|
|
# false when you asked the light to end up OFF (Ramp Down)
|
|
|
|
@@ -448,7 +465,7 @@ sensor:
|
|
|
|
|
unit_of_measurement: "%"
|
|
|
|
|
icon: mdi:percent
|
|
|
|
|
accuracy_decimals: 0
|
|
|
|
|
update_interval: 100ms # consider 200ms if you want fewer updates
|
|
|
|
|
update_interval: 250ms # 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;
|
|
|
|
@@ -480,18 +497,17 @@ sensor:
|
|
|
|
|
unit_of_measurement: "%"
|
|
|
|
|
icon: mdi:square-wave
|
|
|
|
|
accuracy_decimals: 1
|
|
|
|
|
update_interval: 100ms
|
|
|
|
|
update_interval: 250ms
|
|
|
|
|
lambda: |-
|
|
|
|
|
const auto &cv = id(mosfet_leds).current_values;
|
|
|
|
|
if (!cv.is_on()) return 0.0f;
|
|
|
|
|
const float lin = cv.get_brightness(); // 0..1 (linear)
|
|
|
|
|
const float gamma = ${led_gamma}; // from substitutions
|
|
|
|
|
float pwm = powf(lin, gamma); // approximate PWM duty after gamma
|
|
|
|
|
const float lin = cv.get_brightness(); // 0..1 (linear brightness)
|
|
|
|
|
const float gamma = atof("${led_gamma}"); // parse substitution string → float
|
|
|
|
|
float pwm = powf(lin, gamma); // approx PWM duty after gamma
|
|
|
|
|
if (pwm < 0.0f) pwm = 0.0f;
|
|
|
|
|
if (pwm > 1.0f) pwm = 1.0f;
|
|
|
|
|
return pwm * 100.0f;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
##########################################################################################
|
|
|
|
|
# OUTPUT COMPONENT
|
|
|
|
|
# https://esphome.io/components/light/index.html
|
|
|
|
@@ -503,7 +519,7 @@ output:
|
|
|
|
|
- platform: esp8266_pwm
|
|
|
|
|
id: mosfet_pwm
|
|
|
|
|
pin: GPIO4
|
|
|
|
|
frequency: 2000 Hz # high frequency to avoid audible/visible artifacts
|
|
|
|
|
frequency: 500 Hz # high frequency to avoid audible/visible artifacts
|
|
|
|
|
- platform: gpio
|
|
|
|
|
id: green_led_out # Green LED
|
|
|
|
|
pin:
|
|
|
|
@@ -529,12 +545,19 @@ light:
|
|
|
|
|
payload: "${mqtt_local_device_command_ON}"
|
|
|
|
|
retain: true
|
|
|
|
|
- lambda: 'id(ramp_switch_target_on) = true;'
|
|
|
|
|
- script.stop: max_on_watchdog
|
|
|
|
|
- if:
|
|
|
|
|
condition:
|
|
|
|
|
lambda: 'return id(max_on_hours) > 0;'
|
|
|
|
|
then:
|
|
|
|
|
- script.execute: max_on_watchdog
|
|
|
|
|
on_turn_off:
|
|
|
|
|
- mqtt.publish:
|
|
|
|
|
topic: "${mqtt_local_status_topic}/light/state"
|
|
|
|
|
payload: "${mqtt_local_device_command_OFF}"
|
|
|
|
|
retain: true
|
|
|
|
|
- lambda: 'id(ramp_switch_target_on) = false;'
|
|
|
|
|
- script.stop: max_on_watchdog
|
|
|
|
|
on_state:
|
|
|
|
|
- lambda: |-
|
|
|
|
|
const float cap = id(max_brightness_pct) / 100.0f;
|
|
|
|
@@ -630,7 +653,7 @@ number:
|
|
|
|
|
- delay: 400ms
|
|
|
|
|
- lambda: 'id(suppress_slider_sync) = false;'
|
|
|
|
|
else:
|
|
|
|
|
# Map 1..100 → [min..max] and set ON
|
|
|
|
|
# Map 1..100 - [min..max] and set ON
|
|
|
|
|
- lambda: |-
|
|
|
|
|
id(suppress_slider_sync) = true;
|
|
|
|
|
float pos = x; // 0..100
|
|
|
|
@@ -654,6 +677,36 @@ number:
|
|
|
|
|
- delay: 400ms
|
|
|
|
|
- lambda: 'id(suppress_slider_sync) = false;'
|
|
|
|
|
|
|
|
|
|
- platform: template
|
|
|
|
|
id: cfg_max_on_hours
|
|
|
|
|
name: "${friendly_name} Max On (h)"
|
|
|
|
|
entity_category: config
|
|
|
|
|
unit_of_measurement: h
|
|
|
|
|
icon: mdi:timer-cog
|
|
|
|
|
mode: slider
|
|
|
|
|
min_value: 0
|
|
|
|
|
max_value: 48
|
|
|
|
|
step: 1
|
|
|
|
|
lambda: |-
|
|
|
|
|
return (float) id(max_on_hours);
|
|
|
|
|
set_action:
|
|
|
|
|
- lambda: |-
|
|
|
|
|
int hrs = (int) x;
|
|
|
|
|
if (hrs < 0) hrs = 0;
|
|
|
|
|
if (hrs > 48) hrs = 48;
|
|
|
|
|
id(max_on_hours) = hrs;
|
|
|
|
|
id(cfg_max_on_hours).publish_state((float) hrs);
|
|
|
|
|
- if:
|
|
|
|
|
condition:
|
|
|
|
|
lambda: 'return id(mosfet_leds).current_values.is_on();'
|
|
|
|
|
then:
|
|
|
|
|
- script.stop: max_on_watchdog
|
|
|
|
|
- if:
|
|
|
|
|
condition:
|
|
|
|
|
lambda: 'return id(max_on_hours) > 0;'
|
|
|
|
|
then:
|
|
|
|
|
- script.execute: max_on_watchdog
|
|
|
|
|
|
|
|
|
|
##########################################################################################
|
|
|
|
|
# SCRIPT COMPONENT
|
|
|
|
|
# https://esphome.io/components/script.html
|
|
|
|
@@ -757,4 +810,21 @@ script:
|
|
|
|
|
auto call = id(mosfet_leds).make_call();
|
|
|
|
|
call.set_state(false);
|
|
|
|
|
call.set_brightness(id(max_brightness_pct) / 100.0f);
|
|
|
|
|
call.perform();
|
|
|
|
|
call.perform();
|
|
|
|
|
- id: max_on_watchdog
|
|
|
|
|
mode: restart
|
|
|
|
|
then:
|
|
|
|
|
- if:
|
|
|
|
|
condition:
|
|
|
|
|
lambda: 'return id(max_on_hours) > 0;'
|
|
|
|
|
then:
|
|
|
|
|
- delay: !lambda 'return (uint32_t) (id(max_on_hours) * 3600000UL);'
|
|
|
|
|
- if:
|
|
|
|
|
condition:
|
|
|
|
|
lambda: 'return id(mosfet_leds).current_values.is_on();'
|
|
|
|
|
then:
|
|
|
|
|
- lambda: |-
|
|
|
|
|
id(ramp_switch_target_on) = false;
|
|
|
|
|
id(mosfet_ramp_switch).publish_state(false);
|
|
|
|
|
- script.stop: ramp_on_script
|
|
|
|
|
- script.execute: ramp_off_script
|
|
|
|
|