Refactor code structure for improved readability and maintainability

This commit is contained in:
CeeWeasel
2026-01-19 14:47:59 -05:00
parent 6550521520
commit 97a0e678c0
84 changed files with 1614 additions and 1177 deletions
@@ -0,0 +1,442 @@
blueprint:
name: Party Lights
author: AntonH
homeassistant:
min_version: 2024.10.0
description: '**Version 3.2**
Lights go to party mode (color loops or fade-in-and-out)
⚠️ **NOTE:** ⚠️
*This automation is triggered by the status of a switch or an input_boolean entity.*
*You can create this input_boolean by going to Settings > Devices & services >
Helpers*
*There you click on ''Create helper and choose ''Toggle''.*
'
source_url: https://gist.github.com/Twanne/fe33ab8466f9a4e94b3f8e21f745a377
domain: automation
input:
party_mode_trigger:
name: Party mode trigger
description: "The trigger you want to use to turn the party mode on.\nThe automation
will keep running until this is turned off.\nSupported entity types:\n -
input_boolean\n - switch\n"
default: []
selector:
entity:
filter:
- domain:
- input_boolean
- switch
reorder: false
multiple: false
target_lights:
name: Target lights
description: Which lights do you want to control?
selector:
entity:
multiple: true
filter:
- domain:
- light
reorder: false
input_sync_lights:
name: Synchronize lights
description: 'If more than 1 target light is selected, choose if they will all
change to the same state or if they each get their own random values.
`️ Light groups will be seen an a single entity.`
'
default: true
selector:
boolean: {}
time_between_changes:
name: Time between changes
description: Change the lights setting after this duration
default:
hours: 0
minutes: 0
seconds: 0
milliseconds: 0
selector:
duration:
enable_millisecond: true
transition_time:
name: Transition time
description: 'The time it takes for the light to transition to the assigned
value when it''s triggered.
`⚠️ This value should not be greater than the time between changes!`
'
default: 0
selector:
number:
min: 0.0
max: 300.0
step: 1.0
unit_of_measurement: s
mode: slider
color_mode:
name: Color mode
description: "Select how the lights need to change\n \n 1. ⬛ **NO COLOR CHANGE:**\n
\ Don't change colors.\n 2. \U0001F500 **RANDOM COLOR MODE:**\n Change all
RGB values randomly.\n 3. \U0001F308 **SATURATED COLOR MODE**\n Random,
but deeply saturated, colors only.\n 4. \U0001F384 **CHRISTMAS COLORS:**\n
\ Change only between Christmas colors.\n 5. \U0001F6A8 **POLICE LIGHTS**\n
\ Change between red and blue.\n `⚠️ Lights will be synchronized!`\n 6.
\U0001F7E5 **REDS ONLY MODE:**\n Change only red value randomly.\n 7. \U0001F7E9
**GREENS ONLY MODE:**\n Change only green value randomly.\n 8. \U0001F7E6
**BLUES ONLY MODE:**\n Change only blue value randomly.\n 9. \U0001F7E6
**TEALS ONLY MODE:**\n Change only teal shades randomly.\n 10. \U0001F338
**PINKS ONLY MODE:**\n Change only pink shades randomly.\n 11. \U0001F7E8
**YELLOWS ONLY MODE:**\n Change only yellow shades randomly.\n"
default: no_color_change
selector:
select:
mode: dropdown
options:
- label: NO COLOR CHANGE
value: no_color_change
- label: RANDOM COLOR MODE
value: random
- label: SATURATED COLOR MODE
value: deep
- label: CHRISTMAS COLORS
value: christmas
- label: POLICE LIGHTS
value: police
- label: REDS ONLY MODE
value: red
- label: GREENS ONLY MODE
value: green
- label: BLUES ONLY MODE
value: blue
- label: TEALS ONLY MODE
value: teal
- label: PINKS ONLY MODE
value: pink
- label: YELLOWS ONLY MODE
value: yellow
multiple: false
custom_value: false
sort: false
brightness_mode:
name: Brightness mode
description: "Select how the lights need to change\n 1. **RANDOM BRIGHTNESS:**\n
\ Change the brightness randomly within a set range\n \n 2. **FIXED BRIGHTNESS:**\n
\ Keep the light at a user defined brightness\n"
default: random
selector:
select:
mode: dropdown
options:
- label: RANDOM BRIGHTNESS
value: random
- label: FIXED BRIGHTNESS
value: fixed
multiple: false
custom_value: false
sort: false
random_brightness_section:
name: Settings for RANDOM BRIGHTNESS
icon: mdi:brightness-auto
collapsed: true
input:
min_brightness_pct:
name: Minimum brightness (RANDOM BRIGHTNESS MODE)
description: Don't set the brightness of the light below this value
default: 0
selector:
number:
min: 0.0
max: 100.0
step: 1.0
mode: slider
unit_of_measurement: '%'
max_brightness_pct:
name: Maximum brightness (RANDOM BRIGHTNESS MODE)
description: Don't set the brightness of the light above this value
default: 100
selector:
number:
min: 0.0
max: 100.0
step: 1.0
mode: slider
unit_of_measurement: '%'
fixed_brightness_section:
name: Settings for FIXED BRIGHTNESS
icon: mdi:brightness-percent
collapsed: true
input:
fixed_brightness_pct:
name: Brightness (FIXED BRIGHTNESS MODE)
description: Keep the light at this percentage (color changes might affect
this somewhat)
default: 0
selector:
number:
min: 0.0
max: 100.0
step: 1.0
mode: slider
unit_of_measurement: '%'
light_effects_section:
name: Light Effects
icon: mdi:creation-outline
collapsed: true
input:
light_effect:
name: Effects (All modes)
description: 'Which light effect do you want to run?
`️ Recommended to set the time between changes long enough for the effects
to loop at least once.`
'
default: ''
selector:
text:
multiple: false
multiline: false
turn_off_settings_section:
name: Turn off settings
icon: mdi:cog-stop-outline
collapsed: true
input:
turn_off_delay:
name: Turn off delay
description: 'The time to wait before the automation is turned off and the
After Party State becomes active.
'
default:
hours: 0
minutes: 0
seconds: 0
selector:
duration: {}
after_party_state:
name: After party state
description: "What state should the lights have when the party mode is turned
off.\n \n 1. **NO CHANGE:**\n Keep the lights in the state they are
at the end of the party.\n 2. **TURN OFF:**\n Turn the lights off.\n
\ 3. **RETURN TO PREVIOUS STATE:**\n Return the lights to the state they
were before the party began.\n 4. **USER DEFINED SCENE:**\n Activate
a scene that determines the state of the lights after the party.\n 5.
**SCENE THEN OFF**\n Set the lights to a specific setting by activating
the user defined scene, then turn them off.\n"
default: return_to_previous
selector:
select:
mode: dropdown
options:
- label: NO CHANGE
value: no_change
- label: LIGHTS OFF
value: lights_off
- label: RETURN TO PREVIOUS STATE
value: return_to_previous
- label: USER DEFINED SCENE
value: user_defined_scene
- label: SCENE THEN OFF
value: scene_then_off
multiple: false
custom_value: false
sort: false
after_party_scene:
name: After party scene
description: 'User defined scene that can be activated after the party mode
is turned off.
'
default: []
selector:
entity:
filter:
- domain:
- scene
reorder: false
multiple: false
mode: restart
variables:
party_mode_trigger: !input party_mode_trigger
target_lights: !input target_lights
time_between_changes: !input time_between_changes
transition_time: !input transition_time
color_mode: !input color_mode
brightness_mode: !input brightness_mode
min_brightness_pct: !input min_brightness_pct
max_brightness_pct: !input max_brightness_pct
fixed_brightness_pct: !input fixed_brightness_pct
light_effect: !input light_effect
after_party_state: !input after_party_state
after_party_scene: !input after_party_scene
turn_off_delay: !input turn_off_delay
input_sync_lights: !input input_sync_lights
sync_lights: '{{ true if color_mode == "police" else input_sync_lights }}
'
triggers:
- trigger: state
entity_id: !input party_mode_trigger
to: 'on'
actions:
- action: scene.create
metadata: {}
data:
scene_id: before_state
snapshot_entities: '{{ target_lights }}'
- repeat:
sequence:
- choose:
- conditions: '{{ sync_lights is true }}'
sequence:
- variables:
brightness_value: "{% if brightness_mode == \"random\" %}\n {{ range(min_brightness_pct,
max_brightness_pct) | random }}\n{% else %}\n {{ fixed_brightness_pct
}}\n{% endif %}\n"
rgb_value: "{% if color_mode == \"random\" %}\n {{ range(256) | random,
range(256) | random, range(256) | random }}\n{% elif color_mode == \"deep\"
%}\n {% set r = range(256) |random %}\n {% set g = range(256) |random
%}\n {% set b = range(256) |random %}\n {# check if all values aren't
too high. This will mute the colors as they will go towards white. #}\n
\ {% if ( r >= 200 and g >= 200 and b >= 200) %}\n {% set rgb_changer
= range(3) | random %}\n \n {% if rgb_changer == 0 %}\n {{
(r - 100), g, b }}\n {% elif rgb_changer == 1 %}\n {{ r, (g
- 100), b }}\n {% elif rgb_changer == 2 %}\n {{ r, g, (b - 100)
}}\n {% endif %} \n \n {# check if all values aren't too close
together. This will mute the colors because they will form a grey color.
#}\n {% elif ( (r - g)|abs <= 100 and (g - b)|abs <= 100 and (b - r)|abs
<= 100 ) %}\n {% set rgb_changer = range(3) | random %}\n {%
if rgb_changer == 0 %}\n {{ (r / 2)|int , g, b }}\n {% elif
rgb_changer == 1 %}\n {{ r, (g / 2)|int, b }}\n {% elif rgb_changer
== 2 %}\n {{ r, g, (b / 2)|int }}\n {% endif %}\n {% else %}\n
\ {{ r, g, b }}\n {% endif %}\n{% elif color_mode == \"christmas\"
%} \n {% macro random_rgb_component(max) %}\n {{ range(256) | random
}}\n {% endmacro %}\n {% macro get_color(color_key) %}\n {% if
color_key == 1 %}\n [{{ random_rgb_component(256) }}, 0, 0]\n {%
elif color_key == 2 %}\n [0, {{ random_rgb_component(256) }}, 0]\n
\ {% elif color_key == 3 %}\n [0, 0, {{ random_rgb_component(256)
}}]\n {% elif color_key == 4 %}\n [255, 255, {{ random_rgb_component(50)
}}]\n {% endif %}\n {% endmacro %}\n {% set color_key = range(1,
5) | random %}\n {% set random_color = get_color(color_key) %}\n {{
random_color }} \n{% elif color_mode == \"police\" %}\n {% if state_attr(
target_lights[0], 'rgb_color') | string == '(255, 0, 0)' %}\n [ 0,
0, 255 ]\n {% else %}\n [ 255, 0, 0 ]\n {% endif %}\n{% elif color_mode
== \"red\" %}\n {{ range(256) | random, 0, 0 }}\n{% elif color_mode
== \"green\" %}\n {{ 0, range(256) | random, 0 }}\n{% elif color_mode
== \"blue\" %}\n {{ 0, 0, range(256) | random }}\n{% elif color_mode
== \"teal\" %}\n {{ range(256) | random, 255, 255 }}\n{% elif color_mode
== \"pink\" %}\n {{ 255, range(256) | random, 255 }}\n{% elif color_mode
== \"yellow\" %}\n {{ 255, 255, range(256) | random }}\n{% else %}\n
\ {{ 255, 255, 255 }}\n{% endif %}\n"
- action: light.turn_on
data: "{% if light_effect == \"\" %}\n {% if color_mode == \"no_color_change\"
%}\n {{ { \"transition\": transition_time, \"brightness_pct\": brightness_value
} }}\n {% else %}\n {{ { \"transition\": transition_time, \"brightness_pct\":
brightness_value, \"rgb_color\": rgb_value } }}\n {% endif %}\n{% else
%}\n {% if color_mode == \"no_color_change\" %}\n {{ { \"transition\":
transition_time, \"brightness_pct\": brightness_value, \"effect\": light_effect
\ } }}\n {% else %}\n {{ { \"transition\": transition_time, \"brightness_pct\":
brightness_value, \"rgb_color\": rgb_value, \"effect\": light_effect }
}}\n {% endif %}\n{% endif %}\n"
target:
entity_id: '{{ target_lights }}'
- conditions: '{{ sync_lights is false }}'
sequence:
- repeat:
for_each: '{{ target_lights }}'
sequence:
- variables:
brightness_value: "{% if brightness_mode == \"random\" %}\n {{ range(min_brightness_pct,
max_brightness_pct) | random }}\n{% else %}\n {{ fixed_brightness_pct
}}\n{% endif %}\n"
rgb_value: "{% if color_mode == \"random\" %}\n {{ range(256) | random,
range(256) | random, range(256) | random }}\n{% elif color_mode
== \"deep\" %}\n {% set r = range(256) |random %}\n {% set g =
range(256) |random %}\n {% set b = range(256) |random %}\n {#
check if all values aren't too high. This will mute the colors as
they will go towards white. #}\n {% if ( r >= 200 and g >= 200
and b >= 200) %}\n {% set rgb_changer = range(3) | random %}\n
\ \n {% if rgb_changer == 0 %}\n {{ (r - 100), g, b }}\n
\ {% elif rgb_changer == 1 %}\n {{ r, (g - 100), b }}\n {%
elif rgb_changer == 2 %}\n {{ r, g, (b - 100) }}\n {% endif
%} \n \n {# check if all values aren't too close together.
This will mute the colors because they will form a grey color. #}\n
\ {% elif ( (r - g)|abs <= 100 and (g - b)|abs <= 100 and (b - r)|abs
<= 100 ) %}\n {% set rgb_changer = range(3) | random %}\n {%
if rgb_changer == 0 %}\n {{ (r / 2)|int , g, b }}\n {% elif
rgb_changer == 1 %}\n {{ r, (g / 2)|int, b }}\n {% elif
rgb_changer == 2 %}\n {{ r, g, (b / 2)|int }}\n {% endif
%}\n {% else %}\n {{ r, g, b }}\n {% endif %}\n{% elif color_mode
== \"christmas\" %} \n {% macro random_rgb_component(max) %}\n
\ {{ range(0, max) | random }}\n {% endmacro %}\n {% macro get_color(color_key)
%}\n {% if color_key == 1 %}\n [{{ random_rgb_component(256)
}}, 0, 0]\n {% elif color_key == 2 %}\n [0, {{ random_rgb_component(256)
}}, 0]\n {% elif color_key == 3 %}\n [0, 0, {{ random_rgb_component(256)
}}]\n {% elif color_key == 4 %}\n [255, 255, {{ random_rgb_component(50)
}}]\n {% endif %}\n {% endmacro %}\n {% set color_key = range(1,
5) | random %}\n {% set random_color = get_color(color_key) %}\n
\ {{ random_color }}\n{% elif color_mode == \"red\" %}\n {{ range(256)
| random, 0, 0 }}\n{% elif color_mode == \"green\" %}\n {{ 0, range(256)
| random, 0 }}\n{% elif color_mode == \"blue\" %}\n {{ 0, 0, range(256)
| random }}\n{% elif color_mode == \"teal\" %}\n {{ range(256)
| random, 255, 255 }}\n{% elif color_mode == \"pink\" %}\n {{ 255,
range(256) | random, 255 }}\n{% elif color_mode == \"yellow\" %}\n
\ {{ 255, 255, range(256) | random }}\n{% else %}\n {{ 255, 255,
255 }}\n{% endif %}\n"
- action: light.turn_on
data: "{% if light_effect == \"\" %}\n {% if color_mode == \"no_color_change\"
%}\n {{ { \"transition\": transition_time, \"brightness_pct\":
brightness_value } }}\n {% else %}\n {{ { \"transition\": transition_time,
\"brightness_pct\": brightness_value, \"rgb_color\": rgb_value } }}\n
\ {% endif %}\n{% else %}\n {% if color_mode == \"no_color_change\"
%}\n {{ { \"transition\": transition_time, \"brightness_pct\":
brightness_value, \"effect\": light_effect } }}\n {% else %}\n {{
{ \"transition\": transition_time, \"brightness_pct\": brightness_value,
\"rgb_color\": rgb_value, \"effect\": light_effect } }}\n {% endif
%}\n{% endif %}\n"
target:
entity_id: '{{ repeat.item }}'
- delay: !input time_between_changes
until:
- condition: state
entity_id: !input party_mode_trigger
state: 'off'
- delay: !input turn_off_delay
- choose:
- conditions: '{{ "lights_off" in after_party_state }}'
sequence:
- action: light.turn_off
target:
entity_id: '{{ target_lights }}'
- conditions: '{{ "return_to_previous" in after_party_state }}'
sequence:
- action: scene.turn_on
metadata: {}
target:
entity_id: scene.before_state
- conditions: '{{ "user_defined_scene" in after_party_state }}'
sequence:
- action: scene.turn_on
metadata: {}
target:
entity_id: '{{ after_party_scene }}'
- conditions: '{{ "scene_then_off" in after_party_state }}'
sequence:
- action: scene.turn_on
metadata: {}
target:
entity_id: '{{ after_party_scene }}'
- action: light.turn_off
target:
entity_id: '{{ target_lights }}'