Skip to content

Instantly share code, notes, and snippets.

@iwarner
Last active June 13, 2026 21:01
Show Gist options
  • Select an option

  • Save iwarner/b6a640fe4c26edb764b98bf119c60730 to your computer and use it in GitHub Desktop.

Select an option

Save iwarner/b6a640fe4c26edb764b98bf119c60730 to your computer and use it in GitHub Desktop.
blueprint:
name: Synapse - Motion Sensor Lights
description: >
V1.0.0 — Control lights with a Philips Hue Motion Sensor (SML001/SML002) via ZHA.
Trigger: occupancy detected → turn on lights (optional lux gate).
Timer: no new motion for configured timeout → turn off.
Optional: night mode with lower brightness and warmer colour temperature.
Optional: disable entity (sleep mode switch, TV media player).
IMPORTANT — entity selection: use the "Occupancy" binary_sensor.
Do NOT use the "Motion" or "On/Off" entities — these are dead/unreliable
with the PhilipsMotion quirk (ZHA bug, always off).
domain: automation
source_url: https://gist.github.com/iwarner/b6a640fe4c26edb764b98bf119c60730
author: iwarner
homeassistant:
min_version: "2024.6.0"
input:
occupancy_sensor:
name: Occupancy Sensor
description: >
Select the Occupancy binary_sensor from the Philips Hue motion sensor device.
In ZHA device page → Sensors → look for "Occupancy" (device_class: occupancy).
Do NOT select "Motion" or "On/Off" — those are unreliable.
selector:
entity:
domain: binary_sensor
device_class: occupancy
light_target:
name: Light(s)
description: Light entity, ZHA group entity, or area to control.
selector:
target:
entity:
domain: light
no_motion_timeout:
name: No Motion Timeout
description: >
Seconds after last detected motion before lights turn off.
HA controls this timer — independent of the sensor's internal Zigbee timeout.
Each new motion detection resets the timer from zero.
default: 120
selector:
number:
min: 10
max: 3600
step: 10
unit_of_measurement: seconds
mode: box
illuminance_sensor:
name: Illuminance Sensor (optional)
description: >
If set, lights only turn on when lux is below the threshold.
Use the illuminance sensor from the same motion sensor device.
Leave empty to always turn on regardless of ambient light.
default:
selector:
entity:
domain: sensor
device_class: illuminance
lux_threshold:
name: Lux Threshold
description: >
Only turn on lights if illuminance is below this value.
Ignored if no illuminance sensor is set.
Typical indoor dark threshold: 30-80 lx. Closets with no windows: not needed.
default: 50
selector:
number:
min: 0
max: 3000
step: 5
unit_of_measurement: lx
mode: box
daytime_brightness:
name: Daytime Brightness
description: Brightness percentage when not in night mode.
default: 80
selector:
number:
min: 1
max: 100
step: 1
unit_of_measurement: "%"
mode: slider
daytime_colour_temp:
name: Daytime Colour Temperature (K)
description: >
6500K = cool white, 4000K = neutral white, 2700K = warm white.
default: 4000
selector:
number:
min: 2200
max: 6535
step: 100
unit_of_measurement: K
mode: box
nighttime_brightness:
name: Night Brightness
description: >
Brightness at night. Use a very low value (10-20%) to avoid blinding
when waking in the dark.
default: 15
selector:
number:
min: 1
max: 100
step: 1
unit_of_measurement: "%"
mode: slider
nighttime_colour_temp:
name: Night Colour Temperature (K)
description: >
2200K = very warm amber — preserves night vision and minimises sleep disruption.
default: 2200
selector:
number:
min: 2200
max: 6535
step: 100
unit_of_measurement: K
mode: box
night_start:
name: Night Mode Start
description: Time at which night mode begins (local time).
default: "22:00:00"
selector:
time:
night_end:
name: Night Mode End
description: Time at which night mode ends (local time).
default: "07:00:00"
selector:
time:
disable_entity:
name: Disable Entity (optional)
description: >
When active, motion is ignored. input_boolean: disabled when 'on'.
media_player: disabled when 'playing' or 'paused'. Leave empty to never disable.
default:
selector:
entity:
domain:
- input_boolean
- binary_sensor
- media_player
trigger:
- platform: state
entity_id: !input occupancy_sensor
to: "on"
condition: []
variables:
illuminance_sensor: !input illuminance_sensor
lux_threshold: !input lux_threshold
disable_entity: !input disable_entity
night_start: !input night_start
night_end: !input night_end
daytime_brightness: !input daytime_brightness
daytime_colour_temp: !input daytime_colour_temp
nighttime_brightness: !input nighttime_brightness
nighttime_colour_temp: !input nighttime_colour_temp
no_motion_timeout: !input no_motion_timeout
is_night: >
{% set t = now().strftime('%H:%M:%S') %}
{% if night_start > night_end %}
{{ t >= night_start or t < night_end }}
{% else %}
{{ night_start <= t < night_end }}
{% endif %}
active_brightness: "{{ nighttime_brightness if is_night else daytime_brightness }}"
active_colour_temp: "{{ nighttime_colour_temp if is_night else daytime_colour_temp }}"
lux_ok: >
{% if illuminance_sensor == none %}
true
{% else %}
{{ states(illuminance_sensor) | float(0) < lux_threshold }}
{% endif %}
disable_active: >
{% if disable_entity == none %}
false
{% else %}
{{ states(disable_entity) in ['on', 'playing', 'paused'] }}
{% endif %}
action:
- condition: template
value_template: "{{ lux_ok and not disable_active }}"
- service: light.turn_on
target: !input light_target
data:
brightness_pct: "{{ active_brightness }}"
color_temp_kelvin: "{{ active_colour_temp }}"
transition: 1
- delay:
seconds: "{{ no_motion_timeout }}"
- service: light.turn_off
target: !input light_target
data:
transition: 2
mode: restart
max_exceeded: silent
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment