Make your second light mirror power, brightness, and color temperature from the first one — reliably and fast. Tuned for Matter lights that may expose Kelvin or mireds.
TL;DR 🧾
- L2 is the source, L3 is the target.
- Mirrors on/off, brightness, and CCT (prefers Kelvin, falls back to mireds).
- Uses numeric guards to avoid bad states.
mode: restartkeeps things snappy during slider drags.
Why this approach? 💡
Light groups mirror power well, but attributes (brightness/CCT) can be flaky across vendors. This automation enforces deterministic one‑way syncing with Kelvin‑first logic and solid guards — a pattern consistent with the style used across practical, step‑by‑step posts on vahac.com.
Requirements ✅
- Home Assistant 2024.x+
- Two light entities (here named):
- Source (L2):
light.matter_living_light_2 - Target (L3):
light.matter_living_light_3
- Source (L2):
- Source exposes at least one of:
color_temp(mireds),color_temp_kelvin, orkelvin.
Tip: Kelvin is more intuitive (e.g., 2700 K = warm, 6500 K = cool). Mireds are the reciprocal scale.
Full YAML (copy‑paste) 📦
Replace entity IDs to match your setup.
alias: Sync power + brightness + color temp
sequence:
- data:
entity_id: light.matter_living_light_3
kelvin: >-
{{ (state_attr('light.matter_living_light_2','color_temp_kelvin')
or state_attr('light.matter_living_light_2','kelvin')) | int }}
action: light.turn_on
default:
- condition: template
value_template: >-
{{ state_attr('light.matter_living_light_2','color_temp') is number }}
- data:
entity_id: light.matter_living_light_3
color_temp: >-
{{ state_attr('light.matter_living_light_2','color_temp') | int }}
action: light.turn_on
- conditions:
- condition: template
value_template: "{{ trigger.id == 'brightness' }}"
sequence:
- condition: state
entity_id: light.matter_living_light_2
state: "on"
- condition: template
value_template: "{{ trigger.to_state.attributes.brightness is number }}"
- data:
entity_id: light.matter_living_light_3
brightness: "{{ trigger.to_state.attributes.brightness | int }}"
action: light.turn_on
- conditions:
- condition: template
value_template: "{{ trigger.id == 'ct_mireds' }}"
sequence:
- condition: state
entity_id: light.matter_living_light_2
state: "on"
- condition: template
value_template: "{{ trigger.to_state.attributes.color_temp is number }}"
- data:
entity_id: light.matter_living_light_3
color_temp: "{{ trigger.to_state.attributes.color_temp | int }}"
action: light.turn_on
- conditions:
- condition: template
value_template: "{{ trigger.id in ['ct_kelvin','kelvin'] }}"
sequence:
- condition: state
entity_id: light.matter_living_light_2
state: "on"
- choose:
- conditions:
- condition: template
value_template: >-
{{ trigger.to_state.attributes.color_temp_kelvin is number }}
sequence:
- data:
entity_id: light.matter_living_light_3
kelvin: >-
{{ trigger.to_state.attributes.color_temp_kelvin | int }}
action: light.turn_on
default:
- condition: template
value_template: "{{ trigger.to_state.attributes.kelvin is number }}"
- data:
entity_id: light.matter_living_light_3
kelvin: "{{ trigger.to_state.attributes.kelvin | int }}"
action: light.turn_on
mode: restartHow it works (short & sweet) 🛠️
- Power OFF →
light.turn_off(L3). - Power ON →
light.turn_on(L3)→ copy brightness (if numeric) → copy Kelvin if present, else mireds. - While ON: attribute‑specific updates listen to
brightness,color_temp(mireds), orcolor_temp_kelvin/kelvinand forward only that field.
Guards that matter:
... is numberavoids errors onunknown/unavailable.condition: state == onprevents changes while the source is off.mode: restartkeeps the last change winning during rapid slider moves.
Attribute primer 🌈
- Brightness: HA service data uses 0–255 (even if UI shows %).
- Kelvin: 2700 K (warm) ↔ 6500 K (cool). Preferred when available.
- Mireds (
color_temp): reciprocal scale. Lower mireds = cooler.
Testing checklist ✅🧪
- Toggle L2 on/off → L3 mirrors instantly.
- Drag brightness on L2 → L3 tracks smoothly.
- Set Kelvin on L2 (e.g., 2700/4000/6500) → L3 matches.
- If Kelvin isn’t exposed, adjust mireds → L3 matches via
color_temp. - While L2 is off, changing sliders should not affect L3; turning L2 on snaps L3 to the latest look.
Troubleshooting 🔍
- Brightness doesn’t update → Check Developer Tools → States: ensure L2
brightnessis numeric while ON. - CCT doesn’t update → Verify which attribute L2 exposes (
color_temp,color_temp_kelvin,kelvin) and that L3 accepts the same field you’re sending. - Flicker/lag → Device may rate‑limit;
mode: restartalready helps. Consider adding a smallfor:delay to the brightness trigger if needed. - No loops → Only L2 → L3 is wired. Don’t add automations that write L3 → L2 unless you isolate them.
FAQ ❓
Q: Why prefer Kelvin over mireds?
A: Many Matter integrations surface Kelvin and users find it more intuitive; the fallback keeps compatibility with mired‑only devices.
Q: Will this mess with effects or scenes?
A: If L2 changes due to a scene, L3 will mirror. Use a helper to pause syncing when you want L3 independent.
Conclusion 🧩
A single, guarded automation keeps two bulbs visually identical across vendors — power, brightness, and CCT, with Kelvin‑first logic. Clean, fast, dependable.