Keith, a reader of this blog, had a rather interesting problem he was trying to solve, and as I was taking a look at it, I thought the solution could help many with how to break down a trickier problem into smaller bits.
What do we want to do?
Use a Hue Motion Sensor to detect motion and turn on lights if three conditionals are true
- There is an hour or less until sunrise, or the sun has already risen
- It is before midnight
- The brightness level in the room where the motion sensor is mounted is below a predetermined lux level (we’ll use 100 lux in the example, but this is completely up to you)
(In case you’re using an adblocker, please consider whitelisting this site. Any revenue from Google ads goes to the costs of running this site.)
The underpinning is of course a HomeKit Automation that runs every time the motion is detected. We then use a shortcut in that automation to get the logic working.
So how can we break down the problem into smaller bits? If we take a look at the three conditionals, we could solve one at a time and create a variable for each, where we store a number that can be used directly in an if-statement.
Conditional 1: There is an hour or less until sunrise, or the sun has already risen
In an earlier post, I explained how you can check if the sun has already risen using the Current Weather function. The logic for this problem is very similar, however, since we want to use an offset of one hour, we need to know how many minutes there are until the sunrise. Luckily, this is quite easy to do.
To get the time for the sunrise, we need to use the function Get Current Weather at Current Location. We then put Get Details of Weather Conditions after that and choose Sunrise Time as the detail we want.
Next, we’ll use the Get Time Between Dates function and use Current Date and Sunrise Time (this is a magic variable from earlier) as parameters and Minutes as the output. We’ll then save the minutes into a variable by using the action Set variable. Name the variable MinutesToSunrise so that it is easy to remember and set the input to Time Between Dates from earlier. This variable is all we need for the if-statement for the first conditional… if MinutesToSunrise is larger than 60 (minutes), it’s too early for the lights to be turned on.
Conditional 2: It is before midnight
When we use the function Get Current Weather, the time and date for the sunrise isn’t always for the current day. When I tested, I noticed that about half an hour after midnight, we are still getting the time and date of the sunrise for the day before (it seems to have updated before one o’clock at night). That means that just because the MinutesToSunrise is a negative number (meaning the sunrise has already happened), it doesn’t mean it’s not past midnight.
The good thing is we can use the day of month of the sunrise, and we are going to use that to see if the data is for yesterday instead of today (which can happen for almost an hour after midnight). We’ll save the day in the month from the sunrise as well as the day in the month for current time into variables. That way we can compare them, and if they don’t match, we know it is after midnight.
(Explanation: If it’s a half hour after midnight, but the Current Weather Sunrise data is still from the day before, the MinutesToSunrise will still be calculated from the last sunrise. This will get us a negative value. We don’t want to set a hardcoded time for when it should start looking for the next sunrise, since the time of sunrise varies a lot in different parts of the world and different times of year. However, if the day of the month of the current time and Current Weather Sunrise differs, we know that the first conditional will be true (MinutesToSunrise will be a negative number which is smaller than 60), and it’s past midnight since (else the two dates would be the same), and this is all we need for the second conditional.)
We start by creating the variable for the sunrise’s day of the month. Start with the Format Date action. When you select the date, choose Variables and then Sunrise Time. Next select Show More and set the Time Format to None and Date Format to Custom. Choose Format String and remove what is written in it and set it to the letter d (lower case). It’s important that it is in fact lower case, or you’ll get something completely different. This will give us the number for the day in the month.
Now add the Set Variable action and name the variable SunriseDay, and the input should be Formatted Date from above.
Now add another Format Date action. It will probably preselect a date for you which you need to delete. Select whatever it has set as default, press the little keyboard icon to the left and press the backspace key. Now select Variables, and from there Current Date. As with the earlier one, you want the Time Format to be set to None and Date Format to be set to Custom. Again, you need to edit the Format String so that it only contains the letter d (lower case).
Next add the Set Variable action and name the variable Today. The input should be Formatted Date from above (it’s probably preselected).
This is all we need for the second conditional.
Conditional 3: The brightness level in the room where the motion sensor is mounted is below a predetermined lux level
The Hue Motion Sensor is equipped with both a thermometer and a lux meter, and we’ll be able to use the built-in lux meter to get the brightness level of the room.
We start with the action Get the state of Home and choose the lux meter in the Motion sensor as the device. Use Current Light Level as the characteristic you want to query. This will get you the lux value of the room, but we want a number, so we have to use the Get Numbers from Input action. Choose Current Light Level from before as the input. We’ll then save that into a variable with the Set variable action. Name the variable LuxNow and set the input to Numbers from the last action.
We’ve now got the four variables we need for the conditionals for the logic to work. For the last part we’ll use three if-statements, the second nested inside the first and the third nested inside the second. In this case it doesn’t really matter in which order we check the conditionals (this isn’t always the case), but I think it’s more natural to check if the time is correct before checking the brightness in the room.
We’ll start with the first if-statement where we check if the variable MinutestoSunrise is less than or equal to 60. We can remove Otherwise and then add another if-statement that we drag in between the first If and End If.
In the second if-statement we set Today as the Input and Is as the condition. In the Text field we add the variable SunriseDay. (This will check if the day of the month of today is the same as the day of the month of the Sunrise date.) Again, we remove Otherwise.
We’ll now add the third if-statement, and we drag it below the second if-statement, but before the End Ifs. Here we choose LuxNow as the Input, select the conditional is less than, and set the lux number we want as the number. I’ll put 100. Once again, we remove Otherwise.
Lastly, we add a Control Home action, and drag it below the last if-statement, but before the first End If. Here we choose the lamp or lamps and set them to turn on.
I hope there are some ideas in this shortcut that you are able to use when solving other problems.