Joda vs. Java time

Einrichtung der openHAB Umgebung und allgemeine Konfigurationsthemen.

Moderatoren: seppy, udo1toni

Benutzeravatar
OliverCJ
Beiträge: 405
Registriert: 29. Aug 2017 12:41
Answers: 3
Wohnort: Bergisch Gladbach

Joda vs. Java time

Beitrag von OliverCJ »

Guten Abend zusammen,

nachdem ich nun einige Monate OH3 parallel zu OH2.5 genutzt habe um mich erstmal vertraut zu machen, habe ich heute den Pi mit OH2.5 abgeschaltet... Im Grunde funktioniert jetzt alles so wie vorher. Nur mit der Umstellung auf JavaTime hapert es noch in einer rule...

Okay, so ganz richtig lief die eh nie, aber ich habe zumindest Werte bekommen... Zur Zeit bekomme ich gar nichts :-(

Hier mal die alte rule unter 2.5:

Code: Alles auswählen

import org.joda.time.LocalTime
import java.util.ArrayList
import java.util.Map
import java.util.HashMap
import java.util.concurrent.locks.ReentrantLock
import java.util.concurrent.locks.Lock

var Map <String, Double> FuelPricesMap = new HashMap<String, Double>()    // Stationsnamen und Preise für den Kraftstoff
var ArrayList <StringItem> FuelPriceItems =  new ArrayList<StringItem>()

val telegramAction = getActions("telegram","telegram:telegramBot:openHAB")


rule "Benzinpreise Info"
when
	Item FuelPricesMap received update
then
	val LocalTime afternoon = new LocalTime(15, 0)  //Jeden Nachmittag um 15:00 Uhr
  	val LocalTime evening = new LocalTime(19, 0)    //Jeden Abend um 19:00 Uhr
  	
	if (now.toLocalTime().isAfter(afternoon) && now.toLocalTime().isBefore(evening)) {   //zwischen 15 und 19 Uhr
		telegramAction.sendTelegram("Günstigster Sprit: " + TK_Tankstelle_1)               //Erste Tankstelle im Array = günstigste Tankstelle
	}
		else if (TK_Tankstelle_1.state.toString.contains ("0,00")) {
    	postUpdate(TK_Tankstelle_1, "Geschlossen")
	   	}
end


rule "Benzinpreise Update"
when
	Item TK_Stat1_E10 received update or
	Item TK_Stat2_E10 received update or
    Item TK_Stat3_E10 received update or
    Item TK_Stat4_E10 received update
then
    var Lock lock = new ReentrantLock()
	
	var i = 0
	
	lock.lock()

	logInfo("Tankerkönig", "Benzinpreise -> Update der Werte")
    
	// Zuweisung der Display Items in das Array
    FuelPriceItems.add(0, TK_Tankstelle_1)
    FuelPriceItems.add(1, TK_Tankstelle_2)

	// aktuelle Preise aus den Items in die Map übernehmen    
    FuelPricesMap.put("HEM", (TK_Stat1_E10.state as DecimalType).doubleValue())
    FuelPricesMap.put("ESSO", (TK_Stat2_E10.state as DecimalType).doubleValue())
    FuelPricesMap.put("ARAL", (TK_Stat3_E10.state as DecimalType).doubleValue())
	FuelPricesMap.put("ESSO Köln", (TK_Stat4_E10.state as DecimalType).doubleValue())

	// Map nach Preisen sortieren und die Werte dann dem Anzeigearray zuweisen
        for (PriceEntry : FuelPricesMap.entrySet.sortBy[value]) {
            FuelPriceItems.get(i).postUpdate(String::format("%s: %.3f €", PriceEntry.getKey(), PriceEntry.getValue()))
             i = i+1
        }
	lock.unlock()
end
Ich habe bisher folgende Änderungen vorgenommen:

Code: Alles auswählen

import java.time.LocalDateTime
import java.util.ArrayList
import java.util.Map
import java.util.HashMap
import java.util.concurrent.locks.ReentrantLock
import java.util.concurrent.locks.Lock

var Map <String, Double> FuelPricesMap = new HashMap<String, Double>()    // Stationsnamen und Preise für den Kraftstoff
var ArrayList <StringItem> FuelPriceItems =  new ArrayList<StringItem>()


rule "Benzinpreise Info"
when
	Item FuelPricesMap received update
then
	val telegramAction = getActions("telegram","telegram:telegramBot:openHAB")
	val LocalDateTime afternoon = new LocalDateTime(15, 0)  //Jeden Nachmittag um 15:00 Uhr
  	val LocalDateTime evening = new LocalDateTime(19, 0)    //Jeden Abend um 19:00 Uhr
  	
	if (now.toLocalDateTime().isAfter(afternoon) && now.toLocalDateTime().isBefore(evening)) {   //zwischen 15 und 19 Uhr
		telegramAction.sendTelegram("Günstigster Sprit: " + TK_Tankstelle_1)               //Erste Tankstelle im Array = günstigste Tankstelle
	}
		else if (TK_Tankstelle_1.state.toString.contains ("0,00")) {
    	postUpdate(TK_Tankstelle_1, "Geschlossen")
	   	}
end


rule "Benzinpreise Update"
when
	Item TK_Stat1_E10 received update or
	Item TK_Stat2_E10 received update or
    Item TK_Stat3_E10 received update or
    Item TK_Stat4_E10 received update
then
    var Lock lock = new ReentrantLock()
	
	var i = 0
	
	lock.lock()

	logInfo("Tankerkönig", "Benzinpreise -> Update der Werte")
    
	// Zuweisung der Display Items in das Array
    FuelPriceItems.add(0, TK_Tankstelle_1)
    FuelPriceItems.add(1, TK_Tankstelle_2)

	// aktuelle Preise aus den Items in die Map übernehmen    
    FuelPricesMap.put("HEM", (TK_Stat1_E10.state as DecimalType).doubleValue())
    FuelPricesMap.put("ESSO", (TK_Stat2_E10.state as DecimalType).doubleValue())
    FuelPricesMap.put("ARAL", (TK_Stat3_E10.state as DecimalType).doubleValue())
	FuelPricesMap.put("ESSO Köln", (TK_Stat4_E10.state as DecimalType).doubleValue())

	// Map nach Preisen sortieren und die Werte dann dem Anzeigearray zuweisen
        for (PriceEntry : FuelPricesMap.entrySet.sortBy[value]) {
            FuelPriceItems.get(i).postUpdate(String::format("%s: %.3f €", PriceEntry.getKey(), PriceEntry.getValue()))
             i = i+1
        }
	lock.unlock()
end
Mir ist klar, dass das mit den globalen Variablen nicht mehr funktioniert. Aber da bekomme ich gar keinen Fehler. Den Fehler bekomme ich in der ersten rule bei LocalTime bzw jetzt immer noch bei LocalDateTime:
tankerkoenig.JPG
Irgendwas scheine ich hier (https://community.openhab.org/t/datetim ... 3-x/107197) noch falsch zu verstehen...
Kann mir jemand auf die Sprünge helfen?

Danke und Gute Nacht
Oliver
Du hast keine ausreichende Berechtigung, um die Dateianhänge dieses Beitrags anzusehen.

_______________________________________________
Homematic IP Komponenten an CCU 3 (wächst stetig)
Innogy Smarthome System (verabschiedet sich langsam)
Philips Hue Beleuchtung
Fritz!Box
VU+ Solo SAT-Receiver
2 Squeezeboxen
Denon Heos System

Benutzeravatar
udo1toni
Beiträge: 15265
Registriert: 11. Apr 2018 18:05
Answers: 245
Wohnort: Darmstadt

Re: Joda vs. Java time

Beitrag von udo1toni »

OliverCJ hat geschrieben: 21. Aug 2021 22:36 Mir ist klar, dass das mit den globalen Variablen nicht mehr funktioniert.
Was soll denn da nicht mehr funktionieren? Globale Variablen funktionieren wunderbar. Allerdings nur innerhalb der *.rules Dateien. Wenn Du eine Rule (egal welches Progammiermodell) über die UI erzeugst, stehen keine globalen Variablen zur Verfügung. Du kannst höchstens den Inhalt von Variablen aus dem vorherigen Lauf der selben Rule "retten", was aber nur einen Teil der benötigten Funktionalität abdeckt - Stichwort Timer.
OliverCJ hat geschrieben: 21. Aug 2021 22:36 Den Fehler bekomme ich in der ersten rule bei LocalTime bzw jetzt immer noch bei LocalDateTime:
Wenn, dann müsstest Du vermutlich eher sowas verwenden:

Code: Alles auswählen

val afternoon = new ZonedDateTime().withHour(15).withMinute(0).withSecond(0),withNano(0)
Eventuell wäre eine Variante auch diese hier:

Code: Alles auswählen

val afternoon = ZonedDateTime.now().with(LocalTime.MIN).withHour(15)
Nimm den aktuellen Zeitpunkt, aber den frühestmöglichen Zeitpunkt dieses Tages, und rechne 15 Stunden drauf. Damit ist dann ebenfalls sichergestellt, dass auch die Sekunden auf 0 stehen.

Aber es wäre ohnehin viel einfacher, die Stunde zu prüfen:

Code: Alles auswählen

if(now.getHour > 14 && now.getHour < 19) {   //zwischen 15 und 19 Uhr
Problematisch wird das nur, wenn die Zeiten nicht mehr auf der vollen Stunde liegen. Da hilft dann get:

Code: Alles auswählen

if(now.get(SECOND_OF_DAY) >= 15*60*60 + 0*60 + 0 && now.get(SECOND_OF_DAY) < 19*60*60 + 0*60 + 0) {   //zwischen 15 und 19 Uhr
Zu beachten ist der Unterschied zwischen getHour > 14 und get(SECOND_OF_DAY) >= 15*60*60. Im ersten Fall wird ja nur die Stunde geprüft, um 14:59:59 ist die Stunde gleich 14 und um 15:00:00 ist sie gleich 15, während im zweiten Fall ja auf die Sekunde geschaut wird. Deshalb muss auch auf >= getestet werden.
openHAB4.3.5 stable in einem Debian-Container (bookworm) (Proxmox 8.4.1, LXC), mit openHABian eingerichtet

Benutzeravatar
OliverCJ
Beiträge: 405
Registriert: 29. Aug 2017 12:41
Answers: 3
Wohnort: Bergisch Gladbach

Re: Joda vs. Java time

Beitrag von OliverCJ »

Hallo Udo,

ich hatte mehrfach gelesen, dass globale Variablen eben nicht mehr funktionieren. Vielleicht verwende ich auch den falschen Ausdruck. Ich meine die Variablen, die ich innerhalb der rules-Datei definiere, aber noch vor der ersten rule. Tatsächlich hatte ich damit nach der Umstellung Probleme, während es aber funktioniert, wenn ich die Definition innerhalb der rule vornehme...

Ist vielleicht nicht ganz das Gleiche, aber auch bei der Telegram-Action funktioniert folgende Definition NICHT mehr:

Code: Alles auswählen

val telegramAction = getActions("telegram","telegram:telegramBot:openHAB")

rule "Send telegram with question"
when
    Item gAnwesende changed from ON to OFF
then
    
    if (gLicht.state == ON) {
        telegramAction.sendTelegramQuery("Es ist keiner mehr zu Hause, aber es sind noch Lampen an. Möchtest Du sie ausschalten?", "Reply_Lights", "Ja", "Nein")
    }
end
Ich musste das so umstellen:

Code: Alles auswählen

rule "Send telegram with question"
when
    Item gAnwesende changed from ON to OFF
then
    val telegramAction = getActions("telegram","telegram:telegramBot:openHAB")
    if (gLicht.state == ON) {
        telegramAction.sendTelegramQuery("Es ist keiner mehr zu Hause, aber es sind noch Lampen an. Möchtest Du sie ausschalten?", "Reply_Lights", "Ja", "Nein")
    }
end
Aber egal, das soll hier ja gar nicht Thema sein... Vielen Dank auf jeden Fall für die Anregungen! Ich schau mir das morgen mal an. Ist nicht die wichtigste rule, da ich seit 1,5 Jahren eh kaum noch Auto fahre...

_______________________________________________
Homematic IP Komponenten an CCU 3 (wächst stetig)
Innogy Smarthome System (verabschiedet sich langsam)
Philips Hue Beleuchtung
Fritz!Box
VU+ Solo SAT-Receiver
2 Squeezeboxen
Denon Heos System

Benutzeravatar
udo1toni
Beiträge: 15265
Registriert: 11. Apr 2018 18:05
Answers: 245
Wohnort: Darmstadt

Re: Joda vs. Java time

Beitrag von udo1toni »

Nein, das ist schon korrekt, das sind globale Variablen (bzw. in diesem Fall eine globale Konstante). Das Problem ist an dieser Stelle aber, dass das Objekt eigentlich nicht als globales Objekt erlaubt ist. Unter OH2.5 hat das aber tatsächlich auch funktioniert.
Etwas wie

Code: Alles auswählen

var Timer tTimer = null

rule "Timer benutzen"
when
    Item bla changed
then
    if(tTimer !== null)
        return;
    tTimer = createTimer(now.plusSeconds(1), [ |
        tTimer = null
    ])
end
sollte aber funktionieren. Auch die Definition von gewöhnlichen globalen Konstanten sollte wie gewohnt arbeiten. Die action ist aber halt keine gewöhnliche Konstante :)
openHAB4.3.5 stable in einem Debian-Container (bookworm) (Proxmox 8.4.1, LXC), mit openHABian eingerichtet

klausO
Beiträge: 3
Registriert: 3. Nov 2021 17:15
Answers: 0

Re: Joda vs. Java time

Beitrag von klausO »

Hallo zusammen,
auch ich hadere mit der Umstellung der Zeitsyntax von Openhab2.5 auf Openhab3... ;-)
Da ich kein Programmierer sondern eher copyandpaster und auch nur beschränkt allgorithmisch denkfähig bin, bin ich natürlich immer auf der Suche nach Code-Schnipseln, die ich weitgehend verstehe und für meine Bedürfnisse abwandeln kann.
Bei mir geht es um eine Regel, die ab einer bestimmten "Dunkelheit" aber nur zwischen 14:30 Uhr und 23:40 Uhr in betimmten Zimmern das Licht einschaltet.
In Openhab2.5 war das einfach so zu lösen:

Code: Alles auswählen

if (now.isAfter(now.withTimeAtStartOfDay.plusHours(15).plusMinutes(0)) && now.isBefore(now.withTimeAtStartOfDay.plusHours(23).plusMinutes(40)))
Nachdem ich (fast) alle Beiträge zu dem Thema, sowohl hier als auch im englischsprachigen Forum gelesen hab, war ich sehr froh, hier die Zeile von udo1toni zu lesen:

Code: Alles auswählen

if(now.get(SECOND_OF_DAY) >= 15*60*60 + 0*60 + 0 && now.get(SECOND_OF_DAY) < 19*60*60 + 0*60 + 0) {   //zwischen 15 und 19 Uhr
Die hab ich dann so abgewandelt in meine Regel eingebaut:

Code: Alles auswählen

if ((WG_LA_automat_licht.state == ON && (now.get(SECOND_OF_DAY) >= 14*60*60 + 30*60 + 0 && now.get(SECOND_OF_DAY) < 23*60*60 + 30*60 + 0)) && ((GZ_BW_hell_devolo_node21.state < 45) || (AZ_BW_hell_node13_philio.state < 5)))
(ok - ich geb´s zu - ein ziemlicher Bedingungsschlauch.)
Wenn die Regel dann ausgeführt wird, sagt mir das Log allerdings:

Code: Alles auswählen

2021-11-03 19:25:06.918 [ERROR] [internal.handler.ScriptActionHandler] - Script execution of rule with UID 'licht_wenn_zu_dunkel_24-2' failed: The name 'SECOND_OF_DAY' cannot be resolved to an item or type; line 12, column 51, length 13 in licht_wenn_zu_dunkel_24
Ich wäre echt dankbar, wenn jemand ne Idee hätte, wie ich das korrekt hinbekomme und diese Baustelle zumachen könnte...;-)
Grüße
Klaus

Benutzeravatar
peter-pan
Beiträge: 2769
Registriert: 28. Nov 2018 12:03
Answers: 30
Wohnort: Schwäbisch Gmünd

Re: Joda vs. Java time

Beitrag von peter-pan »

klausO hat geschrieben: 5. Nov 2021 17:22 Ich wäre echt dankbar, wenn jemand ne Idee hätte,
....ein kleines Schnipselchen von mir:

Code: Alles auswählen

var vSecond = now.toLocalTime().toSecondOfDay()
logInfo("test","Sekunde: Es sind: {}", vSecond)
Log:

Code: Alles auswählen

2021-11-05 21:25:33.779 [INFO ] [org.openhab.core.model.script.test  ] - Sekunde: Es sind: 77133
Vielleicht geht es ja damit, indem du "now.get(SECOND_OF_DAY)" durch " now.toLocalTime().toSecondOfDay()" auswechselst.
Pi5/8GB(PiOS Lite 64-bit(bookworm)/SSD 120GB - OH4.3.5 openhabian

int5749
Beiträge: 1173
Registriert: 4. Nov 2019 22:08
Answers: 9

Re: Joda vs. Java time

Beitrag von int5749 »

peter-pan hat geschrieben: 5. Nov 2021 21:37 Vielleicht geht es ja damit, indem du "now.get(SECOND_OF_DAY)" durch " now.toLocalTime().toSecondOfDay()" auswechselst.
Welchen Zweck haben die Klammern??
Bei mir reicht ein

Code: Alles auswählen

now.toLocalTime.toSecondOfDay >= 30600
Viele Grüße
openHAB 4.1.0 Release mit openHABian in einem Debian Bookworm (LXC) unter Proxmox 8.1.3

Benutzeravatar
peter-pan
Beiträge: 2769
Registriert: 28. Nov 2018 12:03
Answers: 30
Wohnort: Schwäbisch Gmünd

Re: Joda vs. Java time

Beitrag von peter-pan »

int5749 hat geschrieben: 5. Nov 2021 23:58 Bei mir reicht ein
Das ist gut zu wissen.
Ich hab das mit den Klammern mal irgendwo in einem Java-Tutorial gefunden. Das ist wohl Standard-Syntax. Schaden kann's ja aber wohl nicht ;)
Pi5/8GB(PiOS Lite 64-bit(bookworm)/SSD 120GB - OH4.3.5 openhabian

klausO
Beiträge: 3
Registriert: 3. Nov 2021 17:15
Answers: 0

Re: Joda vs. Java time

Beitrag von klausO »

Hallo peter-pan und int5749,
vielen Dank für eure schnellen und guten Tipps/Schnipsel!!!
Ich hab es jetzt mit einer Kombination von euren und udos Schnipsel gelöst:

Code: Alles auswählen

(now.toLocalTime.toSecondOfDay >= 14*60*60 + 30*60 + 0 && now.toLocalTime.toSecondOfDay < 23*60*60 + 30*60 + 0))
In der Form sind die 14:30 Uhr und die 23:30 Uhr noch wenigstens halbwegs sichtbar und das Log schimpft nicht mehr... ;-)
btw. durch die oben beschriebene Abhängigkeit von der "Dunkelheit", ist der Zeitpunkt, wann das Licht eingeschaltet wird immer schön zufällig.
Was auch z.B. während eines Urlaubs Anwesenheit simuliert.
Leider ist der Ausschaltzeitpunkt immer 23:30 Uhr - wenn hier jemand eine Idee hätte, wie man das mit einer Art Zufallsgenerator plus-minus 30 Minuten einstellen könnte, wäre die Regel perfekt.
Jetzt freue ich mich aber erstmal über den komplett vollzogenen Umzug von 2.5 nach 3.2 - alles läuft wie vorher nur, wie ich finde, etwas stabiler!

Nochmals Danke für eure prompte Unterstützung!
Klaus

Benutzeravatar
peter-pan
Beiträge: 2769
Registriert: 28. Nov 2018 12:03
Answers: 30
Wohnort: Schwäbisch Gmünd

Re: Joda vs. Java time

Beitrag von peter-pan »

... und noch 2 Schnipsel:

Schnipsel 1:

Code: Alles auswählen

   val java.util.Random rand = new java.util.Random()
   var int vRandomNumber = rand.nextInt(60)
   logInfo("randomTest","Neuer Wert randomnumber: {} randomTime.", vRandomNumber )  
Schnipsel 2:

Code: Alles auswählen

   val vMin = -30
   val vMax = 30
   var vRandom = (Math::random * (vMax - vMin)).intValue + vMin
   logInfo("randomTest","Neuer Wert vRandom: {} randomTime.", vRandom)  
Mit beiden Schnipseln kannst du dir Zufallswerte generieren und die Variablen in deiner Rule einbauen. Ich weiss jetzt aber nicht, ob das mathematisch so alles korrekt ist ;) . Aber es scheint zu funktionieren. :lol: :lol:

Edit: Also anstelle von 30 * 60 + 0 kommt dann 30 * 60 + vRandom
oder anstelle von 30 * 60 + 0 kommt vRandomNumber * 60 + 0
Pi5/8GB(PiOS Lite 64-bit(bookworm)/SSD 120GB - OH4.3.5 openhabian

Antworten