Experimenting with Kitchen Lighting Automation
I bought a ton of new Z-wave switches and dimmers, and I’m still trying to find the best user interface for automated lighting given the equipment I have, as well as what would be ideal in a new built house. Today, I tried a few automations for my kitchen lighting, which being the center of activity in the house, are the most noticed by everyone, and must work properly at all times.
First things first, what I’m working with to start. The kitchen has 4 can lights, 3 island pendants, and 2 strings of color changing LEDs fixed to blue on top of the cabinets. The kitchen has an open entry from the great room, stairs going to the second floor, short path to the basement stairs and front TV room, a door to the mud room (which is always left open), and a door to the back deck. Electrically, there is a 3-way switch for the can and pendant lights together (no separate control unfortunately), with the passage to the front TV room lackng a switch (which has been an annoyance for a long time). The color changing LEDs are wired to a single switch next to the stove, as the wiring was intended for under-cabinet lights.
The first place to start with any automation is sensing. In this case, I have a mix of motion sensors and door contacts which I’ve chosen for this project. The mud room already has a motion sensor, and I’m going to trigger the kitchen lights when the motion sensor in the mud room is triggered, since it’s likely the kitchen is the next destination. I also already have a door contact (from my Xfinity Sensors project on the deck door, and I’d like to turn the kitchen light on when the deck door is opened or closed (when the state changes, not when the state is open). I also decided to relocate the Inovelli 4-in-1 motion sensor from my Smart Bathroom to the kitchen, since the bathroom was doing fine with cheaper sensors and the Inovelli motion sensor has a sensing pattern that wasn’t very good in the tiny bathroom.
The next step is control. I chose the Inovelli Red Series Dimmer to control the kitchen lights, and was forced to mount it at the bottom of the stairs since that’s the 3-way switch where power enters the circuit. Ideally I could put it on the other side of the kitchen, but I’ll do some magic later to make both switches work. For the over-cabinet lights, I chose the Inovelli Red Series Switch. Because the wiring in the kitchen is bizarre, these lights are actually fed by the mud room power circuit, and are located next to the dumb 3-way switch for the main lights. This means I can use multi-taps of the over-cabinet switch to control the main light switch, or the dumb 3-way switch.
Finally, we have to bridge the two togehter with logic. In my case, there are a few rules for the logic:
- Lights should default to a dim level at night, but only well after dark, and should revert to full brightness by sunrise
- Lights should turn on automatically if motion is detected in the kitchen, mud room, or the deck door is opened/closed
- Lights should have a way to be forced to stay on automatically at full brightness regardless of other commands
- Lights should have a way to revert to automatic control
- Lights should indicate to the user if they are in forced on mode
- Lights should automatically exit forced on mode after several hours if they are not turned off manually
- Lights should exit forced on mode if they are turned off manually by either the main or slave 3-way switch
- Lights should have a way to be forced on from the other side of the room as intuitively as possible
I ended up breaking this down into a few key bits of automation in Home Assistant:
- Group containing the binary sensors which trigger the automated lights
- Input boolean containing the state of the forced on override
- Automation to turn the lights on automatically
- Automation to handle changes to the forced on override state
- Automation to handle multi-presses of the button to change the forced override state
- Automation at sunrise/sunset to change the default levels of the switch
The code for each of these is below.
1. Group for Sensors⌗
In templates.yaml, I have a template which turns on a binary_sensor whenever the door state changes (and off automatically later). Since the template uses now() it is processed every minute, so the binary_sensor will stay on between 10 and 70 seconds depending on when the processing occurs.
- binary_sensor:
#Indicate if any door switches have **changed** recently (for motion lights)
- name: "Kitchen Door Deck Contact Changed"
unique_id: "kitchen_door_deck_contact_changed"
state: "{{ (as_timestamp(now()) - as_timestamp(states.binary_sensor.kitchen_door_deck_contact.last_changed)) | float < 10 }}"
In groups.yaml I have the group for the sensors:
#Triggers for kitchen lights
kitchen_light_motion:
name: Kitchen Light Motion
entities:
#Motion sensors in the kitchen
- binary_sensor.kitchen_motion_occupancy
#Other sensors which should trigger kitchen lights
- binary_sensor.mud_room_motion_occupancy
- binary_sensor.kitchen_door_deck_contact_changed
2. Input Boolean⌗
Just go to Helpers and create an Input Boolean. Mine is named input_boolean.kitchen_light_override
3. Automation to turn on the lights automatically⌗
I can’t use the Blueprint that ships with HA to do this since I’m using a Group instead of a binary_sensor, so I implemented the equivalent manually.
alias: Kitchen Lights Motion
description: Turn on Kitchen Lights based on Motion
trigger:
- platform: state
entity_id: group.kitchen_light_motion
to: 'on'
condition: []
action:
- service: light.turn_on
target:
entity_id: light.kitchen_lights
- wait_for_trigger:
- platform: state
entity_id: group.kitchen_light_motion
to: 'off'
- delay:
hours: 0
minutes: 4
seconds: 0
milliseconds: 0
- service: light.turn_off
target:
entity_id: light.kitchen_lights
mode: restart
You can create a new automation in the GUI and paste this in, and then switch back to the visual editor if you want. Since the mode is ‘restart’, any new motion detected during the delay period will restart the automation and turn the light on again, waiting for the motion sensor to go off again, and the final turn off won’t occur until the delay is able to complete.
4. Automation to handle changes to Override State⌗
This automation runs whenever the input_boolean changes and responds by setting the lights appropriately. I used a choose to implement the turned on and turned off logic, instead of two automations. It could have been done with two shorter automations instead.
alias: Kitchen Light Update Forced On
description: Update the state of Kitchen Lights when force-on is changed
trigger:
- platform: state
entity_id: input_boolean.kitchen_light_override
condition: []
action:
- choose:
- conditions:
- condition: state
entity_id: input_boolean.kitchen_light_override
state: 'on'
sequence:
- service: automation.turn_off
data:
stop_actions: true
target:
entity_id: automation.kitchen_lights_motion
- service: light.turn_on
target:
entity_id: light.kitchen_lights
data:
brightness_pct: 100
- service: zwave_js.set_config_parameter
data:
parameter: '13'
value: '85'
target:
entity_id: light.kitchen_lights
default:
- service: automation.turn_on
target:
entity_id: automation.kitchen_lights_motion
- service: light.turn_off
target:
entity_id: light.kitchen_lights
- service: zwave_js.set_config_parameter
data:
parameter: '13'
value: '170'
target:
entity_id: light.kitchen_lights
mode: restart
In short, the automation does the following:
- Check if the input boolean is currently on or off, and either run the on or off logic (the ‘choose’)
- If the override is on:
- Turn off the motion sensor automation and do not let it complete (‘stop_actions: true’) so it does not turn off the light
- Turn on the light and force the brightness to 100%
- Write the parameter on the switch which sets the LED color, and set it to Green (this is Inovelli-specific) to indicate the light is under forced control
- If the override is off:
- Turn the motion sensor automation back on
- Turn the light back off
- Write the parameter on the switch which sets the LED color, and set it to Blue (this is Inovelli-specific) to indicate the light is under automatic control
5. Automation to handle multi-presses⌗
Again, I wrote this as a single automation with multiple event triggers. Inovelli switches support up to 5x taps on the up and down button. By default, a single tap is bound to ‘on’ or ‘off’, and the other taps are not bound to anything, but they still generate events of type ‘zwave_js_value_notification’. I capture these events and run logic based on them. I also check if the light is turned off, instead of capturing the single-press off event, so I can correctly capture any events which turn the light off (such as the remote 3-way turning the light off, which doesn’t generate any press events).
For the Inovelli switches, a property key name of ‘001’ is the down button and ‘002’ is the up button. Value will be ‘KeyPressed’ or ‘KeyPressedNx’ where N is 2,3,4,5 for multi-taps. This event relies on the Z-wave node ID, in my case 23 is the kitchen dimmer and 21 is the kitchen over-cabinet switch.
alias: Kitchen Light Double-Tap Handler
description: Double-tap the kitchen light for it to stay on full brightness
trigger:
- platform: event
event_type: zwave_js_value_notification
event_data:
node_id: 23
property_key_name: '002'
value: KeyPressed2x
id: KeyPressOn
- platform: event
event_type: zwave_js_value_notification
event_data:
node_id: 23
property_key_name: '001'
value: KeyPressed2x
id: KeyPressOff
- platform: state
entity_id: light.kitchen_lights
id: KeyPressOffSingle
to: 'off'
- platform: event
event_type: zwave_js_value_notification
event_data:
node_id: 21
property_key_name: '001'
value: KeyPressed2x
id: KeyPressOffAccent
- platform: event
event_type: zwave_js_value_notification
id: KeyPressOnAccent
event_data:
node_id: 21
property_key_name: '002'
value: KeyPressed2x
condition: []
action:
- choose:
- conditions:
- condition: or
conditions:
- condition: trigger
id: KeyPressOn
- condition: trigger
id: KeyPressOnAccent
sequence:
- service: input_boolean.turn_on
target:
entity_id: input_boolean.kitchen_light_override
- delay:
hours: 4
minutes: 0
seconds: 0
milliseconds: 0
- service: input_boolean.turn_off
target:
entity_id: input_boolean.kitchen_light_override
- conditions:
- condition: trigger
id: KeyPressOffSingle
- condition: state
entity_id: input_boolean.kitchen_light_override
state: 'on'
sequence:
- service: input_boolean.turn_off
target:
entity_id: input_boolean.kitchen_light_override
default:
- service: input_boolean.turn_off
target:
entity_id: input_boolean.kitchen_light_override
mode: restart
The automation first sets up 5 triggers which are named for the future. Double-tap up on either the kitchen dimmer or overcabinet switch, and change of state of the light to off (by any means).
If a double-tap up is pressed (either switch), the light override is turned on, and then after 4 hours it is turned back off. Since the mode is restart, any other events will stop this delay.
If the light is turned off for any reason and the override was already set on, the override is turned off to return to automatic control.
If a double-tap down is pressed (either switch), the default case runs and the override is turned off.
6. Sunrise and Sunset⌗
I already have two very long sunrise and sunset automations which set up the lighting brightness and enable/disable automations, so I wrote parameters 9 and 10 (default level and default level Z-wave respectively) on the dimmer in these automations. These parameters are Inovelli specific, and even specific to the dimmer (for the LZW36 fan+light model, the parameters are 12 and 13).
After all of this, I’m fairly satisfied and might expand this UI concept (green means forced, blue means automatic) to the rest of my automated lighting. The RGB indicators on Inovelli switches really make this nice.