Adaptive Lightning Settings

You are right. It does appear to be working. Wish I didn’t need the automation workaround, but happy to not have the initial transition. Thank you so much for all of the help in this thread. Truly appreciate it.

1 Like

I’m also interested in solving this, though it’s much less of an eyesore for me than the color temperature was.

I wonder if brightness can also be sent while the light is off without turning it on. I’m going to test in MQTT Explorer and report back.

I’ll be interested to hear what you find.

I decided to go ahead and update the automation I wrote to change the local default dimming level on my Blue switches. I think this should address most of my concerns with Adaptive Lighting. I’d prefer to change the brightness without turning the light on, though. (I don’t really want to test the reliability of constant parameter writes to these over the years, but as others have pointed out, it’ll be hard to really exhaust the max writes.)

Current revision of adaptive-lighting-adjust-while-off.yaml:

I found some online discussions about execute_if_off also being a parameter for level_config in addition to color_options for some lights, but so far I haven’t been able to publish an MQTT command to set the brightness without also turning the lights on. So currently, I’m stuck.

I believe I read somewhere that the Zigbee protocol doesn’t allow brightness changes while off. If that’s true, then no lights (that properly implement the protocol) would be able to do this.

I don’t see a reason why Inovelli couldn’t add a special command to achieve the same thing, though. This would be easier if the firmware were open source. It seems like a reasonable request, but I’d imagine other higher priority items will always be prioritized.

In the meantime, using parameter 13 seems to be working for me. (See above.) I’m still worried about too many writes, but I’m going to try to dig in and see if my code is actually sending messages to the device when the brightness value doesn’t change. (Wrapping it in a conditional is a simple enough change.) I don’t know the code to set the parameter for z2m, but I doubt it would be hard to find it and adapt what I did.

It turns out that with ZHA, when you invoke the following action, it will always result in a message sent to the device (even if the value doesn’t change):

action: number.set_value
target:
  entity_id: number.my_light_local_default_dimming_level
data:
  value: "45"

Here’s part of what was logged when I did this twice in a row:

2025-03-21 14:12:05.497 DEBUG (MainThread) [zigpy.zcl] [0x3173:1:0xfc31] Sending request header: ZCLHeader(frame_control=FrameControl<0x04>(frame_type=<FrameType.GLOBAL_COMMAND: 0>, is_manufacturer_specific=True, direction=<Direction.Client_to_Server: 0>, disable_default_response=0, reserved=0, *is_cluster=False, *is_general=True), manufacturer=4655, tsn=19, command_id=<GeneralCommand.Write_Attributes: 2>, *direction=<Direction.Client_to_Server: 0>)
2025-03-21 14:12:05.498 DEBUG (MainThread) [zigpy.zcl] [0x3173:1:0xfc31] Sending request: Write_Attributes(attributes=[Attribute(attrid=0x000D, value=TypeValue(type=uint8_t, value=45))])
2025-03-21 14:12:05.628 DEBUG (MainThread) [zigpy.zcl] [0x3173:1:0xfc31] Decoded ZCL frame: InovelliVZM31SNCluster:Write_Attributes_rsp(status_records=[WriteAttributesStatusRecord(status=<Status.SUCCESS: 0>)])
2025-03-21 14:12:08.678 DEBUG (MainThread) [zigpy.zcl] [0x3173:1:0xfc31] Sending request header: ZCLHeader(frame_control=FrameControl<0x04>(frame_type=<FrameType.GLOBAL_COMMAND: 0>, is_manufacturer_specific=True, direction=<Direction.Client_to_Server: 0>, disable_default_response=0, reserved=0, *is_cluster=False, *is_general=True), manufacturer=4655, tsn=20, command_id=<GeneralCommand.Write_Attributes: 2>, *direction=<Direction.Client_to_Server: 0>)
2025-03-21 14:12:08.680 DEBUG (MainThread) [zigpy.zcl] [0x3173:1:0xfc31] Sending request: Write_Attributes(attributes=[Attribute(attrid=0x000D, value=TypeValue(type=uint8_t, value=45))])
2025-03-21 14:12:08.799 DEBUG (MainThread) [zigpy.zcl] [0x3173:1:0xfc31] Decoded ZCL frame: InovelliVZM31SNCluster:Write_Attributes_rsp(status_records=[WriteAttributesStatusRecord(status=<Status.SUCCESS: 0>)])

I’ve therefore updated my automation (rev4, current) to only perform the number.set_value when the value has changed. I’m not sure what happens in the switch firmware & whether or not it would attempt to write anything, but this safeguard should ensure no messages are getting sent when the values don’t change and that I’m not writing too frequently to the switch.

Here is a good replacement set of code so that if you do not have all the lights attributes checked that the code will still continue without breaking.

         lights_currently_off_and_controlled_by_adaptive_lighting_entity: >-
              {% if state_attr(adaptive_lighting_entity, "configuration") is defined and
                    state_attr(adaptive_lighting_entity, "configuration").lights is defined %}
                {{ state_attr(adaptive_lighting_entity, "configuration").lights |
                   expand |
                   selectattr("state", "==", "off") |
                   map(attribute="entity_id") |
                   list }}
              {% else %}
                []
              {% endif %}

I think rather than adding the check and having the automation silently fail, it might be better to use similar logic to enable include_config_in_attributes if configuration isn’t defined for a particular AL instance.

The nice thing with the check, I now can have this apply to some, but not all, of my AL settings. I have 8 groups of them, each different in their own way, and a few that do not need this. That way I can limit the broadcast traffic to the Zigbee network. Also playing with some of the delay settings to not overload the network with excess broadcast messages. Typically can only handle 8 messages in a 9 second window.

Here are the final changes for my setup to find the base topic for each network and also for how my naming works:

              - variables:
                  light_currently_off: "{{ repeat.item }}"
                  friendly_name: "{{ light_currently_off.split('.')[1] }}"
                  device_identifier_tuple: >-
                    {{ device_attr(light_currently_off, 'identifiers') | list |
                    first }}
                  device_identifier: "{{ device_identifier_tuple[1] }}"
                  device_network_id: network_{{ device_identifier.split('_')[1] }}
                  base_topic: >-
                    {% if device_network_id == 'network_84574362537988764539875'
                    %}
                      z2m1
                    {% else %}
                      z2m2
                    {% endif %}
                  mqtt_topic: "{{ base_topic }}/{{ light_currently_off.split('.')[1]}}/set"

I have had the automation running now for about a week and I feel that the transitions have gotten better. However, I am having another odd issue now where on my motion detected lights specifically the lights do not turn on as expected. The only thing I can think is that the execute if off is somehow making the bulbs think they are on when they actually aren’t. Has anyone else experienced this behavior.

No, but something similar & I haven’t fixed it yet. Every once and a while I notice that the smart bulbs are on at 0% brightness while the switch is marked as off.

This makes automations I have based on the lights being off not work (as you’re experiencing).

I was thinking of adding an automation to detect the lights at 0% and on for a few seconds and then turn them off. I’ll get to it eventually, but it’s a low priority for me at the moment.

I wanted to dig into this a little more since my automation is working well and I can’t find details on the forum about the Blue switches.

What I found is the EFR32MG21 chip spec states that it should endure at least 10,000 flash erase cycles before failure (tested below 125°C).

Someone breaks this down further to explain a three byte data write repeated 500 times a day:

Let me do the math for you:

When you write a 3-byte key to PS, it consumes at least 8 bytes because there is some overhead in the storage (it’s not documented by Silabs but it is not hard to reverse-engineer). The PS content is a list that grows whenever you write a new value or change some existing value. Changing a value will make a new entry at the end of the list and invalidate the previous entry. Therefore there will be “holes” in the list and these can be cleaned up when the flash sector is erased.

Sector size is 2048 bytes. Therefore you can write a 3-byte value (consuming 8 bytes) a total of 2048/8 = 256 times before the sector becomes full. When that happens, the content is moved to another sector (PS uses two sectors that are used, only one of them being active).

If you write 500 times a day, that means that you will reach end of flash sector about twice a day. So there is two erases per day, one for each block.

Assuming 10000 erase cycles endurance, the estimated lifetime is then 10000 days which is 27 years. That sounds quite a long period.

My automation is updating a setting about 50 times a day, so assuming all of the above is correct, then this should be okay to do for a pretty long stretch of time. (I’ll probably have other problems before these writes destroy a switch.)

So I figured out that my lights were doing something similar to yours and turning on at only 1%. This happened for a couple of lights when I voice controlled them through Siri. Not sure why or how because the Inovelli switches are programmed to turn on at max brightness and the AL integration has a minimum brightness of 25% set.

I am not sure if this is the same issue you were having or if you were able to figure out an automation for it.

I am still getting weirdness with the motion activated lights, but can’t figure out what is going on. Sometimes my dashboard says they are on, but they aren’t or they are at 1% brightness. Other times they do not turn off as I have programmed. I’ll keep playing and report back if I find anything.

Mine are the other way around. When turning them off, the switch turns off & is marked as off, but the Hue bulbs are still “on” at zero percent brightness.

Gotcha.

I have turned off my automation for now. I am still getting weird behavior with some of the lights not working until I click the Inovelli switch to either turn them on or off. I tried removing the switches from the groups. I tried point the adaptive lighting at the bare bulbs instead of the groups. Still getting weirdness. Wish it wasn’t so difficult to be able to remove the transitions when turning a light on.

When I was still all in on Homekit, the adaptive lighting there just worked. I wish it was that simple.