TOD - tying to Alarm SLEEP + time

I have the following Time of Day rule, generously started by @rlkoshak with his design patterns ( Design Pattern: Time Of Day )

rule "Time of Day"
when
    System started or
    Item g_temperature_average received update or
    Time cron "0 0 5 * * ? *" or
    Time cron "0 0 8 * * ? *" or
    Time cron "0 0 16 * * ? *" or
    Time cron "0 0 22 * * ? *"
then
    // get the DateTime for the start of the time periods
    //5am
    val morningStart = now.withTimeAtStartOfDay.plusDays(1).minusHours(24-(heating_morning_time_on.state as Number).intValue)
    //8am
    val dayStart = now.withTimeAtStartOfDay.plusDays(1).minusHours(24-(heating_morning_time_off.state as Number).intValue)
    //4pm
    //val eveningStart = now.withTimeAtStartOfDay.plusDays(1).minusHours(24-16)
    val eveningStart = new DateTime(Evening_Time.state.toString())
    //10pm
    val lateEvening = now.withTimeAtStartOfDay.plusDays(1).minusHours(24-(heating_daytime_time_off.state as Number).intValue)

    val nightStart = now.withTimeAtStartOfDay.plusDays(1).minusHours(24-(lamp_lighting_time_off.state as Number).intValue)
   //Debug entries
    logInfo("Time of day",String::format("Now: %s Morning Start %s day Start %s evening start %s late evening: %s night start %s, alarm state %s",
                    now,morningStart,dayStart,eveningStart,lateEvening,nightStart,alarm_hb_state.state))

    var newToD = "UNKNOWN"
    switch now {
        case now.isAfter(morningStart) && now.isBefore(dayStart)         : newToD = "MORNING"
        case now.isAfter(dayStart) && now.isBefore(eveningStart)         : newToD = "DAY"
        case now.isAfter(eveningStart) && now.isBefore(lateEvening)      : newToD = "EVENING"
        case now.isAfter(lateEvening) && now.isBefore(nightStart)        : newToD = "LATEEVENING"
        case now.isAfter(nightStart)                                     : newToD = "PRENIGHT"
        case now.isAfter(nightStart) && (alarm_hb_state.state == "SLEEP"
                                || alarm_hb_state.state == "AWAY")       : newToD = "NIGHT"

    }

    if(heating_timeofday.state.toString != newToD)
    {
        heating_timeofday.postUpdate(newToD)
        //Debug entries
        //logInfo("Time of day","Setting Time of Day: " + newToD)
        //Notify_Info.postUpdate(String::format("Time of day changed: " + newToD))
    }
end

In this, LATEEVENING is 22:00, NIGHT is 23:00. I’ve just added the code for the “PRENIGHT” and the and alarm_hb_state.state == SLEEP/AWAY in order to try and change the hard 23:00 night time (which triggers some downstairs lights to turn off), to be based on the alarm being set to SLEEP mode (AWAY is obviously we’re not there at all so also turn it off at 23:00 or after.

But this doesn’t seem to trigger.

Currently this TOD entry is used for heating (morning to day start) and turning off any manual heating at LATEEVENING. I’m in two minds if I should just create a whole new tod rule just for lighting, would make debugging easier I guess. But given all the times are the same, is seems like that would create redundant code.

The problem is the less restrictive case now.isAfter(nightStart) appears before the more restrictive one that includes the alarm_hb_state.

The switch statement will execute the first case statement that returns true and since now.isAfter(nightStart) will be true for both cases, the first one is the only one that will ever execute.

So I should remove PRENIGHT as useless, and LATEEVENING should extend to 23:00 + SLEEP/AWAY when it then becomes NIGHT

No sure why i added that PRENIGHT, perhaps cos the first night i ran this NIGHT didn’t trigger.