Jump to content

[Tutorial] Advanced home wake-up routine with Philips Hue and HC2


Recommended Posts

This is my first topic in a series of post I'm going to write about the advanced LUA scenes I wrote for my home automation project. My goal is not flipping a light scene with a phone but for 90% autonome home automation.

Besides posting LUA code I give you more insight why I came to this routine. It may help you with designing your own automation routines.

 

Disclaimer: I am not a professional programmer and I post the scenes as is. I have no time to make the LUA scenes generic like other great members do on this forum. I just post my LUA code to share knowlegde and inspire you to create awesome things!

 

Advanced home wake-up routine with Philips Hue and HC2

Applies to: Fibaro Home Center 2 and Philips HUE bridge.

 

GOALS

  • Use my Philips Hue led strips as a wake-up light.
  • Use 1 app to schedule the whole home wake-up routine.
  • Start the morning routine when walking downstairs (check motion).
  • Turn on the lights only when it’s dark (read lux).

 

In our bedroom we integrated a Philips Hue lightstrip in the ceiling and use this with the Philips Hue app as a wake-up light. It beautifully fakes a sunrise in our whole room. As we use the Hue app to set our wake-up alarm I use this app to trigger the Home Center to run a wake-up routine for the rest of the house.

 

TL;DR

  • Set recurring wake-up schedule in the Philips Hue app.
  • Home Center LUA scene 1 reads schedules at 04:00 with the keyword Wake in it.
  • If schedule is set for today and motion is detected at the hallway after the scheduled time (scene 2), run wake-up routine.

 

HOW I IMPLEMENTED IT

 

IN WORDS

Reading Hue schedules from the bridge cannot be done with the Fibaro Hue plug-in. Therefore I wrote a LUA scene to read the Hue schedules from the Hue bridge and run the wake-up routine at the schedules wake-up time. I achieved this with 2 LUA scenes:

 

  • Scene 1 runs every minute and polls the Hue bridge schedules at 04:00. If a wake-up is scheduled for today write the wake-up times to a global variable. Every minute it checks if there is a wake-up planned by reading the same global variable and if so it sets the WakeUpReady global variable to 1.
  • Scene 2 runs when motion detected by a Fibaro Motion Sensor. If it detects motion it checks if the global variable WakeUpReady is set to 1 and runs the wake-up routine.

 

SCENE 1 EXPLAINED

You can download the full LUA scenes at the bottom of this post. I only describe snippets of my code to make you understand what it does and show the challenges I ran into.

 

TAG YOUR HUE SCHEDULE WITH A WAKE-UP STRING IN IT!
To know which schedules are used for wake-up I set all those schedules with the Wake keyword in it. Like Wake-up weekday’s and Wake-up weekends. In the LUA scene I find these schedules with the code:

if name:find('Wake') and status == 'enabled' then ... end

RECURRING DAY’S ARE SAVED AS A BITMASK IN THE HUE BRIDGE
The Hue API states:

 

Quote

W[bbb]/T[hh]:[mm]:[ss]
Every day of the week given by bbb at given time

 

The Hue bridge saves the recurring day’s as a bitmask. You have to convert this bitmask to weekday’s. So you can check if the alarm is set for today. The first step is to convert decimal to a binary. I did this with the folowing LUA function:

function bin(dec)
    local result = ""
    repeat
        local divres = dec / 2
        local int, frac = math.modf(divres)
        dec = int
        result = math.ceil(frac) .. result
    until dec == 0
    local StrNumber
    StrNumber = string.format(result, "s")
    local nbZero
    nbZero = 8 - string.len(StrNumber)
    local Sresult
    Sresult = string.rep("0", nbZero)..StrNumber
    return Sresult
end

Then I have a binary representation of the scheduled weekday’s. For example:

mo tu we th fr sa su
 1  1  1  1  0  1  0

You see the alarm is set for monday, tuesday, wednesday, thursday and saturday. With this I can determine if the alarm is set for today:

 

if name:find('Wake') and status == 'enabled' then
  local huedays, huetime = string.match(timepattern, 'W(.*)/T(.*)')
  -- Hue starts at monday, LUA starts at sunday, so I have to fix this.
  local dayofweek = os.date("*t").wday-1
  if dayofweek == 0 then dayofweek = 7 end
  local scheduleddays = bin(huedays)
  -- dayofweek+1 because a week is 7 days and binary is 8 digits, so
  -- a have a pre 0
  local waketoday = string.sub(scheduleddays, dayofweek+1, dayofweek+1)
  if waketoday == '1' then
    wakeUpAlarms =  wakeUpAlarms .. huetime:sub(1, -4) .. '|'
  end
  ...
end

WRITE WAKE-UP TIME TO GLOBAL VARIABLE
If there is an alarm schedule for today write it to a global variable for later use:

if wakeUpAlarms ~= '' then
  fibaro:setGlobal("WakeUpTime", wakeUpAlarms:sub(1, -2)) -- remove last |
else
  -- If no schedules are set, write disabled to the global variable.
  fibaro:setGlobal("WakeUpTime", "disabled")
end

SET WAKEUPREADY GLOBAL VARIABLE FOR MOTION SENSOR LUA SCENE
The LUA scene runs every minute using the code:

setTimeout(tempFunc, 60*1000)

At 04:00 it checks the schedules in the Hue bridge, but every minute it checks the WakeUpTime global variable to set the wakeupReady global variable to 1. This variable triggers the second LUA scene used by the motion sensor.

local wakeupTime  = fibaro:getGlobal("WakeUpTime")
if wakeupTime ~= "disabled" then
  local waketimes = {}
  for match in (wakeupTime..'|'):gmatch("(.-)"..'|') do
    table.insert(waketimes, match);
  end
  for k, v in pairs(waketimes) do
    if os.date("%H:%M") == v then
      fibaro:setGlobal("WakeUpReady", 1)
      fibaro:debug("It's wake-up time! Set motion detector ready!")
    end
  end
end

SCENE 2 EXPLAINED (MOTION SENSOR PART)
With scene 1 I created a global variable setting to determine if the wake-up routine must run. Now I create a second scene to act if there is motion in our hallway.

 

CHECK FOR MOTION AND IF ALARM IS NOT ARMED
First I want to check if there is motion and if the alarm is not armed with the line:

if tonumber(fibaro:getValue(158, "value")) > 0 and tonumber(fibaro:getValue(158, "armed")) == 0 then
...

RUN WAKE-UP ROUTINE ONLY IF IT’S DARK OUTSIDE
The Philips Hue wake-up schedule runs always because our bedroom had curtains and the room is always dark. Downstairs I only want to run the wake-up routine when it’s dark outside. The wakeupReady global variable check’s if the routine needs to run when there is motion (set with scene 1). The line below gets the current lux reading from the Fibaro motion sensor: 

fibaro:getValue(160, "value")

If the illuminance is below 20 I want to turn on my lights.

if wakeupReady == "1" then
      fibaro:setGlobal("WakeUpReady", 0) -- Disable trigger for current wake-up time.
      -- check lux
      local currentLux = tonumber(fibaro:getValue(160, "value")) -- id 160 is sensors light device.
      -- If it's dark then start wake-up routine
      if currentLux < 20 then
        fibaro:debug("Illuminance measuring " .. currentLux .. " lx, starting wake-up routine.")
        fibaro:call(44, "setValue", "8") -- Spots keuken (8%)
        fibaro:call(29, "setValue", "5") -- Tafel eethoek (5%)
        fibaro:call(106 , "turnOn") -- Bolles (aan)
        fibaro:call(118 , "turnOn") -- Spot voordeur (aan)
        fibaro:call(156, "sendPush", "Started wake-up routine. Debug: " .. currentLux .. " lx")
      else
        fibaro:debug("Illuminance measuring " .. currentLux .. " lx, do nothing.")
      end
...

DOWNLOAD MY SCENES COMPLETE LUA CODE
You can download the full LUA scene code from GitHub:

 

 

You have to change the device id’s from my motion sensors in this scene to your own id’s!

And don't forget to set the scenes to run automatic in the Fibaro Home Center 2

Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...