diff --git a/README.md b/README.md new file mode 100644 index 0000000..b988208 --- /dev/null +++ b/README.md @@ -0,0 +1,28 @@ +I wanted to try the sunrise effect for waking up in the morning and found the [blueprint](https://community.home-assistant.io/t/wake-up-light-alarm-with-sunrise-effect/255193/145) that would do this for me. However, this didn't work and was overly difficult to troubleshoot. It triggers every minute, and as I used to be a Systems Adminitrator, this unnecessary use of resources also bugged me. If you didn't catch the errors in the automation with in the number of available traces, it was gone. If you did manage to catch the trace, it was so convoluted that it was nearly impossible to troubleshoot unless you are intimately aware of the execution steps. Not to mention the issues trying to trigger it with a date/time helper other then the the one integrated with the HA phone app. + +I created my own script and automation to bypass the frustations above. It is not nearly as full featured as the blueprint but it is highly configureable. Basically it contains 2 components. The first component is a script that can be executed many times in series to change the rates of the 2 main settings, color temperature in kelvin and brightness. By running it many times in series you get get a more parabolic effect. I added this feature because I could visually detect changes in brightness more at lower values. Below is an example of this. You can see the points of which the values change. + +![image|690x196](upload://MHf7C5rNaVUQZPrWWkcCHY68Um.png) + +The second component is an blueprint that executes the script 3 times in series with different values for each execution. + +## Detailed Explaination of Script +The script expects to be kicked off with parameters defined. For the script to work, the target light needs to be and set to starting Kelvin values. The starting brightnes is always 1%. The blueprint handles the inital turning on of the light. The kelvin value of the light will be used as the starting value. + +![image|690x456](upload://7bOOnbkscen4a6DBca9HNMoflN3.png) + +If you turn off the light at any point while the script is running, the script and blueprint will end. + +The script also allows for defining how long to take to get from start to finish values and how many steps per minute to take to get there. The script will also turn off the light after the 'Light Timeout' period. Setting this value to 0 will disable the timeout, and this is how you can chain executions of the script together to get the desired parabolic curve effect. + +## Detailed Explaination of Bluebrint + +The bluebrint is much simpler. Execute the script 3 to get the desired parabolic curve. All executions of the script (except for the last one) have the 'Light Timeout' set to 0 so that the script will continue from current values. It also checks light is off (for all executions but the first one) so that if you turn the light off, the subsequent executions of the script in the currently running automation will not turn it back on. + +When setting up start time for the trigger you will need to take into account when you want it to finish. In my example below I want it to finish by 7:00 am, so I do the math backwards and start it at 6:35. The total time is solved by adding up all the 'Alarm Length' fields of all executions of the script. + +In my automation I'm using the Workday Integration and its binary sensor to only execute on days I have configured in that integration. + +## Installation +1. Copy and paste the script as is into a new script on your system when editing in YAML mode. +1. Import the blueprint \ No newline at end of file diff --git a/parabolic_alarm.yaml b/parabolic_alarm.yaml index 2a660f3..925729f 100644 --- a/parabolic_alarm.yaml +++ b/parabolic_alarm.yaml @@ -12,21 +12,21 @@ blueprint: - domain: input_datetime workday_sensor: name: Workday Sensor - description: Binary Sensor for determining it it should run. Typically from Workday Integratoin + description: Binary Sensor for determining whether it should run. Typically from Workday Integration selector: entity: filter: - domain: binary_sensor alarm_script: name: Script to trigger - description: Script to trigger + description: Light Alarm Script selector: entity: filter: - domain: script target_light: name: Lights - description: The light(s) with Mireds + description: The light(s) with kelvin selector: entity: filter: @@ -48,21 +48,24 @@ blueprint: min: 1 max: 60 - min_mireds_1: - description: Minimum mireds value (coldest) for 1st run + start_kelvin_temp: + description: Start Kelvin value (warm) for 1st run selector: color_temp: - default: 375 - name: Min Mireds 1 - max_mireds_1: + unit: kelvin + default: 2500 + name: Starting Kelvin + target_kelvin_1: description: >- - Maximum mireds value (warmest) for 1st run + Target Kelvin value (cold) for the end of the first run selector: color_temp: - default: 400 - name: Max Mireds 1 + unit: kelvin + default: 3000 + name: Target Kelvin 1 max_brightness_1: name: Maximum Brightness 1 + description: Finish value for first run selector: number: min: 1 @@ -78,21 +81,17 @@ blueprint: max: 60 default: 10 - min_mireds_2: - description: Minimum mireds value (coldest) for 1st run - selector: - color_temp: - default: 300 - name: Min Mireds 1 - max_mireds_2: + target_kelvin_2: description: >- - Maximum mireds value (warmest) for 1st run + Target Kelvin value (cold) for second run selector: color_temp: - default: 400 - name: Max Mireds 1 + unit: kelvin + default: 4000 + name: Target Kelvin 2 max_brightness_2: name: Maximum Brightness 1 + description: Finish value for second run selector: number: min: 1 @@ -108,21 +107,17 @@ blueprint: max: 60 default: 10 - min_mireds_3: - description: Minimum mireds value (coldest) for 1st run - selector: - color_temp: - default: 160 - name: Min Mireds 1 - max_mireds_3: + target_kelvin_3: description: >- - Maximum mireds value (warmest) for 1st run + Target Kelvin value (cold) for third run selector: color_temp: - default: 400 - name: Max Mireds 1 + unit: kelvin + default: 6500 + name: Target Kelvin 3 max_brightness_3: name: Maximum Brightness 1 + description: Finish value for third and final run selector: number: min: 1 @@ -148,24 +143,32 @@ condition: state: "on" action: - - service: !input alarm_script + - action: light.turn_on data: - min_mireds: !input min_mireds_1 - max_mireds_selector: !input max_mireds_1 + color_temp_kelvin: !input start_kelvin_temp + brightness_pct: 1 + entity_id: !input target_light + - delay: + seconds: 5 + - action: !input alarm_script + data: + target_kelvin: !input target_kelvin_1 + start_kelvin: !input start_kelvin_temp max_brightness_pct: !input max_brightness_1 alarm_length: !input alarm_length_1 steps_per_minute: !input steps_per_minute light_timeout: 0 target_light: !input target_light + - if: - condition: state state: "on" entity_id: !input target_light then: - - service: !input alarm_script + - action: !input alarm_script data: - min_mireds: !input min_mireds_2 - max_mireds_selector: !input max_mireds_2 + target_kelvin: !input target_kelvin_2 + start_kelvin: !input target_kelvin_1 max_brightness_pct: !input max_brightness_2 alarm_length: !input alarm_length_2 steps_per_minute: !input steps_per_minute @@ -176,10 +179,10 @@ action: state: "on" entity_id: !input target_light then: - - service: !input alarm_script + - action: !input alarm_script data: - min_mireds: !input min_mireds_3 - max_mireds_selector: !input max_mireds_3 + target_kelvin: !input target_kelvin_3 + start_kelvin: !input target_kelvin_2 max_brightness_pct: !input max_brightness_3 alarm_length: !input alarm_length_3 steps_per_minute: !input steps_per_minute diff --git a/parabolic_alarm_script.yaml b/parabolic_alarm_script.yaml new file mode 100644 index 0000000..ef214dd --- /dev/null +++ b/parabolic_alarm_script.yaml @@ -0,0 +1,145 @@ +alias: Lamp Wake Up +sequence: + - repeat: + until: + - condition: or + conditions: + - condition: template + value_template: "{{ is_state(target_light, 'off') }}" + - condition: template + value_template: "{{ state_attr(target_light, 'brightness') >= max_brightness }}" + - condition: template + value_template: >- + {{ state_attr(target_light, 'color_temp_kelvin') >= + target_kelvin }} + - condition: template + value_template: >- + {{ (((as_timestamp(now()) - start_time) / individual_step) | + round(0, "ceil")) > steps }} + sequence: + - variables: + steps_to_now: |- + {{ ((as_timestamp(now()) - start_time) / individual_step) | + round(0, "ceil") }} + brightness: >- + {{ min_brightness + (bright_step * steps_to_now) | round(0, + 'ceil') }} + kelvin: "{{ start_kelvin + (kelvin_step * steps_to_now) }}" + - delay: + seconds: "{{ individual_step }}" + - if: + - condition: template + value_template: "{{ is_state(target_light, 'on') }}" + then: + - data: + brightness: "{{ brightness }}" + color_temp_kelvin: "{{ kelvin }}" + transition: "{{ individual_step - 1 }}" + target: + entity_id: "{{ target_light }}" + action: light.turn_on + - if: + - condition: and + conditions: + - condition: template + value_template: "{{ light_timeout != 0 }}" + - condition: template + value_template: "{{ is_state(target_light, 'on') }}" + then: + - delay: + minutes: "{{ light_timeout }}" + - data: {} + target: + entity_id: "{{ target_light }}" + action: light.turn_off +description: Turn on lamps brighter based on wake time +fields: + target_kelvin: + description: Coldest Kelvin value. This is the end value - most white + selector: + color_temp: + unit: kelvin + required: true + default: 6500 + name: Coldest Kelvin + example: 6500 + start_kelvin: + description: >- + This is the start value. If the light is on the current value from the + state of the light will be used and this will be ignored. + example: 2500 + selector: + color_temp: + unit: kelvin + min: 2500 + max: 6500 + default: 6500 + required: true + name: Warmest Kelvin + max_brightness_pct: + description: Maximum brightness in percent to reach by the end of the script + example: 80 + selector: + number: + min: 1 + max: 100 + default: 80 + required: true + name: Max brightness + alarm_length: + description: >- + This is the start to finish time. Take this into account when setting up + the automation this script is called by. + example: 10 + selector: + number: + min: 1 + max: 60 + default: 10 + required: true + name: Alarm Length + steps_per_minute: + description: How many steps per minute + example: 4 + selector: + number: + min: 1 + max: 12 + default: 12 + name: Steps Per minute + required: true + target_light: + description: A single light or group + example: light.master_lamp + selector: + entity: + filter: + domain: light + name: Target Light + required: true + light_timeout: + description: >- + Minutes to delay after Max Brightness has been reached to turn the light + back off. Value of 0 disables the timeout + example: 5 + selector: + number: + min: 0 + max: 60 + default: 5 + name: Light Timeout + required: true +variables: + steps: "{{ alarm_length * steps_per_minute }}" + min_brightness: |- + {% if states(target_light) == 'off' %} + 3 + {% else %} + {{ state_attr(target_light, 'brightness') }} + {% endif %} + max_brightness: "{{ max_brightness_pct * 2.55 }}" + kelvin_step: "{{ (target_kelvin - start_kelvin) / steps }}" + bright_step: "{{ (max_brightness - min_brightness) / steps }}" + start_time: "{{ as_timestamp(now()) }}" + individual_step: "{{ 60 / steps_per_minute }}" +mode: parallel