Seite 1 von 1

Timer in Regel wird nicht zurückgesetzt

Verfasst: 5. Mai 2024 15:53
von Chaosmax
Openhab 4.0.2

Bei der folgenden Regel wird der Timer nicht zurückgesetzt und ich bekomme nach Ablauf der 60 min eine Nachricht. Auch wenn das Item wieder auf "ON" steht. Leider finde ich den Fehler nicht.

Code: Alles auswählen

var Timer Licht4_Timer = null

rule "Nachricht wenn Licht im Haus 4 offline"

when 
     Item Schildkroeten_Licht4_Online changed
then   
  if (Schildkroeten_Licht4_Online != ON) {
    if (Licht4_Timer !== null) {
        Licht4_Timer.cancel()
        Licht4_Timer = null 
    }
     Licht4_Timer = createTimer(now.plusMinutes(60), [|
            {
         val telegramAction = getActions("telegram","telegram:telegramBot:Telegram_Bot")
         telegramAction.sendTelegram("Licht im Schildkrötenhaus 4 ist Offline")
           }
        ])
  }
  else if (Schildkroeten_Licht4_Online==ON)
  {
     if (Licht4_Timer !== null){
    Licht4_Timer.cancel()
    Licht4_Timer = null
     }
  }
end

Re: Timer in Regel wird nicht zurückgesetzt

Verfasst: 5. Mai 2024 22:48
von udo1toni
Ja, die Rule hat Fehler :) Korrekt musst Du den Itemnamen mit .state ergänzen, um den Status zu erhalten, also so:

Code: Alles auswählen

if(Schildkroeten_Licht4_Online.state != ON)
Nun gibt es aber keine Garantie, dass der Status des Items zur Laufzeit der Rule noch identisch mit dem Status ist, der zum Start der Rule geführt hat (auch wenn das fast immer der Fall sein wird).
Besser ist es, nach dem neuen Status zu fragen, dazu gibt es die implizite Variable newState.
Außerdem hast Du unnötig doppelten Code in der Rule, sowie gänzlich unnötigen Code.
Sauber sieht es so aus:

Code: Alles auswählen

var Timer Licht4_Timer = null

rule "Nachricht wenn Licht im Haus 4 offline"
when
    Item Schildkroeten_Licht4_Online changed
then
    Licht4_Timer?.cancel
    if(newState != ON)
         Licht4_Timer = createTimer(now.plusMinutes(60), [|
             val telegramAction = getActions("telegram","telegram:telegramBot:Telegram_Bot")
             telegramAction.sendTelegram("Licht im Schildkrötenhaus 4 ist seit einer Stunde Offline")
        ])
end
Die Schreibweise mit dem Fragezeichen

Code: Alles auswählen

Licht4_Timer?.cancel
ist gleichbedeutend mit

Code: Alles auswählen

if(Licht4_Timer !== null) Licht4_Timer.cancel
Der Timer wird also gestoppt, falls er existiert. Eigentlich: Falls ein Zeiger auf einen Timer existiert, wird dieser aus dem Scheduler gelöscht, unabhängig davon, ob er existiert, noch auf die Ausführung wartet oder schon abgelaufen ist. Die cancel-Funktion wirft aber nur einen Fehler, wenn sie mit null aufgerufen wird, ansonsten wird z.B. bei einem bereits abgelaufenen Timer das Fehlen des Timers stillschweigend ignoriert. Das ist auch der Grund, warum man die Variable nicht explizit auf null setzen muss, nur beim Initialisieren (var Timer ... = null) ist das wichtig.
Da der Timer so oder so gestoppt werden muss, kann man das auch genauso gut zu Beginn des Codes erledigen und anschließend nur für den Fall, dass das Item nicht den Zustand ON hat den Timer erneut anlegen.

Re: Timer in Regel wird nicht zurückgesetzt

Verfasst: 6. Mai 2024 19:08
von Chaosmax
Super. Vielen Dank für die Hilfe. Werde ich morgen mal testen.

Re: Timer in Regel wird nicht zurückgesetzt

Verfasst: 8. Mai 2024 07:12
von Chaosmax
kurze Nachfrage

Code: Alles auswählen

Licht4_Timer?.cancel
oder

Code: Alles auswählen

Licht4_Timer?.cancel()
oder sind die Klammern egal?

Re: Timer in Regel wird nicht zurückgesetzt

Verfasst: 8. Mai 2024 16:09
von udo1toni
Die Klammern brauchst Du nicht.

Re: Timer in Regel wird nicht zurückgesetzt

Verfasst: 8. Mai 2024 21:43
von Chaosmax
Danke.