diff --git a/services/lampBehaviour.yaml b/services/lampBehaviour.yaml index 71d1b49..4e4fa83 100644 --- a/services/lampBehaviour.yaml +++ b/services/lampBehaviour.yaml @@ -26,6 +26,7 @@ globals: type: float initial_value: "0.0" + # This script updates the front panel illumination. script: - id: update_front_panel @@ -57,6 +58,55 @@ script: - front_panel.turn_on_leds: [ POWER ] - front_panel.update_leds: + - id: apply_night_light_calibration + mode: restart + then: + - lambda: |- + if (isnan(id(my_night_light_tint).state) || + isnan(id(my_night_light_temperature).state) || + isnan(id(my_night_light_level).state)) { + return; + } + + const float tint = id(my_night_light_tint).state; + const float temperature = id(my_night_light_temperature).state; + const float level = id(my_night_light_level).state; + + const float base_red_drive = 1.0f - ${night_light_calibration_red_base}f; + const float base_green_drive = 1.0f - ${night_light_calibration_green_base}f; + const float base_blue_drive = 1.0f - ${night_light_calibration_blue_base}f; + + auto approx_exp = [](float x) -> float { + return 1.0f + x + 0.5f * x * x; + }; + + // Work in drive space, where larger values mean a brighter channel. + // Quadratic gain approximation keeps tint and temperature perceptible + // without pulling in runtime exponential math. + const float level_gain = approx_exp(level * 0.027f); + const float temperature_amount = temperature * 0.027f; + const float tint_amount = tint * 0.035f; + + const float red_drive = base_red_drive * level_gain * + approx_exp(temperature_amount * 0.5f) * + approx_exp(tint_amount * 0.5f); + const float green_drive = base_green_drive * level_gain * + approx_exp(temperature_amount * 0.25f) * + approx_exp(-tint_amount); + const float blue_drive = base_blue_drive * level_gain * + approx_exp(-temperature_amount * 0.75f) * + approx_exp(tint_amount * 0.5f); + + const float red = clamp(1.0f - red_drive, + ${night_light_calibration_min}f, ${night_light_calibration_max}f); + const float green = clamp(1.0f - green_drive, + ${night_light_calibration_min}f, ${night_light_calibration_max}f); + const float blue = clamp(1.0f - blue_drive, + ${night_light_calibration_min}f, ${night_light_calibration_max}f); + + id(my_light).set_night_light_color_temperature_calibration(red, green, blue); + + # This component controls the LED lights of the lamp. light: - platform: xiaomi_bslamp2 @@ -196,61 +246,10 @@ substitutions: night_light_calibration_min: "0.920" night_light_calibration_max: "0.980" -esphome: - on_boot: - - priority: 600 - then: - - script.execute: apply_night_light_calibration -script: - - id: apply_night_light_calibration - mode: restart - then: - - lambda: |- - if (isnan(id(my_night_light_tint).state) || - isnan(id(my_night_light_temperature).state) || - isnan(id(my_night_light_level).state)) { - return; - } - const float tint = id(my_night_light_tint).state; - const float temperature = id(my_night_light_temperature).state; - const float level = id(my_night_light_level).state; - - const float base_red_drive = 1.0f - ${night_light_calibration_red_base}f; - const float base_green_drive = 1.0f - ${night_light_calibration_green_base}f; - const float base_blue_drive = 1.0f - ${night_light_calibration_blue_base}f; - - auto approx_exp = [](float x) -> float { - return 1.0f + x + 0.5f * x * x; - }; - - // Work in drive space, where larger values mean a brighter channel. - // Quadratic gain approximation keeps tint and temperature perceptible - // without pulling in runtime exponential math. - const float level_gain = approx_exp(level * 0.027f); - const float temperature_amount = temperature * 0.027f; - const float tint_amount = tint * 0.035f; - - const float red_drive = base_red_drive * level_gain * - approx_exp(temperature_amount * 0.5f) * - approx_exp(tint_amount * 0.5f); - const float green_drive = base_green_drive * level_gain * - approx_exp(temperature_amount * 0.25f) * - approx_exp(-tint_amount); - const float blue_drive = base_blue_drive * level_gain * - approx_exp(-temperature_amount * 0.75f) * - approx_exp(tint_amount * 0.5f); - - const float red = clamp(1.0f - red_drive, - ${night_light_calibration_min}f, ${night_light_calibration_max}f); - const float green = clamp(1.0f - green_drive, - ${night_light_calibration_min}f, ${night_light_calibration_max}f); - const float blue = clamp(1.0f - blue_drive, - ${night_light_calibration_min}f, ${night_light_calibration_max}f); - - id(my_light).set_night_light_color_temperature_calibration(red, green, blue); + number: - platform: template id: my_night_light_tint