OH2.5 Rules - DateTime to String an Final concatenation

Hier bitte alles rein was Off-topic ist.

Moderatoren: Cyrelian, seppy

Antworten
summy
Beiträge: 3
Registriert: 29. Dez 2021 21:56

OH2.5 Rules - DateTime to String an Final concatenation

Beitrag von summy »

Hallo zusammen. Ich hoffe mir kann jemand bei meiner RULE in Openhab 2.5 helfen.
Ich hole mir über CalDev (google Calender) meine Urlaubsdaten und versuche diese mittels Start und Ende Datum einem anderen ITEM als String zu übergeben, damit ich an einer anderen Stelle damit weiterarbeiten kann.

Die Variable ModUrlaub_X_X bekomme ich gefüllt und kann darauf auch if abfragen durchführen. Das Ergebnis dann final in eine weitere Variable vom Typ String ModUrlaub_XFinal“ zu übergeben funktioniert dann nicht, weiß jemand wieso?

Code: Alles auswählen

rule "UrlaubAdding"

when 
Item CalDav_UrlaubDate_1 changed or System started or Time cron "0 0/2 * * * ?"  //every 2 Minutes
then

var String ModUrlaub_1_0 
var String ModUrlaub_1_1 
var String ModUrlaub_2_0 
var String ModUrlaub_2_1 
var String ModUrlaub_3_0 
var String ModUrlaub_3_1 
 
var String ModUrlaub_1Final = "-"
var String ModUrlaub_2Final = "-"
var String ModUrlaub_3Final = "-"


if (CalDav_UrlaubDate_1 === UNDEF || CalDav_UrlaubDate_1 === NULL) { ModUrlaub_1_0 = "-.-.-" } else { ModUrlaub_1_0 as CalDav_UrlaubDate_1.state.format("%1$td.%1$tm.%1$ty") }
if (CalDav_UrlaubDate_1_1 === UNDEF || CalDav_UrlaubDate_1_1 === NULL) { ModUrlaub_1_1 = "-.-.-" } else { ModUrlaub_1_1 as CalDav_UrlaubDate_1_1.state.format("%1$td.%1$tm.%1$ty") }
if (CalDav_UrlaubDate_2 === UNDEF || CalDav_UrlaubDate_2 === NULL) { ModUrlaub_2_0 = "-.-.-" } else { ModUrlaub_2_0 as CalDav_UrlaubDate_2.state.format("%1$td.%1$tm.%1$ty") }
if (CalDav_UrlaubDate_2_1 === UNDEF || CalDav_UrlaubDate_2_1 === NULL) { ModUrlaub_2_1 = "-.-.-" } else { ModUrlaub_2_1 as CalDav_UrlaubDate_2_1.state.format("%1$td.%1$tm.%1$ty") }
if (CalDav_UrlaubDate_3 === UNDEF || CalDav_UrlaubDate_3 === NULL) { ModUrlaub_3_0 = "-.-.-" } else { ModUrlaub_3_0 as CalDav_UrlaubDate_3.state.format("%1$td.%1$tm.%1$ty") }
if (CalDav_UrlaubDate_3_1 === UNDEF || CalDav_UrlaubDate_3_1 === NULL) { ModUrlaub_3_1 = "-.-.-" } else { ModUrlaub_3_1 as CalDav_UrlaubDate_3_1.state.format("%1$td.%1$tm.%1$ty") }
 


 if (ModUrlaub_1_0 !== "-.-.-" && ModUrlaub_2_0 !== "-.-.-" && ModUrlaub_3_0 !== "-.-.-" )
 {
    if (ModUrlaub_1_0 === ModUrlaub_1_1)
      { ModUrlaub_1Final.postUpdate(ModUrlaub_1_0) }
      else 
      { ModUrlaub_1Final.postUpdate(ModUrlaub_1_0 + "-" + ModUrlaub_1_1) }
    
    if (ModUrlaub_2_0 === ModUrlaub_2_1)
      { ModUrlaub_2Final.postUpdate(ModUrlaub_2_0) }
      else 
      { ModUrlaub_2Final.postUpdate(ModUrlaub_2_0 + "-" + ModUrlaub_2_1) }

    if (ModUrlaub_3_0 === ModUrlaub_3_1)
      { ModUrlaub_3Final.postUpdate(ModUrlaub_3_0) }
      else 
      { ModUrlaub_3Final.postUpdate(ModUrlaub_3_0 + "-" + ModUrlaub_3_1) }

//Final String
 Urlaubstage.postUpdate(ModUrlaub_1Final + ";" + ModUrlaub_2Final + ";" + ModUrlaub_3Final)
}
  

 if (ModUrlaub_1_0 !== "-.-.-" && ModUrlaub_2_0 !== "-.-.-" )
 {
   
    if (ModUrlaub_1_0 === ModUrlaub_1_1)
      { ModUrlaub_1Final.postUpdate(ModUrlaub_1_0) }
      else 
      { ModUrlaub_1Final.postUpdate(ModUrlaub_1_0 + "-" + ModUrlaub_1_1) }

    if (ModUrlaub_2_0 === ModUrlaub_2_1)
      { ModUrlaub_2Final.postUpdate(ModUrlaub_2_0) }
      else 
      { ModUrlaub_2Final.postUpdate(ModUrlaub_2_0 + "-" + ModUrlaub_2_1) }  

//Final String
    Urlaubstage.postUpdate(ModUrlaub_1Final + ";" + ModUrlaub_2Final)
 } 


 if (ModUrlaub_1_0 !== "-.-.-")
 {
   
    if (ModUrlaub_1_0 === ModUrlaub_1_1)
      { ModUrlaub_1Final.postUpdate(ModUrlaub_1_0) }
      else 
      { ModUrlaub_1Final.postUpdate(ModUrlaub_1_0 + "-" + ModUrlaub_1_1) }

//Final String
    Urlaubstage.postUpdate(ModUrlaub_1Final)
 }
end

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

Re: OH2.5 Rules - DateTime to String an Final concatenation

Beitrag von udo1toni »

Da sind einige Fehler drin...

Zuerst mal darfst Du nicht ein Item direkt abfragen, sondern musst dessen Status verwenden. Immer (solange es um den Status geht...)

Der Vergleich === bedeutet -> ist identisch. Dieser Vergleich ist exakt an einer Stelle zulässig, sinnvoll und gefordert, nämlich beim Vergleich mit null (null != NULL !!!).
Kurzer Einschub: === prüft, ob der Zeiger einer Variablen auf die gleiche Speicherzelle verweist. Eine Variable ist immer ein Zeiger auf einen bestimmten Speicherbereich. Abhängig vom Typ der Variable werden dann eine bestimmte Anzahl Speicherzellen danach oder bis zum EOF-Signal eingelesen (das wäre dann bei String der Fall). Der Wert null bedeutet, dass die Variable nicht initialisiert ist. Das wird dadurch erreicht, dass der Zeiger auf eine ganz bestimmte Stelle im Speicher verweist (Keine Ahnung... könnte z.B. die Speicherzelle 0 sein, oder auch 4711...). Diese Speicherzelle ist dann per Definition der Wert null, egal, was da steht. (Das Betriebssystem kümmert sich aber darum, dass dort ein Wert steht, der sinnvoll als null interpretiert werden kann...) Mit === wird also nun nicht der eigentliche Wert geprüft, sondern, ob der Zeiger auf die null-Speicherzelle verweist. Im Unterschied dazu ist NULL oder auch UNDEV ein gültiger Status eines Items, der aber anders codiert wird.

Es gibt einen grundlegenden Unterschied zwischen Variablen und Items. Erstere müssen direkt verwendet werden (variable = 5 -> der Variablen wird der Wert 5 zugewiesen; if(variable == 5) -> Prüfung, ob der Wert in der Variablen dem Wert 5 entspricht; if(variable != "drölf") -> Prüfung, ob sich der Wert der Variablen vom String drölf unterscheidet; if(variable === null) prüfung ob die Variable nicht initialisiert ist...)
Letztere müssen über die Methoden angesprochen werden, also Item.state -> Status des Items. Item.postUpdate -> Setze den Status des Items Item.sendCommand -> Sende einen Befehl an den/die verknüpfte(n) Channel.

Die Funktion .format steht nur für Strings zur Verfügung. Ein Status (.state) ist aber kein String!!! Das heißt, man muss den Status zunächst zu einem String machen.
Kurzer Einschub: if(Item.state == NULL) -> NULL ist ein Status; if(Item.state == "NULL") "NULL" ist ein String. openHAB ist nett und führt automatisch das .toString aus. Bei Item.state.format ist es aber nicht möglich, eine Wandlung nach String zu automatisieren, es wird explizit .state.format aufgerufen, was nicht definiert ist -> Fehler.

Codewiederholungen sind meist unnötig und lassen sich leicht aus der Welt schaffen, wenn man das Problem anders betrachtet.

Eine (ungetestete) Version der Rule, die eventuell korrekt funktioniert (eher nicht... erfahrungsgemäß habe ich immer irgendwo einen Fehler drin...):

Code: Alles auswählen

rule "Urlaub Adding"
when 
    Item CalDav_UrlaubDate_1 changed or
    System started or
    Time cron "0 0/2 * * * ?"  //every 2 Minutes  //? echt jetzt? unnötig... oder nur zum Test drin?
then

    var String ModUrlaub_1_0 = "-.-.-" // Default Wert gleich setzen
    var String ModUrlaub_1_1 = "-.-.-"
    var String ModUrlaub_2_0 = "-.-.-"
    var String ModUrlaub_2_1 = "-.-.-"
    var String ModUrlaub_3_0 = "-.-.-"
    var String ModUrlaub_3_1 = "-.-.-"
 
    var String ModUrlaub_1Final = "-"
    var String ModUrlaub_2Final = "-"
    var String ModUrlaub_3Final = "-"

    var String Final = ""

    // evtl. besser stattdessen if(CalDav_UrlaubDate_nnn.state instanceof DateTimeType) // prüft auf gültiges Datum
    // if(CalDav_UrlaubDate_1.state   != UNDEF && CalDav_UrlaubDate_1.state   != NULL) prüft auf "keiner von zwei möglichen ungültigen Werten"

	if (CalDav_UrlaubDate_1.state   != UNDEF && CalDav_UrlaubDate_1.state   != NULL) ModUrlaub_1_0 = CalDav_UrlaubDate_1.state.toString.format(  "%1$td.%1$tm.%1$ty") 
	if (CalDav_UrlaubDate_1_1.state != UNDEF && CalDav_UrlaubDate_1_1.state != NULL) ModUrlaub_1_1 = CalDav_UrlaubDate_1_1.state.toString.format("%1$td.%1$tm.%1$ty")
	if (CalDav_UrlaubDate_2.state   != UNDEF && CalDav_UrlaubDate_2.state   != NULL) ModUrlaub_2_0 = CalDav_UrlaubDate_2.state.toString.format(  "%1$td.%1$tm.%1$ty")
	if (CalDav_UrlaubDate_2_1.state != UNDEF && CalDav_UrlaubDate_2_1.state != NULL) ModUrlaub_2_1 = CalDav_UrlaubDate_2_1.state.toString.format("%1$td.%1$tm.%1$ty")
	if (CalDav_UrlaubDate_3.state   != UNDEF && CalDav_UrlaubDate_3.state   != NULL) ModUrlaub_3_0 = CalDav_UrlaubDate_3.state.toString.format(  "%1$td.%1$tm.%1$ty")
	if (CalDav_UrlaubDate_3_1.state != UNDEF && CalDav_UrlaubDate_3_1.state != NULL) ModUrlaub_3_1 = CalDav_UrlaubDate_3_1.state.toString.format("%1$td.%1$tm.%1$ty")

    if (ModUrlaub_1_0 != "-.-.-") {                                   // Falls gültiges Startdatum1
        ModUrlaub_1Final = ModUrlaub_1_0                              // setze Startdatum1
		if (ModUrlaub_1_0 != ModUrlaub_1_1)                           // Falls außerdem gültiges Enddatum1
		    ModUrlaub_1Final = ModUrlaub_1Final + "-" + ModUrlaub_1_1 // ergänze Enddatum1
    }
	if (ModUrlaub_2_0 != "-.-.-" && ModUrlaub_1Final != "-") {        // Falls gültiges Startdatum2 UND gültiges Datum für 1
		ModUrlaub_2Final = ModUrlaub_2_0                              // ...
		if (ModUrlaub_2_0 != ModUrlaub_2_1)                           // ...
		    ModUrlaub_2Final = ModUrlaub_2Final + "-" + ModUrlaub_2_1 // ...
	}
	if (ModUrlaub_3_0 != "-.-.-" && ModUrlaub_2Final != "-") {        // Falls gültiges Startdatum3 UND gültiges Datum für 2
		ModUrlaub_3Final = ModUrlaub_3_0                              // ...
		if (ModUrlaub_3_0 != ModUrlaub_3_1)
		    ModUrlaub_3Final = ModUrlaub_3Final + "-" + ModUrlaub_3_1
    }
    if (ModUrlaub_1Final != "-")              // Falls gültiges Datum1
        Final = ModUrlaub_1Final              // setze in finalem String
    if (ModUrlaub_2Final != "-")              // Falls gültiges Datum2
        Final = Final +";" + ModUrlaub_2Final // ergänze Datum2
    if (ModUrlaub_3Final != "-")              // Falls gültiges Datum3
        Final = Final +";" + ModUrlaub_3Final // ergänze Datum3

    Urlaubstage.postUpdate(Final)             // Item update
end
openHAB4.1.2 stable in einem Debian-Container (bookworm) (Proxmox 8.1.5, LXC), mit openHABian eingerichtet

summy
Beiträge: 3
Registriert: 29. Dez 2021 21:56

Re: OH2.5 Rules - DateTime to String an Final concatenation

Beitrag von summy »

Danke für die schnelle Hilfe! Ich habe mir meine Fehler nochmal genau angeschaut. Ich habe dein Script nun eingebaut und etwas angepasst.
Anbei die finale RULE. Die Time cron auf 2 min war nur zum testen :D, final soll die Rule nur um 5 Uhr ausgeführt werden. bzw. wenn das System neugestartet wird.

Code: Alles auswählen

rule "Urlaub Adding"
when 

    /*
    Item CalDav_UrlaubDate_1 changed or
    System started or
    Time cron "0 0/2 * * * ?"  //every 2 Minutes 
    */
    
    System started or Time cron "0 5 * * * ?" //daily at 5:00 am
then

    var String ModUrlaub_1_0 = "-.-.-" // Default Wert gleich setzen
    var String ModUrlaub_1_1 = "-.-.-"
    var String ModUrlaub_2_0 = "-.-.-"
    var String ModUrlaub_2_1 = "-.-.-"
    var String ModUrlaub_3_0 = "-.-.-"
    var String ModUrlaub_3_1 = "-.-.-"
 
    var String ModUrlaub_1Final = "-"
    var String ModUrlaub_2Final = "-"
    var String ModUrlaub_3Final = "-"

    var String Final = ""

    // evtl. besser stattdessen if(CalDav_UrlaubDate_nnn.state instanceof DateTimeType) // prüft auf gültiges Datum
    // if(CalDav_UrlaubDate_1.state   != UNDEF && CalDav_UrlaubDate_1.state   != NULL) prüft auf "keiner von zwei möglichen ungültigen Werten"
  if (CalDav_UrlaubDate_1.state   != UNDEF && CalDav_UrlaubDate_1.state   != NULL) { ModUrlaub_1_0 = CalDav_UrlaubDate_1.state.format("%1$td.%1$tm.%1$ty") }
	if (CalDav_UrlaubDate_1_1.state != UNDEF && CalDav_UrlaubDate_1_1.state != NULL) { ModUrlaub_1_1 = CalDav_UrlaubDate_1_1.state.format("%1$td.%1$tm.%1$ty") }
	if (CalDav_UrlaubDate_2.state   != UNDEF && CalDav_UrlaubDate_2.state   != NULL) { ModUrlaub_2_0 = CalDav_UrlaubDate_2.state.format("%1$td.%1$tm.%1$ty") }
	if (CalDav_UrlaubDate_2_1.state != UNDEF && CalDav_UrlaubDate_2_1.state != NULL) { ModUrlaub_2_1 = CalDav_UrlaubDate_2_1.state.format("%1$td.%1$tm.%1$ty") }
  if (CalDav_UrlaubDate_3.state   != UNDEF && CalDav_UrlaubDate_3.state   != NULL) { ModUrlaub_3_0 = CalDav_UrlaubDate_3.state.format("%1$td.%1$tm.%1$ty") }
	if (CalDav_UrlaubDate_3_1.state != UNDEF && CalDav_UrlaubDate_3_1.state != NULL) { ModUrlaub_3_1 = CalDav_UrlaubDate_3_1.state.format("%1$td.%1$tm.%1$ty") }


    if (ModUrlaub_1_0 != "-.-.-") {                                       // Falls gültiges Startdatum1
        ModUrlaub_1Final = ModUrlaub_1_0                                  // setze Startdatum1
		if (ModUrlaub_1_0 != ModUrlaub_1_1)                                   // Falls außerdem gültiges Enddatum1
		   { ModUrlaub_1Final = ModUrlaub_1Final + "-" + ModUrlaub_1_1 }      // ergänze Enddatum1
    }
	if (ModUrlaub_2_0 != "-.-.-" && ModUrlaub_1Final != "-") {              // Falls gültiges Startdatum2 UND gültiges Datum für 1
		ModUrlaub_2Final = ModUrlaub_2_0                                      // ...
		if (ModUrlaub_2_0 != ModUrlaub_2_1)                                   // ...
		   { ModUrlaub_2Final = ModUrlaub_2Final + "-" + ModUrlaub_2_1 }      // ...
	}
	if (ModUrlaub_3_0 != "-.-.-" && ModUrlaub_2Final != "-") {              // Falls gültiges Startdatum3 UND gültiges Datum für 2
		ModUrlaub_3Final = ModUrlaub_3_0                                      // ...
		if (ModUrlaub_3_0 != ModUrlaub_3_1)
		   { ModUrlaub_3Final = ModUrlaub_3Final + "-" + ModUrlaub_3_1 }
    }

    if (ModUrlaub_1Final != "-")                                          // Falls gültiges Datum1
       { Final = ModUrlaub_1Final  }                                      // setze in finalem String
    if (ModUrlaub_2Final != "-")                                          // Falls gültiges Datum2
       { Final = Final +";" + ModUrlaub_2Final }                          // ergänze Datum2
    if (ModUrlaub_3Final != "-")                                          // Falls gültiges Datum3
      { Final = Final +";" + ModUrlaub_3Final }                           // ergänze Datum3

    Urlaubstage.postUpdate(Final)                                         // Item update
end

Antworten