tl;dr: I explain how to integrate a Xiaomi Aquara Motion sensor and a Govee light-strip with my openhab-setup and present two nice applications: a night-light and an artificial pre-alarm-wakeup-sunrise.
For Christmas, I got an LED Light-strip (from Govee) that has a small microcontroller attached and lives in my WIFI. I also added it into my Alexa-Ecosystem (hence I can control it via Alexa-routines). However, I wanted to do more 🙂 The second present I got was a Xiaomi Aquara Motion-sensor (which speaks Zigbee and I should be able to control it with my Conbee II Zigbee-Stick). My plan was to combine the two things to build various gimmicks:
- A night light that gets triggered by the motion sensor, when you get up in the night and that shines for ~20 seconds
- when a new alarm gets set via Alexa, get the time via openhab (and HABapp) and 5 minutes before the alarm goes off, set the light-strip to “sunrise”, so that you are already woken up by the light (or at least the wake-up is more gentle).
Setup
Our Govee-Light-Strip is only added to Alexa and can be controlled from openhab via Alexa-Routines, so I added a new item “Echo_Bedroom_StartRoutine” I can send commands to. Also I can query the next alarm that has been set on the echo via the item “Echo_Bedroom_NextAlarm”.
Adding the motion-sensor is straightforward: we add it as a thing as a Zigbee-device to my “deconz”-devices (like the window open-close-sensor, cf. Window Alert Rule with HABApp and Alexa). Caveat: this one sensor, actually is two “things”, one presencesensor and one lightsensor (not very sensitive — I am not using it right now).
The relevant parts of my things and items files:
[smarhome.things]
Bridge amazonechocontrol:account:MyEchoAccount "Amazon Account" @ "Accounts" [discoverSmartHome=3, pollingIntervalSmartHomeAlexa=60, pollingIntervalSmartSkills=120]
{
[...]
Thing echo echo_dot_bedroom "Alexa" @ "Bedroom" [serialNumber="XXXX"]
}
Bridge deconz:deconz:homeserver [ host="x.x.x.x", httpPort="8090", apikey="XXXX" ]
{
[...]
Thing lightsensor light_bedroom "Light sensor bedroom" @ "Bedroom" [ id="11", lastSeenPolling=2 ]
Thing presencesensor motion_bedroom "Motion sensor bedroom" @ "Bedroom" [ id="12", lastSeenPolling=2 ]
}
[smarthome.items]
Switch presence_bedroom "Presence in the bedroom: [%s]." <motion> (gBedRoom) ["Motion"] {channel="deconz:presencesensor:homeserver:motion_bedroom:presence"}
Number:Illuminance lux_bedroom "Lux in the bedroom: [%d]" <light> ["Light"] {channel="deconz:lightsensor:homeserver:light_bedroom:lightlux"}
String Echo_Bedroom_StartRoutine "Start Routine" (gAlexaEchosIn) {channel="amazonechocontrol:echo:MyEchoAccount:echo_dot_bedroom:startRoutine"}
Night Light
The basic night-light-functionality is simple: If the motion-sensor detects movement, we trigger an Alexa-routine (wich we called “bewegungssensor routine bett”) that switches our Govee-Light-Strip to “red” with an intensity of 1% for 20 seconds — this is low enough to not disturb a sleeping person, but high enough to illuminate the room dimly when getting up at night.
import HABApp
import HABApp.openhab.definitions
from HABApp.core.events import ValueUpdateEvent
from HABApp.core.events import ValueUpdateEventFilter
from HABApp.openhab.items import SwitchItem
from HABApp.openhab.items import StringItem
import datetime
import logging
log = logging.getLogger("MyRuleLogger")
class BedroomMovementDetector(HABApp.Rule):
def __init__(self):
super().__init__()
self.movement_detector = SwitchItem.get_item("presence_bedroom")
self.alexa_routine = StringItem.get_item("Echo_Bedroom_StartRoutine")
self.movement_detector.listen_event(self.movement_detected, ValueUpdateEventFilter())
def movement_detected(self, event: ValueUpdateEvent):
log.debug(f'{event.name} updated value: "{event.value}"')
log.debug(f"Last update of {self.movement_detector.name}: " +
f"{self.movement_detector.last_update}")
log.debug(f"Last change of {self.movement_detector.name}: " +
f"{self.movement_detector.last_change}")
if self.movement_detector.is_on():
log.debug("Potentially, we switch on the night-light...")
log.debug("Movement detected -- commanding alexa.")
self.alexa_routine.oh_send_command("bewegungssensor routine bett")
BedroomMovementDetector()
Improvements
Our first version of the night-light above has two drawbacks:
- It also gets triggered during the day
- When we have started a routine that plays a scene on the light-strip and then trigger the motion-sensor, the scene will be interrupted
The first is not really a big issue — the light is barely visible, but still … . The second issue is more annoying. Many times close to bedtime, when we had set the light-strip to “sunset” (takes some 5-10 minutes) and then accidentally triggered the motion sensor, the light-strip went to “dark red” for 20 seconds and then went off. Any computer scientist will recognize this issue as a classic race condition and the easy solution is a semaphore/mutex — i.e. when we want to play a scene on the light-strip un-interrupted, we also set a virtual switch (“LED protection”) to “on”. And the night-light-rule checks if this LED-protection-switch is “off” before it fires.
We add a simple virtual switch to our “smarthome.items” file:
// Mutex for Ledi
Switch ledi_semaphore "Ledi Semaphore" <switch> {alexa="Switchable"}
(Yes, our light-strip is called “ledi” :)) So this virtual switch has to be added to Alexa and will be turned “on” by any Alexa-routine which should prevent the light-strip being triggered via the motion-sensor and the HABApp-rule below.
Since the rule is written in HABApp, we have the full power of python at our hands and we can simply compare timestamps:
def movement_detected(self, event: ValueUpdateEvent):
log.debug(f'{event.name} updated value: "{event.value}"')
log.debug(f"Last update of {self.movement_detector.name}: " +
f"{self.movement_detector.last_update}")
log.debug(f"Last change of {self.movement_detector.name}: " +
f"{self.movement_detector.last_change}")
log.debug(f"Mutex state: '{self.mutex.get_value()}', movement state: \
'{self.movement_detector.get_value()}'")
if self.mutex.is_off() and self.movement_detector.is_on():
log.debug("Potentially, we switch on the night-light...")
now = datetime.datetime.now().time() # ignore date -- only keep time
# the rule should only be active in the night... between 21 and 7 o'clock
morning_time = datetime.time(7,0,0,0)
bed_time = datetime.time(21,0,0,0)
if now > bed_time or now < morning_time:
log.debug("Movement detected -- commanding alexa.")
self.alexa_routine.oh_send_command("bewegungssensor routine bett")
else:
log.debug(f"Movement detected, but time now \
({now}) is outside 21--7 (nighttime) where rule should fire.")
Pre-Alarm Sunrise
Via the echo-control-binding we can get the next alarm (channel “nextAlarm”), so we just add a new item:
[smarthome.items]
DateTime Echo_Bedroom_NextAlarm "Next alarm" (gAlexaEchosIn) {channel="amazonechocontrol:echo:MyEchoAccount:echo_dot_bedroom:nextAlarm"}
The HABApp-rule is really simple: we get the time of the next alarm from Alexa via the Echo-control-binding, and a few minutes earlier, we start an Alexa-routine that switches the LED-strip into “sunrise” mode (not shown)
from HABApp.core.events import ValueUpdateEvent
from HABApp.core.events import ValueUpdateEventFilter
import logging
import datetime
log = logging.getLogger("MyRuleLogger")
class PreAlarmLight(HABApp.Rule):
def __init__(self):
super().__init__()
self.next_alarm = DatetimeItem.get_item("Echo_Bedroom_NextAlarm")
self.next_alarm.listen_event(self.alarm_set, ValueUpdateEventFilter())
self.alexa_routine = StringItem.get_item("Echo_Bedroom_StartRoutine")
def alarm_set(self, event: ValueUpdateEvent):
log.debug(f"{event.name} updated value: '{event.value}'")
time_of_alarm = self.next_alarm.get_value()
time_of_LED = time_of_alarm - datetime.timedelta(minutes=5)
self.run.at(time_of_LED, self.switch_pre_alarm_LED)
def switch_pre_alarm_LED(self):
log.debug(f"switching LED...")
self.alexa_routine.oh_send_command("weckervorbeleuchtung")
PreAlarmLight()
Result
Sorry for the blurry picture — it is dark in the room:) .. and note that in reality the red-light at 1% is fairly dim — it does not disturb your sleep.