Writing a DAY/NIGHT rule using Astro

Running latest release, openhabian.

Trying to think through the logic of a value to indicate it light or dark outside.

I have the following thing:

astro:sun:myastrothing [ geolocation="my coords, my cords", interval=60 ] {
    Channels:
        Type rangeEvent : set#event [
            offset=-30
        ]
        Type rangeEvent : rise#event [
            offset=30
        ]
}

To confirm, the offset is applied to the set and rise, but if in an items file I define additional channels:

DateTime Day_Start "Day Start [%1$tH:%1$tM]" { channel="astro:sun:myastrothing:daylight#start" }

DateTime Day_End "Day End [%1$tH:%1$tM]" { channel="astro:sun:myastrothing:daylight#end" }

these don’t have an offset?

I believe the Astro thing updates at midnight??

Such that the following rule would work?

rule "Test Daylight"
when
    System started or
    Channel 'astro:sun:myastrothing:daylight#event' triggered START or
    Channel 'astro:sun:myastrothing:daylight#event' triggered END or
    Time cron "0 1 0 * * ? *"
then
    val day_start = new DateTime(Day_Start.state.toString).plusMinutes(-10)
    val day_end = new DateTime(Day_End.state.toString).plusMinutes(10)
    var drive_curr = "DARK"
    if (now.isAfter(day_start) && now.isBefore(day_end) ){
        drive_curr = "LIGHT"
    }
    DriveState.sendCommand(drive_curr)
end

Note: I’m reworking this because, after Jan. 1st the the previous code that works correctly for 6 months reversed DARK and LIGHT.

A really go way is the Design Pattern Time of Day. Just search for it in the forum

You can read about it here.

1 Like

So, nothing about this looks familiar? Good, I guess I’ve messed with the design pattern enough to make it unrecognizable and Rich won’t accuse me of plagiarism. :wink:

In fact, I have the design pattern in my rules…I think, with little or no changes. But, it does what it says. But, have have yet to get my driveway lights controlled correctly with the resulting vTimeOfDay value.

Additionally, if you look at the code above, I am using the astro daylight channel. (I don’t think I saw anything about astro daylight channel in the design pattern.)

The design pattern does not show the thing definition used, it does say the astro thing supports an offset. But the astro binding page shows examples of defining offsets on a per channel basis. So my question above is: does an offset defined in a thing file for a given channel offset channels NOT mentioned in the thing file?

It took me also a bit before I more or less understood how it works. I’ve setup mine using PaperUI, so I can’t show you my Thing file because I don’t have one.

A couple of things (no pun intended) first. In your Thing file, you have channels defined for the sunset (set#event) and sunrise (rise#event) events. However, in your items file you have defined two items, one for daylight start (daylight#start) and daylight end (daylight#end). You did not define an offset for daylight, so that is the reason why the items do not have an offset.

If you want to use daylight then you need to use two Things because you want to use two different offsets for the same group.

Type rangeEvent : daylight#event [
            offset=-30
        ]

Type rangeEvent : daylight#event [
            offset=30
        ]

In the above example there is no way openHAB can know which one to use when, so this will not work. Hence the need for two different Things, one for each daylight offset:

The myastrothing1.thing file for daylight start:

astro:sun:myastrothing1 [ geolocation="my coords, my cords", interval=60 ] {
    Channels:
        Type start : daylight#start [
            offset=30
        ]
        Type rangeEvent : daylight#event [
            offset=30
        ]
}

The myastrothing2.thing file for daylight end:

astro:sun:myastrothing2 [ geolocation="my coords, my cords", interval=60 ] {
    Channels:
        Type start : daylight#end [
            offset=-30
        ]
        Type rangeEvent : daylight#event [
            offset=-30
        ]
}

and the corresponding items file:

DateTime Day_Start "Day Start [%1$tH:%1$tM]" { channel="astro:sun:myastrothing1:daylight#start" }

DateTime Day_End "Day End [%1$tH:%1$tM]" { channel="astro:sun:myastrothing2:daylight#end" }
rule "Test Daylight"
when
    System started or
    Time cron "0 1 0 * * ? *"
then
    val day_start = new DateTime(Day_Start.state.toString).plusMinutes(-10)
    val day_end = new DateTime(Day_End.state.toString).plusMinutes(10)
    var drive_curr = "DARK"
    if (now.isAfter(day_start) && now.isBefore(day_end) ){
        drive_curr = "LIGHT"
    }
    DriveState.sendCommand(drive_curr)
end

I don’t think the above rule will do what you originally intended. You could try to trigger a rule when either Day_Start or Day_End is changed. That should happen when the Astro binding has done its calculation (at least that works in openHAB 1.x). Just make sure that neither of them is null or undefined when doing calculations with them.

rule "Test Daylight start"
when
    Channel 'astro:sun:myastrothing1:daylight#event' triggered START
then
    DriveState.sendCommand("LIGHT")
end
rule "Test Daylight end"
when
    Channel 'astro:sun:myastrothing2:daylight#event' triggered END
then
    DriveState.sendCommand("DARK")
end

If you want to use sunrise and sunset instead (which I now know you don’t but I’ll leave it for reference), then the following may work:

astro:sun:myastrothing [ geolocation="my coords, my cords", interval=60 ] {
    Channels:
        Type start : rise#start [
            offset=30
        ]
        Type start : set#start [
            offset=-30
        ]
        Type rangeEvent : rise#event [
            offset=30
        ]
        Type rangeEvent : set#event [
            offset=-30
        ]
}

and the corresponding items file:

DateTime Day_Start "Day Start [%1$tH:%1$tM]" { channel="astro:sun:myastrothing:rise#start" }

DateTime Day_End "Day End [%1$tH:%1$tM]" { channel="astro:sun:myastrothing:set#start" }

In PaperUI I cannot link an item to the rangeEvent channel, hence in my system I have my item connected to the Start Time channel. I have both the Start Time channel and the rangeEvent channel configured with the same offset. That way the linked item shows the correct time when the rangeEvent is triggered to close my rollershutters.

Unfortunately, the documentation does not show any complex examples, so if the above works then please let me know.

probably a question for a different thread but why not? If you want your lights to come on at sunset (or some offset from sunset) you trust the driveway lights rule with

Item vTimeOfDay changed to EVENING

of course using what ever state you have starting at that time.

If you don’t have a state starting at that time, add a new state.

A Design Pattern is not intended to be a compete and stand alone solution. The code in a DP is an example. You can trigger the Time of Day Rule with just about anything, moon phases, zodiac symbols, etc. The approach doesn’t care what generates the events. The key is you are giving the events a meaning and storing that meaning in the vTimeOfDay Item.

I think I even state in the DP that the same approach can be used for days (e. g. work day, holiday, etc). The only difference is the events that trigger the rule and the case statements in the the rule.