Rule triggered by cron is running only for 12-18 hours

Hello,
I have a cron triggered rule which should start once per hour through a time cron trigger to control my heating system over the whole week with start/restart and stop times.
Every 12 to 18 Hours…this depends on what ever, it seems that openhab stops triggering the rule.

My rule:

//Komfort = 1
//Standby = 2
//Nacht = 3
//Frost = 4

rule "Steuerung - prüfen"
when 
      Time cron "0 0 0/1 1/1 * ? *"
then
      
    var VarHeizEinMo         = (HeizEinMo.state as DecimalType).intValue     
    var VarHeizWiedereinMo   = (HeizWiedereinMo.state as DecimalType).intValue
    var VarHeizAusMo         = (HeizAusMo.state as DecimalType).intValue 
    var VarHeizEinDi         = (HeizEinDi.state as DecimalType).intValue 
    var VarHeizWiedereinDi   = (HeizWiedereinDi.state as DecimalType).intValue 
    var VarHeizAusDi         = (HeizAusDi.state as DecimalType).intValue 
    var VarHeizEinMi         = (HeizEinMi.state as DecimalType).intValue 
    var VarHeizWiedereinMi   = (HeizWiedereinMi.state as DecimalType).intValue 
    var VarHeizAusMi         = (HeizAusMi.state as DecimalType).intValue 
    var VarHeizEinDo         = (HeizEinDo.state as DecimalType).intValue 
    var VarHeizWiedereinDo   = (HeizWiedereinDo.state as DecimalType).intValue 
    var VarHeizAusDo         = (HeizAusDo.state as DecimalType).intValue 
    var VarHeizEinFr         = (HeizEinFr.state as DecimalType).intValue 
    var VarHeizWiedereinFr   = (HeizWiedereinFr.state as DecimalType).intValue 
    var VarHeizAusFr         = (HeizAusFr.state as DecimalType).intValue 
    var VarHeizEinSa         = (HeizEinSa.state as DecimalType).intValue 
    var VarHeizWiedereinSa   = (HeizWiedereinSa.state as DecimalType).intValue 
    var VarHeizAusSa         = (HeizAusSa.state as DecimalType).intValue 
    var VarHeizEinSo         = (HeizEinSo.state as DecimalType).intValue 
    var VarHeizWiedereinSo   = (HeizWiedereinSo.state as DecimalType).intValue 
    var VarHeizAusSo         = (HeizAusSo.state as DecimalType).intValue 
    
    sendTelegram("johannes","Heizungprogramm Prüfung läuft")
    logInfo("rules","Heizungprogramm Prüfung läuft")

    //Montag
    if (now.getDayOfWeek.intValue == 1) {
        if ((now.getHourOfDay.intValue == VarHeizEinMo) || (now.getHourOfDay.intValue == VarHeizWiedereinMo)) {
        
            //Heizung in Komfort (=1) schalten und Standby (=2)
            sendCommand(Heizung_KanalA_Betriebsart, 1)  //Wohnzimmer in Komfort mit Küche/Flur gekoppelt
            Thread::sleep(500)
            sendCommand(Heizung_KanalB_Betriebsart, 1)  //Küche in Komfort
            Thread::sleep(500)
            sendCommand(Heizung_KanalC_Betriebsart, 1)  //Flur EG/GaesteWC in Komfort
            Thread::sleep(500)
            sendCommand(Heizung_KanalD_Betriebsart, 1)  //Kinderzimmer in Komfort
            Thread::sleep(500)
            sendCommand(Heizung_KanalE_Betriebsart, 2)  //Schlafzimmer in Standby
            Thread::sleep(500)
            sendCommand(Heizung_KanalF_Betriebsart, 2)  //Badezimmer in Standby
            Thread::sleep(500)
            sendCommand(Heizung_KanalG_Betriebsart, 2)  //Speicher in Standby
            sendTelegram("johannes","Heizung eingeschaltet über Heizprogramm!")
            logInfo("rules","Heizung eingeschaltet über Heizprogramm!")
            }

        else if (now.getHourOfDay.intValue == VarHeizAusMo) {
            //Heizung in Nacht schalten
            sendCommand(Heizung_KanalA_Betriebsart, 3)  //Wohnzimmer in Nacht mit Küche/Flur gekoppelt
            Thread::sleep(500)
            sendCommand(Heizung_KanalB_Betriebsart, 3)  //Küche in Nacht
            Thread::sleep(500)
            sendCommand(Heizung_KanalC_Betriebsart, 3)  //Flur EG/GaesteWC in Nacht
            Thread::sleep(500)
            sendCommand(Heizung_KanalD_Betriebsart, 3)  //Kinderzimmer in Nacht
            Thread::sleep(500)
            sendCommand(Heizung_KanalE_Betriebsart, 3)  //Schlafzimmer in Nacht
            Thread::sleep(500)
            sendCommand(Heizung_KanalF_Betriebsart, 3)  //Badezimmer in Nacht
            Thread::sleep(500)
            sendCommand(Heizung_KanalG_Betriebsart, 3)  //Speicher in Nacht
            sendTelegram("johannes","Heizung ausgeschaltet (Nacht) über Heizprogramm!")
            logInfo("rules","Heizung ausgeschaltet (Nacht) über Heizprogramm!")
            }
        else {
            logInfo("rules","Heizprogramm keine Übereinstimmung!") 
            //sendTelegram("johannes","Heizungsprogramm Fehler, keine Übereinstimmung!")
        }
    }
    //Dienstag
    else if (now.getDayOfWeek.intValue == 2) {
        if ((now.getHourOfDay.intValue == VarHeizEinDi) || (now.getHourOfDay.intValue == VarHeizWiedereinDi)) {
        
            //Heizung in Komfort (=1) schalten und Standby (=2)
            sendCommand(Heizung_KanalA_Betriebsart, 1)  //Wohnzimmer in Komfort mit Küche/Flur gekoppelt
            Thread::sleep(500)
            sendCommand(Heizung_KanalB_Betriebsart, 1)  //Küche in Komfort
            Thread::sleep(500)
            sendCommand(Heizung_KanalC_Betriebsart, 1)  //Flur EG/GaesteWC in Komfort
            Thread::sleep(500)
            sendCommand(Heizung_KanalD_Betriebsart, 1)  //Kinderzimmer in Komfort
            Thread::sleep(500)
            sendCommand(Heizung_KanalE_Betriebsart, 2)  //Schlafzimmer in Standby
            Thread::sleep(500)
            sendCommand(Heizung_KanalF_Betriebsart, 2)  //Badezimmer in Standby
            Thread::sleep(500)
            sendCommand(Heizung_KanalG_Betriebsart, 2)  //Speicher in Standby
            sendTelegram("johannes","Heizung eingeschaltet über Heizprogramm!")
            logInfo("rules","Heizung eingeschaltet über Heizprogramm!")
            }

        else if (now.getHourOfDay.intValue == VarHeizAusDi) {
           //Heizung in Nacht schalten
            sendCommand(Heizung_KanalA_Betriebsart, 3)  //Wohnzimmer in Nacht mit Küche/Flur gekoppelt
            Thread::sleep(500)
            sendCommand(Heizung_KanalB_Betriebsart, 3)  //Küche in Nacht
            Thread::sleep(500)
            sendCommand(Heizung_KanalC_Betriebsart, 3)  //Flur EG/GaesteWC in Nacht
            Thread::sleep(500)
            sendCommand(Heizung_KanalD_Betriebsart, 3)  //Kinderzimmer in Nacht
            Thread::sleep(500)
            sendCommand(Heizung_KanalE_Betriebsart, 3)  //Schlafzimmer in Nacht
            Thread::sleep(500)
            sendCommand(Heizung_KanalF_Betriebsart, 3)  //Badezimmer in Nacht
            Thread::sleep(500)
            sendCommand(Heizung_KanalG_Betriebsart, 3)  //Speicher in Nacht
            sendTelegram("johannes","Heizung ausgeschaltet (Nacht) über Heizprogramm!")
            logInfo("rules","Heizung ausgeschaltet (Nacht) über Heizprogramm!")
            }
        else {
            logInfo("rules","Heizprogramm keine Übereinstimmung!") 
            //sendTelegram("johannes","Heizungsprogramm Fehler, keine Übereinstimmung!")
        }
    }
    //Mittwoch
    else if (now.getDayOfWeek.intValue == 3) {
        if ((now.getHourOfDay.intValue == VarHeizEinMi) || (now.getHourOfDay.intValue == VarHeizWiedereinMi)) {
        
            //Heizung in Komfort (=1) schalten und Standby (=2)
            sendCommand(Heizung_KanalA_Betriebsart, 1)  //Wohnzimmer in Komfort mit Küche/Flur gekoppelt
            Thread::sleep(500)
            sendCommand(Heizung_KanalB_Betriebsart, 1)  //Küche in Komfort
            Thread::sleep(500)
            sendCommand(Heizung_KanalC_Betriebsart, 1)  //Flur EG/GaesteWC in Komfort
            Thread::sleep(500)
            sendCommand(Heizung_KanalD_Betriebsart, 1)  //Kinderzimmer in Komfort
            Thread::sleep(500)
            sendCommand(Heizung_KanalE_Betriebsart, 2)  //Schlafzimmer in Standby
            Thread::sleep(500)
            sendCommand(Heizung_KanalF_Betriebsart, 2)  //Badezimmer in Standby
            Thread::sleep(500)
            sendCommand(Heizung_KanalG_Betriebsart, 2)  //Speicher in Standby
            sendTelegram("johannes","Heizung eingeschaltet über Heizprogramm!")
            logInfo("rules","Heizung eingeschaltet über Heizprogramm!")
            }

        else if (now.getHourOfDay.intValue == VarHeizAusMi) {
            //Heizung in Nacht schalten
            sendCommand(Heizung_KanalA_Betriebsart, 3)  //Wohnzimmer in Nacht mit Küche/Flur gekoppelt
            Thread::sleep(500)
            sendCommand(Heizung_KanalB_Betriebsart, 3)  //Küche in Nacht
            Thread::sleep(500)
            sendCommand(Heizung_KanalC_Betriebsart, 3)  //Flur EG/GaesteWC in Nacht
            Thread::sleep(500)
            sendCommand(Heizung_KanalD_Betriebsart, 3)  //Kinderzimmer in Nacht
            Thread::sleep(500)
            sendCommand(Heizung_KanalE_Betriebsart, 3)  //Schlafzimmer in Nacht
            Thread::sleep(500)
            sendCommand(Heizung_KanalF_Betriebsart, 3)  //Badezimmer in Nacht
            Thread::sleep(500)
            sendCommand(Heizung_KanalG_Betriebsart, 3)  //Speicher in Nacht
            sendTelegram("johannes","Heizung ausgeschaltet (Nacht) über Heizprogramm!")
            logInfo("rules","Heizung ausgeschaltet (Nacht) über Heizprogramm!")
            }
        else {
            logInfo("rules","Heizprogramm keine Übereinstimmung!")
            //sendTelegram("johannes","Heizungsprogramm Fehler, keine Übereinstimmung!")
            }
    }
    //Donnerstag
    else if (now.getDayOfWeek.intValue == 4) {
        if ((now.getHourOfDay.intValue == VarHeizEinDo) || (now.getHourOfDay.intValue == VarHeizWiedereinDo)) {
        
            //Heizung in Komfort (=1) schalten und Standby (=2)
            sendCommand(Heizung_KanalA_Betriebsart, 1)  //Wohnzimmer in Komfort mit Küche/Flur gekoppelt
            Thread::sleep(500)
            sendCommand(Heizung_KanalB_Betriebsart, 1)  //Küche in Komfort
            Thread::sleep(500)
            sendCommand(Heizung_KanalC_Betriebsart, 1)  //Flur EG/GaesteWC in Komfort
            Thread::sleep(500)
            sendCommand(Heizung_KanalD_Betriebsart, 1)  //Kinderzimmer in Komfort
            Thread::sleep(500)
            sendCommand(Heizung_KanalE_Betriebsart, 2)  //Schlafzimmer in Standby
            Thread::sleep(500)
            sendCommand(Heizung_KanalF_Betriebsart, 2)  //Badezimmer in Standby
            Thread::sleep(500)
            sendCommand(Heizung_KanalG_Betriebsart, 2)  //Speicher in Standby
            sendTelegram("johannes","Heizung eingeschaltet über Heizprogramm!")
            logInfo("rules","Heizung eingeschaltet über Heizprogramm!")
            }

        else if (now.getHourOfDay.intValue == VarHeizAusDo) {
            //Heizung in Nacht schalten
            sendCommand(Heizung_KanalA_Betriebsart, 3)  //Wohnzimmer in Nacht mit Küche/Flur gekoppelt
            Thread::sleep(500)
            sendCommand(Heizung_KanalB_Betriebsart, 3)  //Küche in Nacht
            Thread::sleep(500)
            sendCommand(Heizung_KanalC_Betriebsart, 3)  //Flur EG/GaesteWC in Nacht
            Thread::sleep(500)
            sendCommand(Heizung_KanalD_Betriebsart, 3)  //Kinderzimmer in Nacht
            Thread::sleep(500)
            sendCommand(Heizung_KanalE_Betriebsart, 3)  //Schlafzimmer in Nacht
            Thread::sleep(500)
            sendCommand(Heizung_KanalF_Betriebsart, 3)  //Badezimmer in Nacht
            Thread::sleep(500)
            sendCommand(Heizung_KanalG_Betriebsart, 3)  //Speicher in Nacht
            sendTelegram("johannes","Heizung ausgeschaltet (Nacht) über Heizprogramm!")
            logInfo("rules","Heizung ausgeschaltet (Nacht) über Heizprogramm!")
            }
        else {
            logInfo("rules","Heizprogramm keine Übereinstimmung!") 
            //sendTelegram("johannes","Heizungsprogramm Fehler, keine Übereinstimmung!")
            }
    }
    //Freitag
    else if (now.getDayOfWeek.intValue == 5) {
        if ((now.getHourOfDay.intValue == VarHeizEinFr) || (now.getHourOfDay.intValue == VarHeizWiedereinFr)) {
        
            //Heizung in Komfort (=1) schalten und Standby (=2)
            sendCommand(Heizung_KanalA_Betriebsart, 1)  //Wohnzimmer in Komfort mit Küche/Flur gekoppelt
            Thread::sleep(500)
            sendCommand(Heizung_KanalB_Betriebsart, 1)  //Küche in Komfort
            Thread::sleep(500)
            sendCommand(Heizung_KanalC_Betriebsart, 1)  //Flur EG/GaesteWC in Komfort
            Thread::sleep(500)
            sendCommand(Heizung_KanalD_Betriebsart, 1)  //Kinderzimmer in Komfort
            Thread::sleep(500)
            sendCommand(Heizung_KanalE_Betriebsart, 2)  //Schlafzimmer in Standby
            Thread::sleep(500)
            sendCommand(Heizung_KanalF_Betriebsart, 2)  //Badezimmer in Standby
            Thread::sleep(500)
            sendCommand(Heizung_KanalG_Betriebsart, 2)  //Speicher in Standby
            sendTelegram("johannes","Heizung eingeschaltet über Heizprogramm!")
            logInfo("rules","Heizung eingeschaltet über Heizprogramm!")
            }

        else if (now.getHourOfDay.intValue == VarHeizAusFr) {
            //Heizung in Nacht schalten
            sendCommand(Heizung_KanalA_Betriebsart, 3)  //Wohnzimmer in Nacht mit Küche/Flur gekoppelt
            Thread::sleep(500)
            sendCommand(Heizung_KanalB_Betriebsart, 3)  //Küche in Nacht
            Thread::sleep(500)
            sendCommand(Heizung_KanalC_Betriebsart, 3)  //Flur EG/GaesteWC in Nacht
            Thread::sleep(500)
            sendCommand(Heizung_KanalD_Betriebsart, 3)  //Kinderzimmer in Nacht
            Thread::sleep(500)
            sendCommand(Heizung_KanalE_Betriebsart, 3)  //Schlafzimmer in Nacht
            Thread::sleep(500)
            sendCommand(Heizung_KanalF_Betriebsart, 3)  //Badezimmer in Nacht
            Thread::sleep(500)
            sendCommand(Heizung_KanalG_Betriebsart, 3)  //Speicher in Nacht
            sendTelegram("johannes","Heizung ausgeschaltet (Nacht) über Heizprogramm!")
            logInfo("rules","Heizung ausgeschaltet (Nacht) über Heizprogramm!")
            }
        else {
            logInfo("rules","Heizprogramm keine Übereinstimmung!")
            //sendTelegram("johannes","Heizungsprogramm Fehler, keine Übereinstimmung!")
            
            }
    }
    //Samstag
    else if (now.getDayOfWeek.intValue == 6) {
        if ((now.getHourOfDay.intValue == VarHeizEinSa) || (now.getHourOfDay.intValue == VarHeizWiedereinSa)) {
        
            //Heizung in Komfort (=1) schalten und Standby (=2)
            sendCommand(Heizung_KanalA_Betriebsart, 1)  //Wohnzimmer in Komfort mit Küche/Flur gekoppelt
            Thread::sleep(500)
            sendCommand(Heizung_KanalB_Betriebsart, 1)  //Küche in Komfort
            Thread::sleep(500)
            sendCommand(Heizung_KanalC_Betriebsart, 1)  //Flur EG/GaesteWC in Komfort
            Thread::sleep(500)
            sendCommand(Heizung_KanalD_Betriebsart, 1)  //Kinderzimmer in Komfort
            Thread::sleep(500)
            sendCommand(Heizung_KanalE_Betriebsart, 2)  //Schlafzimmer in Standby
            Thread::sleep(500)
            sendCommand(Heizung_KanalF_Betriebsart, 2)  //Badezimmer in Standby
            Thread::sleep(500)
            sendCommand(Heizung_KanalG_Betriebsart, 2)  //Speicher in Standby
            sendTelegram("johannes","Heizung eingeschaltet über Heizprogramm!")
            logInfo("rules","Heizung eingeschaltet über Heizprogramm!")
            }

        else if (now.getHourOfDay.intValue == VarHeizAusSa) {
            //Heizung in Nacht schalten
            sendCommand(Heizung_KanalA_Betriebsart, 3)  //Wohnzimmer in Nacht mit Küche/Flur gekoppelt
            Thread::sleep(500)
            sendCommand(Heizung_KanalB_Betriebsart, 3)  //Küche in Nacht
            Thread::sleep(500)
            sendCommand(Heizung_KanalC_Betriebsart, 3)  //Flur EG/GaesteWC in Nacht
            Thread::sleep(500)
            sendCommand(Heizung_KanalD_Betriebsart, 3)  //Kinderzimmer in Nacht
            Thread::sleep(500)
            sendCommand(Heizung_KanalE_Betriebsart, 3)  //Schlafzimmer in Nacht
            Thread::sleep(500)
            sendCommand(Heizung_KanalF_Betriebsart, 3)  //Badezimmer in Nacht
            Thread::sleep(500)
            sendCommand(Heizung_KanalG_Betriebsart, 3)  //Speicher in Nacht
            sendTelegram("johannes","Heizung ausgeschaltet (Nacht) über Heizprogramm!")
            logInfo("rules","Heizung ausgeschaltet (Nacht) über Heizprogramm!")
            }
        else {
            logInfo("rules","Heizprogramm keine Übereinstimmung!")
            //sendTelegram("johannes","Heizungsprogramm Fehler, keine Übereinstimmung!")
            }
    }
    //Sonntag
    else if (now.getDayOfWeek.intValue ==7) {
        if ((now.getHourOfDay.intValue == VarHeizEinSo) || (now.getHourOfDay.intValue == VarHeizWiedereinSo)) {
        
            //Heizung in Komfort (=1) schalten und Standby (=2)
            sendCommand(Heizung_KanalA_Betriebsart, 1)  //Wohnzimmer in Komfort mit Küche/Flur gekoppelt
            Thread::sleep(500)
            sendCommand(Heizung_KanalB_Betriebsart, 1)  //Küche in Komfort
            Thread::sleep(500)
            sendCommand(Heizung_KanalC_Betriebsart, 1)  //Flur EG/GaesteWC in Komfort
            Thread::sleep(500)
            sendCommand(Heizung_KanalD_Betriebsart, 1)  //Kinderzimmer in Komfort
            Thread::sleep(500)
            sendCommand(Heizung_KanalE_Betriebsart, 2)  //Schlafzimmer in Standby
            Thread::sleep(500)
            sendCommand(Heizung_KanalF_Betriebsart, 2)  //Badezimmer in Standby
            Thread::sleep(500)
            sendCommand(Heizung_KanalG_Betriebsart, 2)  //Speicher in Standby
            sendTelegram("johannes","Heizung eingeschaltet über Heizprogramm!")
            logInfo("rules","Heizung eingeschaltet über Heizprogramm!")
            }


        else if (now.getHourOfDay.intValue == VarHeizAusSo) {
            //Heizung in Nacht schalten
            sendCommand(Heizung_KanalA_Betriebsart, 3)  //Wohnzimmer in Nacht mit Küche/Flur gekoppelt
            Thread::sleep(500)
            sendCommand(Heizung_KanalB_Betriebsart, 3)  //Küche in Nacht
            Thread::sleep(500)
            sendCommand(Heizung_KanalC_Betriebsart, 3)  //Flur EG/GaesteWC in Nacht
            Thread::sleep(500)
            sendCommand(Heizung_KanalD_Betriebsart, 3)  //Kinderzimmer in Nacht
            Thread::sleep(500)
            sendCommand(Heizung_KanalE_Betriebsart, 3)  //Schlafzimmer in Nacht
            Thread::sleep(500)
            sendCommand(Heizung_KanalF_Betriebsart, 3)  //Badezimmer in Nacht
            Thread::sleep(500)
            sendCommand(Heizung_KanalG_Betriebsart, 3)  //Speicher in Nacht
            sendTelegram("johannes","Heizung ausgeschaltet (Nacht) über Heizprogramm!")
            logInfo("rules","Heizung ausgeschaltet (Nacht) über Heizprogramm!")
            }
        else {
            logInfo("rules","Heizprogramm keine Übereinstimmung!")
            //sendTelegram("johannes","Heizungsprogramm Fehler, keine Übereinstimmung!")
            }
    }    

end

I don’t know what is the problem why openhab stopps triggering the rule. In the logs there is nothing to see. It seems that at some point for openhab this rule doesn’t exist. To start the execution again, I have to edit the rule and than openhab reload the rule and every thing starts from the beginning:-)

Any help/ideas appreciated.

Thank you!

Maybe a problem with the cron statement. If i understand it right your rule should run every hour every day. So you could replace the 0/1 and 1/1 by a *

Maybe that helps

The cron expression stood out to me too, but if it works a few times, it should keep going. However, you might want to try offsetting the time so that the rule does not run right on the hour. Maybe you have some other cron jobs that could run concurrently? There are only 2 threads in the cron thread pool, so things might get locked up if they are all used up when the rule is to trigger. Do your other cron rules stop running too, when this one stops? A log entry at the end of the rule could help determine if maybe the rule never makes it to the end. What binding are you using for the Heizung_KanalX_Betriebsart devices?

The sleeps are also concerning. You could try using timers instead eliminate the possibility of using up RuleEngine threads. One of these DPs might help… https://community.openhab.org/search?q=design%20pattern%20timer.

I’m not familiar with the sendTelegram action, but IIRC, others have reported rules hanging do to using it. I could be completely remembering this wrong.

Thank you, I will give it a try.

No

KNX2 Binding

Thank you for your help.

The sleeps and sendTelegram also stand out to me. It would only require two calls to sendTelegram to hang before you run out of cron threads and all your cron triggered Rules stop running.

As Scott suggests, add some logging to make sure that your Rule is running to completion each and every time it gets triggered.

See Design Pattern: Looping Timers for how to deal with the Thread::sleeps using Timers and see Design Pattern: How to Structure a Rule for how to reduce this Rule down to just a dozen or so lines of code. Shorter Rules are easier to read, usually easier to understand, and easier to maintain.

Other general advice, avoid converting Numbers to primitive ints and always call ItemName.sendCommand(cmd) instead of using the sendCommand Action if you know the Item to call up front.

I don’t speak German so it is hard to really figure out what is going on here so I may have something off. I’m just typing this in, there are likely bugs.

import org.eclipse.smarthome.model.script.ScriptServiceUtil // to access Items by name

// Define constants to make Rules more self explanatory
val KOMFORT = 1
val STANDBY = 2
val NACHT = 3
val FRONT = 4

var Timer heizungTimer = null

rule "Steuerung - prüfen"
when
    Time cron "25 0 * ? * * *"
then
    // 1. Always execute the Rule logic

    // 2. Calculate what to do

    val dayNum = now.getDayofWeek
    val hourNum = now.getHourOfDay
    var dayStr = ""
    switch(dayNum) {
        case 0: dayStr = "So"
        case 1: dayStr = "Mo"
        case 2: dayStr = "Di"
        case 3: dayStr = "Mi"
        case 4: dayStr = "Do"
        case 5: dayStr = "Fr"
        case 6: dayStr = "Sa"
    } 

    // Get the Ein, Wiederin, and Aus Items for the current day
    val ein       = ScriptServiceUtil.getItemRegistry.getItem("HeitzEin"+dayStr).state as Number
    val widererin = ScriptServiceUtil.getItemRegistry.getItem("HeitzWiederein"+dayStr).state as Number
    val aus       =  ScriptServiceUtil.getItemRegistry.getItem("HeitzAus"+dayStr).state as number

    var timeCondition = "Unknown"
    if(hourNum == ein || hourNum == wiederein) timeCondition ="Ein or Wiederein"
    else if(hourNum == aus) timeCondition = "Aus"

    // Get the the values to send to 
    var valueOne = -1 // Heizung_KanalA_Betriebsart through Heizung_KanalD_Betriebsart
    var valueTwo = -1 // Heizung_KanalE_Betriebsart through Heizung_KanalG_Betriebsart

    if(timeCondition == "Ein or Wiederein"){ 
        valueOne = KOMFORT
        valueTwo = STANDBY
    }
    else if(timeCondition == "Aus") {
        valueOne = NACHT
        valueTwo = NACHT
    }

    // Determine the message
    var msg = ""
    if(valueOne == -1 || valueTwo == -1) msg = "Heizprogramm keine Übereinstimmung!"
    else  msg = "Heizung " + (if(timeCondition == "Ein or Wiederein") "eingeschaltet " else "augeschaltet (Nacht) ") + "über Heizprogramm!"
        

    // 3. Do it
    sendTelegram("johannes","Heizungprogramm Prüfung läuft")
    logInfo("rules","Heizungprogramm Prüfung läuft")
    
    // If we don't have valueOne or valueTwo log message and return
    if(valueOne == -1 || valueTwo == -1) {
        logInfo("rules", msg) // Error message?
        return;
    }

    // Loop through A to G and send the appropriate command
    var char kanal = 'A' // primitive char is a number
    heizungTimer = createTimer(now, [ |
        sendCommand("Heizung_Kanal"+kanal+"_Betriebsart", if(kanal < 'E') valueOne else valueTwo)
        kanal = kanal + 1

        // wait if we haven't reached the final letter and run the Timer again
        if(kanal <= 'G') HeizungTimer.reschedule(now.plusMillis(500))

        // We are done, send the telegram and log the message
        else {
            sendTelegram("johannes", msg)
            logInfo("rules", msg)
        }
    ])
end

The above is meant primarily for inspiration. I can’t guarantee it works or does what you want. It should do what your current Rule does however. I like to leave before and after like examples around the forum though to help encourage users to discover and find a way to avoid lots and lots of duplicate code.

We have gone from 354 lines of code down to 85 lines of code, over a 65% reduction.

Thank your Rich for your work. The rule looks great.
I will give it a try! Hope I understand all the new stuff right:-).

My rule is compared to yours very primitive.

@rich Learned something new. Thank You

import org.eclipse.smarthome.model.script.ScriptServiceUtil // to access Items by name

Maybe that makes some group member filter something else constructs easier

5iver discovered it. I’ve just been spreading the word. I’ve updated the Associated Items DP with this option awhile back.