Seite 1 von 1

Openhab3-Rule: Problem mit Map of Timers

Verfasst: 5. Dez 2021 12:20
von hermann59
Hallo zusammen,
ich habe eine Rule geschrieben, die verwendet werden soll, um zeitverzögert Benachrichtigungen nach Statusänderungen beliebiger Items zu verschicken. Hierzu wird für jedes getriggerte Item ein Timer angelegt, welcher in einer Map<String,Timer> gespeichert wird. Die Map-Einträge werden verwendet, um die Timer abbrechen zu können, wenn sich der Status des Items vor Ablauf des Timers wieder ändert.

Die Timer werden auch erfolgreich angelegt und zeitverzögert ausgeführt. Mein Problem ist jetzt, dass das Speichern der Timer in der Map nicht funktioniert und damit ein Timer nie abgebrochen werden kann. Hat irgendjemand eine Idee, warum das Speichern in der Map nicht funktioniert?

Hier die Regel:

Code: Alles auswählen

//
// Benachrichtigung auf das Smartphone aller in der cloud registrierten Benutzer,
// wenn ein Fenster zu lange offen steht.
//

import org.openhab.core.model.script.ScriptServiceUtil
import java.util.Map

val logger = "notification.rules"

val notificationConf =
	newHashMap(
		"Badfenster_State" -> (
			newHashMap(
				"trigger"        -> "OPEN",
				"maxOpenMinutes" -> "15",
				"timerMsg"       -> "Das Badfenster ist seit %d Minuten offen",
				"triggerLog"     -> "Badfenster wurde geöffnet",
				"nonTriggerLog"  -> "Badfenster wurde geschlossen"
			)
		),
		"BuerofensterLinks_State" -> (
			newHashMap(
				"trigger"        -> "OPEN",
				"maxOpenMinutes" -> "1",
				"timerMsg"       -> "Das linke Bürofenster ist seit %d Minuten offen",
				"triggerLog"     -> "linkes Bürofenster wurde geöffnet",
				"nonTriggerLog"  -> "linkes Bürofenster wurde geschlossen"
			)
		)
	)

var Map<String, Timer> timers = newHashMap
	
rule "Benachrichtigung"
when
	Item Badfenster_State changed or
	Item BuerofensterLinks_State changed
then
	logInfo(logger, "rule for " + triggeringItemName + " called");
	
    var item = ScriptServiceUtil.getItemRegistry.getItem(triggeringItemName);
	if (item===null) {
		throw new Exception("item " + triggeringItemName + " does not exist");
	}
	logInfo(logger, "state = " + item.state);
	
	var conf = notificationConf.get(triggeringItemName);
	
	var trigger = conf.get("trigger");
	logInfo(logger, "trigger=" + trigger);
	
	var maxOpenMinutes = Integer::parseInt(conf.get("maxOpenMinutes"));
	logInfo(logger, "maxOpenMinutes=" + maxOpenMinutes);
	
	var timerMsg = conf.get("timerMsg");
	logInfo(logger, "timerMsg=" + timerMsg);
	
	var triggerLog = conf.get("triggerLog");
	logInfo(logger, "triggerLog=" + triggerLog);
	
	var nonTriggerLog = conf.get("nonTriggerLog");
	logInfo(logger, "nonTriggerLog=" + nonTriggerLog);

	// einen eventuell laufenden timer abbrechen
	var timer = timers.get("triggeringItemName");
	logInfo(logger, "timer=" + timer);
	
    timer?.cancel();

    if (item.state == trigger) {
		logInfo(logger, triggerLog);
		
		// aktuelle Uhrzeit beim Öffnen in Millisekunden
		var openTime = (new java.util.Date()).getTime();
		
		logInfo(logger, "creating timer");
		timers.put(triggeringItemName, createTimer(now.plusMinutes(maxOpenMinutes),
			[|
				// aktuelle Uhrzeit beim Start des timers
				var curTime = (new java.util.Date()).getTime();
				
				// Anzahl Minuten seit dem Öffnen des Fensters
				var openDuration = ((curTime - openTime) / 60000);
				
				// auszugebende Meldung
				var msg = String::format(timerMsg, openDuration);
				
				// ... ins log schreiben
				logInfo(logger, msg);
				
				// ... auf die Smartphones senden
				sendBroadcastNotification(msg);
            ]
		));
		logInfo(logger, "stored timer: " + timers.get("triggeringItemName"));
    }
	else {
		logInfo(logger, nonTriggerLog);
	}
end	
Und hier die zugehörige LOG-Ausgabe:

Code: Alles auswählen

2021-12-05 12:00:39.086 [INFO ] [core.model.script.notification.rules] - rule for BuerofensterLinks_State called
2021-12-05 12:00:39.093 [INFO ] [core.model.script.notification.rules] - state = OPEN
2021-12-05 12:00:39.100 [INFO ] [core.model.script.notification.rules] - trigger=OPEN
2021-12-05 12:00:39.106 [INFO ] [core.model.script.notification.rules] - maxOpenMinutes=1
2021-12-05 12:00:39.110 [INFO ] [core.model.script.notification.rules] - timerMsg=Das linke Bürofenster ist seit %d Minuten offen
2021-12-05 12:00:39.115 [INFO ] [core.model.script.notification.rules] - triggerLog=linkes Bürofenster wurde geöffnet
2021-12-05 12:00:39.120 [INFO ] [core.model.script.notification.rules] - nonTriggerLog=linkes Bürofenster wurde geschlossen
2021-12-05 12:00:39.125 [INFO ] [core.model.script.notification.rules] - timer=null
2021-12-05 12:00:39.129 [INFO ] [core.model.script.notification.rules] - linkes Bürofenster wurde geöffnet
2021-12-05 12:00:39.134 [INFO ] [core.model.script.notification.rules] - creating timer
2021-12-05 12:00:39.147 [INFO ] [core.model.script.notification.rules] - stored timer: null
Der Timer wird zwischen den Meldungen

Code: Alles auswählen

creating timer
und

Code: Alles auswählen

stored timer: null
erzeugt und in der Map abgelegt. Wie man im log sieht, steht dort aber dann nichts. Nichtsdestotrotz wird der Timer erzeugt, da die Meldung auf dem Smartphone kommt.

Hat irgendjemand eine Idee, was ich falsch mache?

Re: Openhab3-Rule: Problem mit Map of Timers

Verfasst: 5. Dez 2021 13:41
von hermann59
Ich habe jetzt das Problem auf folgenden Sachverhalt reduziert:

Die Map wird vor allen Regeln angelegt mit:

Code: Alles auswählen

var HashMap<String, Timer> notificationTimers = newHashMap()
Der Timer wird erstellt, in der Map abgelegt und anschließend zu Testzwecken wieder aus der Map abgefragt:

Code: Alles auswählen

		var Timer newNotificationTimer = createTimer(now.plusMinutes(maxOpenMinutes), [|
				// aktuelle Uhrzeit beim Start des timers
				var curTime = (new java.util.Date()).getTime();
				
				// Anzahl Minuten seit dem Öffnen des Fensters
				var openDuration = ((curTime - openTime) / 60000);
				
				// auszugebende Meldung
				var msg = String::format(timerMsg, openDuration);
				
				// ... ins log schreiben
				logInfo(logger, msg);
				
				// ... auf die Smartphones senden
				sendBroadcastNotification(msg);
            ]
		)

		logInfo(logger, "newNotificationTimer: " + newNotificationTimer)
		notificationTimers.put(triggeringItemName, newNotificationTimer)
		var Timer storedNotificationTimer = notificationTimers.get("triggeringItemName")
		logInfo(logger, "storedNotificationTimer: " + storedNotificationTimer)
Im Log sieht man, dass der Timer zwar korrekt angelegt wird, aber entweder funktioniert das Speichern in der Map nicht oder das Auslesen:

Code: Alles auswählen

2021-12-05 13:31:57.591 [INFO ] [core.model.script.notification.rules] - newNotificationTimer: org.openhab.core.model.script.internal.actions.TimerImpl@4c9bf0
2021-12-05 13:31:57.595 [INFO ] [core.model.script.notification.rules] - storedNotificationTimer: null
Stimmt irgend etwas mit dem put oder get auf die Map nicht?

Re: Openhab3-Rule: Problem mit Map of Timers

Verfasst: 5. Dez 2021 13:48
von hermann59
Problem gelöst.
Es darf natürlich nicht

Code: Alles auswählen

var Timer storedNotificationTimer = notificationTimers.get("triggeringItemName")
heißen sondern

Code: Alles auswählen

var Timer storedNotificationTimer = notificationTimers.get(triggeringItemName)