Adaptive Lighting is working well on a number of lights I’m using, but for some WLED strips, I’m finding that the manual control kicks in unexpectedly and prevents further updates. The setup on these strips is a bit complex, but enacts the following flow:
- The lights configured in Adaptive Lighting are template lights.
- These template lights run a script for on/off/set level/set temperature commands.
- The script fires an event to send the necessary info to Node Red.
- Node Red takes the temperature, and derives two RGB values with a slight offset either side of the set temperature.
- Node Red formats the two RGB values into a JSON request direct to the WLED strip to apply the “Lake” effect with the primary and tertiary colours (the secondary colour is the background, so always remains black)
I know this is very convoluted, but it was the only way I found that could support adaptive lighting in conjunction with multiple colours being sent to a WLED effect - just using the native integration only allows a single colour/temperature, or a preset palette (which won’t work unless you create hundreds of palettes for each temp adaptive lighting might send).
The Home Assistant side of things is set up with the following YAML:
light:
- platform: template
lights:
toms_bedhead_blob:
value_template: >
{% set state = states('light.toms_bedhead') == 'on' %}
{% set effect = state_attr('light.toms_bedhead','effect') == 'Lake' %}
{% if state and effect %}
on
{% else %}
off
{% endif %}
level_template: "{{ state_attr('light.toms_bedhead','brightness') }}"
temperature_template: "{{ states('input_number.toms_bedhead_temperature') }}"
turn_on:
service: script.wled_blob
data:
command: "turn_on"
color_temp: "{{ color_temp | default( states('input_number.toms_bedhead_temperature') ) }}"
brightness: "{{ brightness | default( state_attr('light.toms_bedhead','brightness') ) }}"
ip_address: "192.168.0.86"
turn_off:
service: script.wled_blob
data:
command: "turn_off"
ip_address: "192.168.0.86"
set_level:
service: script.wled_blob
data:
command: "set_level"
brightness: "{{ brightness }}"
ip_address: "192.168.0.86"
set_temperature:
- service: script.wled_blob
data:
command: "set_temperature"
color_temp: "{{ color_temp }}"
brightness: "{{ brightness }}"
ip_address: "192.168.0.86"
- service: input_number.set_value
target:
entity_id: input_number.toms_bedhead_temperature
data:
value: "{{ color_temp }}"
input_number:
toms_bedhead_temperature:
name: Toms Bedhead Temperature
min: 153
max: 500
script:
wled_blob:
alias: WLED Blob
mode: parallel
sequence:
- event: node_red.wled_blob
event_data:
command: "{{ command }}"
color_temp: "{{ color_temp | default( states('input_number.toms_bedhead_temperature') ) }}"
brightness: "{{ brightness | default( state_attr('light.toms_bedhead','brightness') ) }}"
ip_address: "{{ ip_address }}"
adaptive_lighting:
- name: Toms Bedhead Blob
lights:
- light.toms_bedhead_blob
prefer_rgb_color: false
separate_turn_on_commands: false
interval: 5
transition: 1
sunrise_time: '08:00:00'
sunset_time: '19:00:00'
min_brightness: 25
max_brightness: 100
The Node Red flow is as follows:
[{"id":"f7241b344eb53bfe","type":"inject","z":"45e2bb67.67d724","name":"Warmest","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"{\"event_type\":\"node_red.wled_blob\",\"event\":{\"command\":\"set_temperature\",\"color_temp\":500,\"brightness\":\"\",\"ip_address\":\"192.168.0.86\"},\"origin\":\"LOCAL\",\"time_fired\":\"2024-02-19T12:00:53.392888+00:00\",\"context\":{\"id\":\"01HQ0KV3KZF0VWQJ003AXKCN8Y\",\"parent_id\":null,\"user_id\":\"52e86cd98fc0420ebbd8301a6df6a7cb\"}}","payloadType":"json","x":220,"y":800,"wires":[["d8bb1a6807c0aac4"]]},{"id":"d8bb1a6807c0aac4","type":"change","z":"45e2bb67.67d724","name":"","rules":[],"action":"","property":"","from":"","to":"","reg":false,"x":355,"y":820,"wires":[["0e9fa73d268c4e10"]],"l":false},{"id":"719afc65e19e1183","type":"server-events","z":"45e2bb67.67d724","name":"","server":"fbad561e431e2711","version":3,"exposeAsEntityConfig":"","eventType":"node_red.wled_blob","eventData":"","waitForRunning":true,"outputProperties":[{"property":"payload","propertyType":"msg","value":"","valueType":"eventData"},{"property":"topic","propertyType":"msg","value":"$outputData(\"eventData\").event_type","valueType":"jsonata"}],"x":160,"y":760,"wires":[["d8bb1a6807c0aac4"]]},{"id":"7e9f7e1f58848014","type":"inject","z":"45e2bb67.67d724","name":"Coolest","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"{\"event_type\":\"node_red.wled_blob\",\"event\":{\"command\":\"set_temperature\",\"color_temp\":153,\"brightness\":\"\",\"ip_address\":\"192.168.0.86\"},\"origin\":\"LOCAL\",\"time_fired\":\"2024-02-19T12:02:00.763243+00:00\",\"context\":{\"id\":\"01HQ0KX5DA7PNMG5YV4F5BZ9BF\",\"parent_id\":null,\"user_id\":\"52e86cd98fc0420ebbd8301a6df6a7cb\"}}","payloadType":"json","x":230,"y":880,"wires":[["d8bb1a6807c0aac4"]]},{"id":"5b35354b6183af36","type":"inject","z":"45e2bb67.67d724","name":"Medium","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"{\"event_type\":\"node_red.wled_blob\",\"event\":{\"command\":\"set_temperature\",\"color_temp\":232,\"brightness\":\"\",\"ip_address\":\"192.168.0.86\"},\"origin\":\"LOCAL\",\"time_fired\":\"2024-02-19T12:02:33.707331+00:00\",\"context\":{\"id\":\"01HQ0KY5JR77FJN9QV3PPBMV68\",\"parent_id\":null,\"user_id\":\"52e86cd98fc0420ebbd8301a6df6a7cb\"}}","payloadType":"json","x":220,"y":840,"wires":[["d8bb1a6807c0aac4"]]},{"id":"8e46774499e80e01","type":"change","z":"45e2bb67.67d724","name":"Preserve Event","rules":[{"t":"move","p":"payload.event","pt":"msg","to":"bloblight","tot":"msg"},{"t":"move","p":"bloblight.color_temp","pt":"msg","to":"bloblight.mireds","tot":"msg"},{"t":"set","p":"payload","pt":"msg","to":"bloblight.mireds","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":500,"y":840,"wires":[["ca27dc1f9a7f0e2f"]]},{"id":"0e9fa73d268c4e10","type":"change","z":"45e2bb67.67d724","name":"Split Temperatures","rules":[{"t":"set","p":"payload.event.differential","pt":"msg","to":"75","tot":"num"},{"t":"set","p":"payload.event.color_temp","pt":"msg","to":"[payload.event.color_temp - payload.event.differential, payload.event.color_temp, payload.event.color_temp + payload.event.differential]","tot":"jsonata"}],"action":"","property":"","from":"","to":"","reg":false,"x":490,"y":800,"wires":[["8e46774499e80e01"]]},{"id":"ca27dc1f9a7f0e2f","type":"split","z":"45e2bb67.67d724","name":"","splt":"\\n","spltType":"str","arraySplt":1,"arraySpltType":"len","stream":false,"addname":"","x":710,"y":760,"wires":[["372589c0c67a4356"]]},{"id":"372589c0c67a4356","type":"change","z":"45e2bb67.67d724","name":"Convert M to K","rules":[{"t":"set","p":"payload","pt":"msg","to":"{\t \"temperature\": $round(1000000 / payload, 0)\t}","tot":"jsonata"}],"action":"","property":"","from":"","to":"","reg":false,"x":740,"y":800,"wires":[["4105e48b25664024"]]},{"id":"4105e48b25664024","type":"node-red-contrib-colorspace","z":"45e2bb67.67d724","name":"","target":"payload","x":740,"y":840,"wires":[["9a41d8a72dc3263b","e1fdaf93de86a60f"]]},{"id":"9a41d8a72dc3263b","type":"change","z":"45e2bb67.67d724","name":"Preserve RGB","rules":[{"t":"set","p":"payload","pt":"msg","to":"[payload.rgb.red,payload.rgb.green,payload.rgb.blue]","tot":"jsonata"}],"action":"","property":"","from":"","to":"","reg":false,"x":740,"y":880,"wires":[["3cfacb24b9edfce2"]]},{"id":"3cfacb24b9edfce2","type":"join","z":"45e2bb67.67d724","name":"","mode":"auto","build":"object","property":"payload","propertyType":"msg","key":"topic","joiner":"\\n","joinerType":"str","accumulate":"false","timeout":"","count":"","reduceRight":false,"x":950,"y":780,"wires":[["d193803e0b4f6ade"]]},{"id":"7ba15f8a6e6949e8","type":"http request","z":"45e2bb67.67d724","name":"POST JSON","method":"POST","ret":"txt","paytoqs":"ignore","url":"","tls":"","persist":false,"proxy":"","insecureHTTPParser":false,"authType":"","senderr":false,"headers":[],"x":970,"y":860,"wires":[["c5de333fdb5cca11"]]},{"id":"d193803e0b4f6ade","type":"change","z":"45e2bb67.67d724","name":"","rules":[{"t":"set","p":"url","pt":"msg","to":"bloblight.ip_address & \"/json/state\"","tot":"jsonata"},{"t":"move","p":"payload","pt":"msg","to":"bloblight.rgb_array","tot":"msg"},{"t":"set","p":"bloblight.rgb_array[1]","pt":"msg","to":"[0,0,0]","tot":"json"},{"t":"set","p":"payload","pt":"msg","to":"{\t \"on\": bloblight.command != \"turn_off\",\t \"bri\": bloblight.brightness,\t \"transition\": 7,\t \"seg\": [\t {\t \"on\": true,\t \"bri\": 255,\t \"col\": bloblight.rgb_array,\t \"fx\": 75,\t \"fxdef\":true,\t \"pal\": 5,\t \"sx\": 45,\t \"mi\": false,\t \"rev\": false\t } \t ] \t }\t","tot":"jsonata"}],"action":"","property":"","from":"","to":"","reg":false,"x":980,"y":820,"wires":[["7ba15f8a6e6949e8"]]},{"id":"fbad561e431e2711","type":"server","name":"New Home Assistant","version":5,"addon":false,"rejectUnauthorizedCerts":true,"ha_boolean":"y|yes|true|on|home|open","connectionDelay":true,"cacheJson":true,"heartbeat":false,"heartbeatInterval":30,"areaSelector":"friendlyName","deviceSelector":"friendlyName","entitySelector":"friendlyName","statusSeparator":"at: ","statusYear":"hidden","statusMonth":"short","statusDay":"numeric","statusHourCycle":"h23","statusTimeFormat":"h:m","enableGlobalContextStore":true}]
A sample of the adaptive lighting and wled logs follow, but I couldn’t find the correct logging to get the template lights to also appear, which I think might be most useful to understand what’s making the change that triggers manual control:
2024-05-17 20:37:26.843 DEBUG (MainThread) [custom_components.adaptive_lighting.switch] Toms Bedhead Blob: '_update_attrs_and_maybe_adapt_lights' called with context.id='01HY321JDV:al:KRXW:ntrv:7E' lights: 'None', transition: '1.0', force: 'False'
2024-05-17 20:37:26.844 DEBUG (MainThread) [custom_components.adaptive_lighting.switch] Toms Bedhead Blob: filtered_lights: '[]'
2024-05-17 20:37:29.272 DEBUG (MainThread) [custom_components.adaptive_lighting.switch] (0) _service_interceptor_turn_on_handler: call.context.id='01HY321MSPNQW6VE2DPYQW4TMG', is_skipped_hash='False'
2024-05-17 20:37:29.272 DEBUG (MainThread) [custom_components.adaptive_lighting.switch] (1) _service_interceptor_turn_on_handler: call='<ServiceCall light.turn_on (c:01HY321MSPNQW6VE2DPYQW4TMG): entity_id=['light.toms_bedhead_blob'], params=>', service_data='{'entity_id': ['light.toms_bedhead_blob'], 'params': {}}'
2024-05-17 20:37:29.274 DEBUG (MainThread) [custom_components.adaptive_lighting.switch] (2) _service_interceptor_turn_on_handler: switch_to_eids='{'Adaptive Lighting: Toms Bedhead Blob': ['light.toms_bedhead_blob']}', skipped='[]'
2024-05-17 20:37:29.275 DEBUG (MainThread) [custom_components.adaptive_lighting.switch] (3) _service_interceptor_turn_on_handler: intercepting entity_ids='['light.toms_bedhead_blob']'
2024-05-17 20:37:29.276 DEBUG (MainThread) [custom_components.adaptive_lighting.switch] Intercepted TURN_ON call with data {'params': {}, 'entity_id': ['light.toms_bedhead_blob']} (01HY321MSPNQW6VE2DPYQW4TMG)
2024-05-17 20:37:29.281 DEBUG (MainThread) [custom_components.adaptive_lighting.switch] Toms Bedhead Blob: Setting color_temp of light light.toms_bedhead_blob
2024-05-17 20:37:29.282 DEBUG (MainThread) [custom_components.adaptive_lighting.adaptation_utils] Preparing adaptation data for light.toms_bedhead_blob with service data {'entity_id': 'light.toms_bedhead_blob', 'brightness': 171, 'color_temp_kelvin': 2000}
2024-05-17 20:37:29.282 DEBUG (MainThread) [custom_components.adaptive_lighting.switch] Detected an 'light.turn_on('['light.toms_bedhead_blob']')' event with context.id='01HY321MSPNQW6VE2DPYQW4TMG'
2024-05-17 20:37:29.283 DEBUG (MainThread) [custom_components.adaptive_lighting.switch] Toms Bedhead Blob: execute_cancellable_adaptation_calls with data: AdaptationData(entity_id=light.toms_bedhead_blob, context_id=01HY321MT1:al:KRXW:dpt_:7F, sleep_time=0.0, force=False, max_length=1, which=both, initial_sleep=True)
2024-05-17 20:37:29.283 INFO (MainThread) [homeassistant.helpers.script.toms_bedhead_blob] toms_bedhead_blob: Running template script
2024-05-17 20:37:29.284 INFO (MainThread) [homeassistant.helpers.script.toms_bedhead_blob] toms_bedhead_blob: Executing step call service
2024-05-17 20:37:29.292 INFO (MainThread) [homeassistant.components.script.wled_blob] WLED Blob: Running script sequence
2024-05-17 20:37:29.292 INFO (MainThread) [homeassistant.components.script.wled_blob] WLED Blob: Executing step node_red.wled_blob
2024-05-17 20:37:29.312 INFO (MainThread) [homeassistant.helpers.script.toms_bedhead_blob] toms_bedhead_blob: Executing step call service
2024-05-17 20:37:29.365 DEBUG (MainThread) [homeassistant.components.wled] Manually updated wled data
2024-05-17 20:37:29.389 DEBUG (MainThread) [custom_components.adaptive_lighting.switch] Detected a 'light.toms_bedhead_blob' 'state_changed' event: '{'min_color_temp_kelvin': 2000, 'max_color_temp_kelvin': 6535, 'min_mireds': 153, 'max_mireds': 500, 'supported_color_modes': [<ColorMode.COLOR_TEMP: 'color_temp'>], 'color_mode': <ColorMode.COLOR_TEMP: 'color_temp'>, 'brightness': 171, 'color_temp_kelvin': 2000, 'color_temp': 500, 'hs_color': (30.601, 94.547), 'rgb_color': (255, 136, 13), 'xy_color': (0.599, 0.382), 'friendly_name': 'toms_bedhead_blob', 'supported_features': <LightEntityFeature: 0>}' with context.id='01HY321MWR3VXD8G8BEX0R0GAK'
2024-05-17 20:37:29.390 DEBUG (MainThread) [custom_components.adaptive_lighting.switch] Detected an 'off' → 'on' event for 'light.toms_bedhead_blob' with context.id='01HY321MWR3VXD8G8BEX0R0GAK'
2024-05-17 20:37:29.390 DEBUG (MainThread) [custom_components.adaptive_lighting.switch] is_proactively_adapting_context='False', context_id='01HY321MWR3VXD8G8BEX0R0GAK'
2024-05-17 20:37:29.390 DEBUG (MainThread) [custom_components.adaptive_lighting.switch] just_turned_off: delta_time='36.866754' > delay='5'
2024-05-17 20:37:29.390 DEBUG (MainThread) [custom_components.adaptive_lighting.switch] is_proactively_adapting_context='False', context_id='01HY321MWR3VXD8G8BEX0R0GAK'
2024-05-17 20:37:29.390 DEBUG (MainThread) [custom_components.adaptive_lighting.switch] Toms Bedhead Blob: Ignoring 'off' → 'on' event for 'light.toms_bedhead_blob' with context.id='01HY321MWR3VXD8G8BEX0R0GAK' because 'light.turn_on' was not called by HA and 'detect_non_ha_changes' is False
2024-05-17 20:37:29.390 DEBUG (MainThread) [custom_components.adaptive_lighting.switch] Marking 'light.toms_bedhead_blob' as manually controlled.
2024-05-17 20:37:32.344 DEBUG (MainThread) [custom_components.adaptive_lighting.switch] Toms Bedhead Blob: '_update_attrs_and_maybe_adapt_lights' called with context.id='01HY321QSR:al:KRXW:ntrv:7G' lights: 'None', transition: '1.0', force: 'False'
2024-05-17 20:37:32.348 DEBUG (MainThread) [custom_components.adaptive_lighting.switch] Toms Bedhead Blob: filtered_lights: '['light.toms_bedhead_blob']'
2024-05-17 20:37:32.349 DEBUG (MainThread) [custom_components.adaptive_lighting.switch] Toms Bedhead Blob: 'light.toms_bedhead_blob' is being manually controlled, stop adapting, context.id=01HY321QSR:al:KRXW:ntrv:7G.
2024-05-17 20:37:34.147 DEBUG (MainThread) [custom_components.adaptive_lighting.switch] asfsdf: '_update_attrs_and_maybe_adapt_lights' called with context.id='01HY321SJ3:al:MFZW:ntrv:0G' lights: 'None', transition: '45', force: 'False'
2024-05-17 20:37:34.155 DEBUG (MainThread) [custom_components.adaptive_lighting.switch] asfsdf: filtered_lights: '[]'
I’d really appreciate any assistance in preventing the manual control from triggering unexpectedly.
EDIT: Tried listening to call_service
events, but could only see single turn_on
calls on the blob light at an interval matching that configured in adaptive lighting, so everything seems to be okay there.
Also tried configuring adaptive lighting using the light entity from the WLED integration rather than my template entity. It worked as expected without manual mode kicking in for seemingly no reason.
Finaly, tried putting my another light (LIFX) that’s currently working fine on adaptive light behind a template. Even through the template, the manual control works properly.