HomeKit Automation Tips

Getting more out of your smart home devices

Building a shortcut using conditionals with sunrise minus one hour, time of day and room brightness

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

  1. There is an hour or less until sunrise, or the sun has already risen
  2. It is before midnight
  3. 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.)

Advertisements

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.)

Advertisements

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.

18 thoughts on “Building a shortcut using conditionals with sunrise minus one hour, time of day and room brightness”

  1. Hey Stefan,

    I’ve been reading this post and also the other post on conditional sunrise, but can’t seem to work this out. I also don’t understand why I can’t choose a certain hour to begin and sunrise to end, or vice versa with sunset.

    I want to have the light in our stairway to react as following:

    1) On from 8h till 21h at 100%, but not after sunrise. So if the sun rises that day at 7h, the light don’t come on.If it only rises at 9h, light will turn on from 8h till 9h.
    2) On from 21h till 23h at 50% (so we don’t wake the children with too mach light in the stairway)
    3) Off from 23h till 8h

    I can do option 2 and 3 from within the Hue app, but not 3. I prefer to get it to work within Homekit. Within homekit I can’t seem to get the lights not to go on between sunrise and sunset. (tried an automaization just for that, but that didn’t work)

    Is there a way to get this to work?

    Thanks!

    Dave

    1. Hi Dave,

      That’s an excellent question!

      I’m actually sitting and planning a post about the power of the Format Date function, which is really useful for solving your problem. By using the custom format (Hmm), and converting the time into a number, there are a lot of possibilities for conditionals. I’m going to give you a sneak peek to that with the solution to your problem. If you’ve got any questions about the shortcut, just ask away 😉

      Using both sunrise and sunset as conditionals

      1. Thanks Stefan,

        I just created the automation, I would’ve never figured it out myself. 😊 I think I’ve forgot one thing, I want the lights to turn off after 5 minutes. What do I need to add for this to work?

        Just tried it, when passing the sensor the lights turn on, since it’s only 15h here, I think I missed something… The lights shouldn’t be turning on now.

        Thanks!

        1. For turning the lights off, I would use this HomeKit automation shortcut: https://homekitautomationtips.com/how-to-use-a-motion-sensor-to-turn-on-and-off-your-lights-with-homekit/

          When you’re motion sensor has stopped seeing motion, it will trigger the Motion Sensor stops detecting motion event, which in turn will run the shortcut. It runs a loop checking if it still doesn’t see any motion. If it sees motion again, it will exit the shortcut, but if no motion has been detected after 90 seconds , it will turn off the lights. If you want it to run for 5 minutes, change the Repeat value to 100.

          If you want, I can send you an email to the address you registered with your comment, and you can email me back screenshots of your shortcut. It’s hard to debug it without being able to see it.

  2. Thanks Stefan, I had been looking at the other automation, but wasn’t sure how to include it here.

    Sure, sent me a mail. Really appreciate it!

    Thanks!

    Dave

  3. Hi Stefan,
    Thanks – It was actually an hour before Sunset rather than Sunrise that I was after but this is a great guide and it’s working perfectly for me after substituting sunrise for sunset 🙂

    It is a little slower to respond than the previous shortcut I used which was just looking at movement and light but I guess that’s to be expected as it’s doing a lot more with the various lookups.

    1. Ops, you’re absolutely correct. Sorry, I don’t understand how I mixed that up.

      I made a correct and slightly simpler version for you, that uses the same idea as the one I made for Dave. It might be a little bit faster, but what might take a little bit of time is when it queries the Weather data for the sunset time. Again, if you have any questions, just let me know 🙂 And sorry again for the mixup.

      Correction, shortcut using sunset

      1. OK, thank you for that, it’s very helpful and I’ll give it a try.

        You’ve set SunsetTimeOffset to Calculation Result with the number being 100. Is that 100 minutes before Sunset so for an hour, it would be 60?

        I’m wondering if I can implement this along with another time check so that there are two possible outcomes.. From one hour before Sunset until midnight, it runs one scene and then from midnight until an hour before Sunset, it runs another scene (effectively the same one but with dimmer lights). I think it would be more effective to run them both from one shortcut so it only does one ‘get current weather’.

        1. Actually, the 100 is an hour… Sunset is at 6:00 PM, the custom format date will give you the number 1800. If you subtract 100 from that, it becomes 1700… which is 17:00 or 5:00 PM… The problem with this system is that we can’t subtract or add anything less than an hour. (If sunset was at 6:45 PM, and we added 30 minutes, it would be 1845 + 30 = 1875… and that doesn’t translate well. If you really want the ability to add minutes, we would have to convert all time attributes to minutes only… so for instance 10:15 AM would be (10 * 60) + 15)

          Having two different outcomes is very simple… you just use an Otherwise on the outer if-statement.

          If TimeNow is between SunsetTimeOffset and 2359
          If LuxNow is less than or equal to 100
          Set Lamp to 100%
          End If
          Oterwise
          Set lamp to 50%
          End If

          If you want to, you can of course check the lux value after Otherwise with an if-statement.

          1. I’m using that second method and I changed the weather from “Current Location” to specifically be my house – I figured that if it didn’t need to do a GPS lookup, that might also speed things up.
            It does seem to react faster now.

          2. It’s all good – I’ve set up a second one from 00:01 to an hour after sunrise for the lights at a lower brightness using the same principles. I had to use just ‘1’ as the time because it wouldn’t accept leading zeros so I hope that’s going to be interpreted the same way..

            Is it possible to clone automations at all? I’ve got three more rooms with similar setups and it would make things a lot easier if I could clone what I’ve already got.

          3. As far as the shortcut is concerned, these are not time units, they are only numbers, so that’s why it doesn’t want leading zeros. So yes, 1 will work as 00:01.

            And no, cloning or copying shortcuts is not possible at the moment. For normal, non-HomeKit shortcuts, just running on your iPhone, you’re actually able to point from one to another shortcut, but that doesn’t work in HomeKit. I wish Apple would add this ability sooner rather than later.

  4. I’ve got all my shortcuts working now, from before sunset to midnight and then after midnight until after sunrise. They’re working well, thanks.

    One further question – What’s the benefit of using your method of determining the current light level, ie getting the numbers from current light level, setting a variable and checking that as opposed to simply using:

    IF [insert motion sensor name] [light level] is less than or equal to 10 lux

    Isn’t that taking three steps to achieve what can be checked in a single IF statement?

    1. Great that you’ve got them all working 🙂 I’m glad I could help.

      That’s actually a very good question you asked, and you’re correct. You could absolutely put it directly into the if-statement, and that works perfectly fine. However, there has been some bugs with doing that before. For instance, before the last update, there was a bug (I think it was introduced in iOS 14) that made it impossible to check brightness levels in if-statements… they result would always be false. But by actually taking the value, forcing it to become a number and putting it into a variable was a workaround for that bug. What was even more bizarre about that bug was that shortcuts created before iOS 14 ran fine, but when trying to create a new one, it wouldn’t work. So, converting these values into numbers and putting them into a variable is sort of a belt and suspenders kind of approach.

  5. I have an automation that I can’t seem to get running quite right, and recommendations would be helpful.

    I have a bedroom that all lights are HomeKit, and I have a LogiCircle 2 camera (HomeKit secure video) that also functions as a motion sensor, has lux sensor, and a presence sensor in the home app.

    My schedule is not consistent, so setting actions for a time of day trigger is not optimal.
    I have a bedtime scene that I run when I go to sleep, one light is at 1%.

    I would like to use the motion sensor to trigger all lights to on and 100% and white (circadian) if that one light is not at that 1%. I don’t want it to trigger the lights to full brightness when motion is detected while the bedtime scene is set. And bonus points if I can have the lights turn off when presence is not detected meaning I left the room (but not turn off the bedtime scene one light at 1% if that is already set to the bedtime scene, Im often still in this room so motion x timer would get old). Reason for motion to turn on vs presence is it reacts quicker when I walk in.

    I hope I explained that ok but in essence I want all sensors to do nothing if Bedtime scene is set. (which includes one light at 1% and a purple color.)
    Otherwise, use the motion sensor to turn on lights.
    Presence sensor, not detecting people, turn off lights.

    I’ve gotten close but it just doesn’t seem to be consistent, I think I’m missing something.

    1. Hi Mat,

      I started using “state” variables quite early with HomeKit by using smart plugs as variables. For instance, one of the smart plugs was a variable for sleeping, so if that was on, my shortcuts would take a specific path. As I started using more of them, I got a Raspberry Pi that I can use to create virtual switches that take on this job.

      However, since you’ve got a specific night light that is set to 1% when your bedtime “state” is active, we can use that as the conditional in the shortcuts. I’ll call this light NightLight in the shortcuts.

      I think you need to have two HomeKit automations converted into shortcuts.

      The first is when the LogiCircle 2 detects motion:

      If NightLight Brightness is 1%
      Exit shortcut with Result
      Otherwise
      Set all the lights to in the bedroom to 100% and white (Control Home action)
      End If

      And the second automation is when the LogiCircle 2 does not detect presence:

      If NightLight Brightness is 1%
      Turn off all lights but NightLight in the bedroom (Control Home action)
      Otherwise
      Turn of all lights in the bedroom (Control Home action)
      End If

      Would this work? Did I understand the brief correctly? 🙂

Leave a Comment

Your email address will not be published. Required fields are marked *