Adaptive Lightning Settings

Sorry for the delay. I will do my best to answer questions.

  1. I AM using the automation to prime the lights.
  2. I point the adaptive lighting integration to either the single bulb or a group made up of only bulbs.
  3. I still have groups that include the switch and any bulbs connected to it.

Some examples below. I will start with a single bulb circuit with an Inovelli light switch.
Z2M Group

Adaptive lighting

This one is also included in a motion sensor automation that I point at the Z2M group to keep the LED bar matched to the brightness.

The second example is a circuit with a single switch and multiple bulbs.
Z2M main group

Z2M bulb group

Adaptive Lighting

This one is also included in a motion sensor automation that I point at the Z2M group to keep the LED bar matched to the brightness.

I think that is everything. Let me know if you have any other questions.

I think what I’m not understanding is how the LED bar is kept in sync if it isn’t part of the zigbee group.

It is part of A zigbee group. Just not the one that primes the bulbs for me. The bulbs are part of a group with the switches though. The only thing I can figure is that whenever anything happens to a member of the Z2M group, all members of the group are kept in sync. That is my only guess because all of this gets very confusing with settings in multiple different locations.

All I can say is that it works for me and my situation. I get instant transitions. The bulbs turn on to the right color. No funny business with lights showing on, but not actually being on. It finally works for me.

I have a slightly different approach that’s also working, and doesn’t use multiple zigbee groups per light/room. It does use multiple instances of Adaptive Lighting, though.

I have a zigbee group per room, containing all lights and switches in that room. The switches are bound to that group.

I have an instance of AL named “Global Color”, which is set to adapt color only, and not brightness. Its update interval is infrequent (300 seconds) and the transition is 5 seconds. It controls every color-adapting bulb in my house directly, and no groups. I did this to reduce traffic on my zigbee network. My understanding is a command sent to a zigbee group is actually broadcast to the entire network, and it’s the responsibility of each device to filter if it belongs to the group. Direct commands result in less traffic.

This “Global Color” AL instance uses an automation to prime the color temperature, so the lights always turn on to the right temperature without a transition.

I have other AL instances for rooms that adapt brightness only, not color. Those updates are more frequent, and control the zigbee groups that contain the switches. Everything stays in sync. I have an automation that turns off the room’s AL if the dimmers are adjusted manually. And it will also reenable AL if I hold the dimmer’s config button.

There’s only one thing I wish were different. There can be a slight brightness transition over the first few seconds after turning on a light in the morning that was last used at night (or vice versa). But otherwise, the setup has been working very well for a few months.

I’d still like to hear more about this automation to prime the lights.

1 Like

The automation is posted above.

@larryo108,
I’m intrigued and would love to know more. I’m a little bit lost as the adaptive lighting HACS “Device” configuration looks different on my installation.

If I’m gathering what you’re saying:

  1. You only use the adaptive lighting to set color temp and not brightness.

  2. When you refer to “automation,” you mean the adaptive lighting HACS module, or do you mean a different sort of automation (native Home Assistant or Node Red, etc.)

  3. Could I ask you a favor? Could you screenshot your configuration screens a little larger/less cropped? Just trying to follow what you’re doing.

My configuration for the Adaptive Lighting HACS device looks like this:

Thanks!
-Jonathan

  1. Yes. I do not let Adaptive Lighting control my brightness with the exception of a couple of lights that have Sleep brightness applied.
  2. The automation I am referring to is posted above for priming the color temp on the lights when they are off. You can scroll through this thread and there is discussion about the automation I am referring to.
  3. See below for a more complete screenshot.

Anyone have the priming brightness setup when using Zigbee2MQTT? Trying to get something similar setup. I’d like to be able to setup a schedule and have the switches still turn the loads on and off directly but using the default brightness changing. Guessing I can use the similar automations but migrate the commands to zigbee2mqtt but was curious if anyone had done it.

Yes. Here is a full priming package for HA:

# Package for "priming" Philips Hue lights and Inovelli Blue dimmers
# with Adpative Lighting color temperatures and brightness values while
# they are off.  This ensures that the lights always turn on with
# the AL settings already applied, and the user does not experience
# a visible transition to those values.
#
# Groups are only primed while they are off.  Standard AL functionality will
# adapt groups that are on.  The primer is triggered every 10 minutes, or when
# the group is turned off (which clears any manual setting, scenes, etc.)
#
# This approach assumes that both indivdual bulbs and the dimmers are
# in the same Z2M group.  This ensures that the dimmer indicators
# always match the brightness of the light group, and values remain in
# sync whether a change is initiated from the dimmer or the Zigbee network.
#
# With this assumption, all configuration is dynamic.  Zigbee device data
# and group relationships are read from MQTT.  Adaptive lighting values are
# read directly from the integration config.  Multiple AL instances are
# supported out of the box.
#
# PREREQUISITES
# - Zigbee2MQTT
# - Philips Hue bulbs and Inovelli Blue dimmers
# - Dimmers must be bound to the same Zigbee group as the bulbs they control
# - Adaptive lighting config must be exposed as an AL switch attribute
#     - include_config_in_attributes: true
# - Dimmer transition times (default 2.5s) should equal Adaptive Lighting
#   transition times (default 1s)
#     - Set Inovelli DimmingSpeedUpRemote parameter to 10

mqtt:
  sensor:
    # Helper sensor containing the basic information we need about Z2M devices to support Adaptive Lighting
    - name: Z2M Adaptive Lighting Devices
      object_id: z2m_adaptive_lighting_devices
      unique_id: b0fbc6ea-b025-4413-9985-0737873d96a0
      state_topic: zigbee2mqtt/bridge/devices
      value_template: "{{ value_json | length }}"
      json_attributes_topic: zigbee2mqtt/bridge/devices
      json_attributes_template: >
        {% set ns = namespace(map={}, bound_devices=[], bound_groups=[]) %}
        {% for z2m_device in value_json %}
          {% set ns.bound_devices = [] %}
          {% set ns.bound_groups = [] %}
          {% for ep in z2m_device.get('endpoints', {}).values() %}
            {% for binding in ep.get('bindings', []) %}
              {% if binding.target.type == 'endpoint'
                    and binding.target.ieee_address is defined
                    and binding.target.ieee_address not in ns.bound_devices %}
                {% set ns.bound_devices = ns.bound_devices + [binding.target.ieee_address] %}
              {% elif binding.target.type == 'group'
                    and binding.target.id is defined
                    and binding.target.id not in ns.bound_groups %}
                {% set ns.bound_groups = ns.bound_groups + [binding.target.id] %}
              {% endif %}
            {% endfor %}
          {% endfor %}
          {% set key = z2m_device.get('friendly_name') %}
          {% set val = {
            'ieee_address': z2m_device.get('ieee_address'),
            'type': z2m_device.get('type'),
            'manufacturer': z2m_device.get('manufacturer'),
            'model_id': z2m_device.get('model_id'),
            'bound_devices': ns.bound_devices,
            'bound_groups': ns.bound_groups
          } %}
          {% set ns.map = ns.map | combine({ key: val }) %}
        {% endfor %}
        {{ {"devices": ns.map} | tojson }}

    # Helper sensor containing the basic information we need about Z2M groups to support Adaptive Lighting
    - name: Z2M Adaptive Lighting Groups
      object_id: z2m_adaptive_lighting_groups
      unique_id: 800ec202-768b-4828-85da-647acf2eb1ee
      state_topic: zigbee2mqtt/bridge/groups
      value_template: "{{ value_json | length }}"
      json_attributes_topic: zigbee2mqtt/bridge/groups
      json_attributes_template: >
        {% set ns = namespace(map={}) %}
        {% for z2m_group in value_json %}
          {% set key = z2m_group.get('friendly_name') %}
          {% set val = {
            'id':  z2m_group.get('id'),
            'group_members': z2m_group.members | map(attribute='ieee_address') | unique | list
          } %}
          {% set ns.map = ns.map | combine({ key: val }) %}
        {% endfor %}
        {{ {"groups": ns.map} | tojson }}

template:
  - sensor:
      # Helper sensor tracking when Z2M groups are turned off
      - name: Z2M Adaptive Lighting Group Off Helper
        unique_id: f1c3b8d2-4a0e-4c5b-9f6d-7c8e1f2b3c4d
        state: "{{ trigger.event.data.new_state.last_changed }}"
        attributes:
          entity_id: "{{ trigger.event.data.entity_id }}"
          group_name: "{{ state_attr(trigger.event.data.entity_id, 'friendly_name') }}"
    trigger:
      - trigger: event
        event_type: state_changed
    condition: >
      {% set friendly_name = state_attr(trigger.event.data.entity_id, 'friendly_name') %}
      {% set z2m_groups = state_attr('sensor.z2m_adaptive_lighting_groups', 'groups') or {} %}
      {{ friendly_name in z2m_groups.keys() 
        and trigger.event.data.old_state.state == 'on'
        and trigger.event.data.new_state.state == 'off' }}

script:
  z2m_adaptive_lighting_apply:
    alias: "Apply Adaptive Lighting to Z2M groups that are turned off"
    mode: queued
    fields:
      group_name:
        description: >
          Optional: Friendly name of Z2M group to apply Adaptive Lighting to.
          Can be a single group name or a list of group names.
          If not provided, all groups will be processed.
        required: false
    sequence:
      - variables:
          z2m_groups: "{{ state_attr('sensor.z2m_adaptive_lighting_groups', 'groups') or {} }}"
          z2m_devices: "{{ state_attr('sensor.z2m_adaptive_lighting_devices', 'devices') or {} }}"
          group_list: >
            {% set groups = [] %}
            {% if group_name is defined %}
              {% if group_name is string and group_name in z2m_groups %}
                {% set groups = [group_name] %}
              {% elif group_name is sequence and group_name is not string %}
                {% set groups = group_name | select('in', z2m_groups.keys()) | list %}
              {% endif %}
            {% else %}
              {% set groups = z2m_groups.keys() | list %}
            {% endif %}
            {{ groups }}
      - repeat:
          for_each: "{{ group_list }}"
          sequence:
            - variables:
                group_name: "{{ repeat.item }}"
                group_entity_id: "light.{{ group_name | slugify }}"
            - if: "{{ is_state(group_entity_id, 'off') }}"
              then:
                - variables:
                    group_members: "{{ z2m_groups[group_name].group_members }}"
                    al_attributes: >
                      {%- set ns = namespace(sw=None) -%}
                      {%- for sw in expand(integration_entities('adaptive_lighting')) -%}
                        {% set config = sw.attributes.get('configuration', {}) %}
                        {% if config.get('lights') and group_entity_id in config.get('lights', []) %}
                          {% set ns.sw = sw %}
                          {% break %}
                        {% endif %}
                      {%- endfor -%}
                      {% if ns.sw %}
                        {{
                          {
                            "switch_id": ns.sw.entity_id,
                            "color_temp_mired": ns.sw.attributes.get('color_temp_mired'),
                            "brightness_pct": ns.sw.attributes.get('brightness_pct'),
                            "manual_control": group_entity_id in ns.sw.attributes.get('manual_control', []),
                            "switch_active": states(ns.sw.entity_id)|bool,
                            "adapt_brightness": states('switch.adaptive_lighting_adapt_brightness_' ~ ns.sw.entity_id.replace('switch.adaptive_lighting_', ''))|bool,
                            "adapt_color": states('switch.adaptive_lighting_adapt_color_' ~ ns.sw.entity_id.replace('switch.adaptive_lighting_', ''))|bool,
                            "sleep_mode": states('switch.adaptive_lighting_sleep_mode_' ~ ns.sw.entity_id.replace('switch.adaptive_lighting_', ''))|bool
                          }
                        }}
                      {% else %}
                        {{ None }}
                      {% endif %}
                - if: "{{ al_attributes is mapping and al_attributes.switch_active and not al_attributes.manual_control }}"
                  then:
                    - variables:
                        adaptive_brightness_255: "{{ (al_attributes.brightness_pct | int(100) * 2.55) | round(0) | int }}"
                        color_temp_mired: "{{ al_attributes.color_temp_mired | int(250) }}"
                    - variables:
                        dimmer_friendly_names: >
                          {% set ns = namespace(dimmers=[]) %}
                          {% for member in group_members %}
                            {% for name, device in z2m_devices.items() %}
                              {% if device.ieee_address == member and device.manufacturer == 'Inovelli' %}
                                {% set ns.dimmers = ns.dimmers + [name] %}
                              {% endif %}
                            {% endfor %}
                          {% endfor %}
                          {{ ns.dimmers }}
                    - alias: Prime the group dimmers with brightness
                      repeat:
                        for_each: "{{ dimmer_friendly_names }}"
                        sequence:
                          - if: "{{ al_attributes.adapt_brightness }}"
                            then:
                              - service: mqtt.publish
                                data:
                                  topic: "zigbee2mqtt/{{ repeat.item }}/set"
                                  payload: >
                                    {{ {'defaultLevelLocal': adaptive_brightness_255} | tojson }}
                    - alias: Prime the group lights with color temperature and brightness
                      service: mqtt.publish
                      data:
                        topic: "zigbee2mqtt/{{ group_name }}/set"
                        payload: >
                          {% set pl = {} %}
                          {% if al_attributes.adapt_brightness %}
                            {% set pl = dict(pl, **{
                              'level_config': { 'execute_if_off': true, 'on_level': adaptive_brightness_255 }
                            }) %}
                          {% endif %}
                          {% if al_attributes.adapt_color %}
                            {% set pl = dict(pl, **{
                              "color_options": { "execute_if_off": true },
                              "color_temp": color_temp_mired
                            }) %}
                          {% endif %}
                          {{ pl | tojson }}

automation:
  - alias: Z2M Adaptive Lighting Primer
    description: >
      Applies Adaptive Lighting to all Z2M groups every 10 minutes and to
      an individual group when turned off
    id: d16ca5e5-e7c6-4fde-ab1c-7a6a526d83fd
    mode: single
    trigger:
      - alias: Every 10 minutes
        platform: time_pattern
        minutes: "/10"
      - alias: A Z2M group is turned off
        platform: state
        entity_id: sensor.z2m_adaptive_lighting_group_off_helper
    action:
      - alias: If the trigger is a Z2M group being turned off, prime the group with Adative Lighting settings.  Otherwise, prime all groups.
        choose:
          conditions:
            - condition: template
              value_template: "{{ trigger.platform == 'state' }}"
          sequence:
            - delay:
                seconds: 5
            - service: script.z2m_adaptive_lighting_apply
              data:
                group_name: "{{ state_attr(trigger.entity_id, 'group_name') }}"
        default:
          - service: script.z2m_adaptive_lighting_apply
3 Likes

Thanks

Hi, would it be possible to modify this automation to track lights from the HA Philips Hue integration, and instead of sending mqtt payloads, to send restful commands (Hue API) ? The API is also json format and use mired values, and can also change the state of a light while off.

Is this a blueprint?