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