Just sharing this since I couldn’t find anything similar so wrote my own!
Little script blueprint you can then run in a repeat loop within an automation to randomly change xy colour by small values:
blueprint:
name: Fading Hue/Saturation Changes
description: Gradually change light colour
domain: script
input:
entities:
name: Entities
description: "Which entities to control. Input as YAML list"
selector:
object:
max_value_hue:
name: Max Hue Value
description: Max Hue Value
default: 360.0
selector:
number:
min: 0.0
max: 360.0
step: 0.001
mode: box
min_value_hue:
name: Min Hue Value
description: Min Hue Value
default: 0.001
selector:
number:
min: 0.0
max: 360.0
step: 0.001
mode: box
max_value_sat:
name: Max Saturation
description: Max Saturation
default: 100.0
selector:
number:
min: 0.0
max: 100.0
step: 0.001
mode: box
min_value_sat:
name: Min Saturation
description: Min Saturation
default: 28
selector:
number:
min: 0.0
max: 100.0
step: 0.001
mode: box
step_value_hue:
name: Hue Step value
description: Step value to change each time - is divided by 1000
default: 30
selector:
number:
min: 0.0
max: 1000
step: 1
mode: box
step_value_sat:
name: Saturation Step value
description: Step value to change each time - is divided by 1000
default: 30
selector:
number:
min: 0.0
max: 1000
step: 1
mode: box
use_negatives:
name: Use negatives
description: Use negative value changes
default: true
selector:
boolean:
default_value_hue:
name: Default Hue Value
description: Default Starting Hue Value
default: 240
selector:
number:
min: 0.0
max: 360
step: 0.001
mode: box
default_value_sat:
name: Default Saturation
description: Default Starting Saturation
default: 69
selector:
number:
min: 0.0
max: 100
step: 0.001
mode: box
sequence:
- service: light.turn_on
data:
entity_id: '{{ entities }}'
hs_color: >-
{% set data = namespace(hs_col=[]) %}
{% if state_attr(entities|first, 'hs_color') == None %}
{{ default_colour }}
{% else %}
{% for hs in ['hue', 'sat'] %}
{% if hs == 'hue' %}
{% set step_value = step_value_hue %}
{% else %}
{% set step_value = step_value_sat %}
{% endif %}
{% if use_negatives %}
{% set rand_add = ([(range(0, step_value) | random), 0-(range(0, step_value) | random)] | random) / 1000 %}
{% else %}
{% set rand_add = (range(0, step_value) | random) / 1000 %}
{% endif %}
{% set cur_hs = state_attr(entities|first, 'hs_color') | list %}
{% if hs == 'hue' %}
{% set val = cur_hs[0] %}
{% set max_value_hs = max_value_hue %}
{% set min_value_hs = min_value_hue %}
{% set default_value_hs = default_value_hue %}
{% else %}
{% set val = cur_hs[1] %}
{% set max_value_hs = max_value_sat %}
{% set min_value_hs = min_value_sat %}
{% set default_value_hs = default_value_sat %}
{% endif %}
{% if float(val) + rand_add <= max_value_hs and float(val) + rand_add > min_value_hs %}
{% set new_val = float(val) + rand_add %}
{% else %}
{% set new_val = default_value_hs %}
{% endif %}
{% set data.hs_col = data.hs_col + [new_val] %}
{% endfor %}
{% endif %}
{{ data.hs_col or default_colour or [0, 0] }}
# brightness_pct: 100
variables:
entities: !input entities
max_value_hue: !input max_value_hue
min_value_hue: !input min_value_hue
max_value_sat: !input max_value_sat
min_value_sat: !input min_value_sat
step_value_hue: !input step_value_hue
step_value_sat: !input step_value_sat
use_negatives: !input use_negatives
default_value_hue: !input default_value_hue
default_value_sat: !input default_value_sat
default_colour: [!input default_value_hue, !input default_value_sat]
mode: single
Just ask if you want me to explain anything for your own uses