Seite 1 von 3

Regel von Openhab 3.5 auf 4.0 ändern

Verfasst: 21. Okt 2023 13:47
von N1d45
Moin.

Ich habe ein Problem, das eine Regel, die in 3.4 funktionierte, jetzt in 4.0 nicht mehr funktioniert. (Eigentlich zwei Regeln, aber erst einmal die eine Baustelle)

Es ist eine Regel, die eine Sprachausgabe auf Amazon Echos steuert, falls ich die Fenster beim Lüften vergesse zu schließen.

Über einen Timer soll nach 10 Minuten, wiederholend auf weitere 10 Minuten, auf den Echos ausgegeben werden, welche Fenster geschlossen werden sollen.

Die Ausgabe auf die Echos, habe ich schon erfolgreich angepasst. Sie funktioniert auch, wenn ich alles was mit Zeit und Timer zu tun hat, auskommentiere. Leider finde ich nicht die Information, wahrscheinlich weil ich gar nicht so richtig weiß wo und nach was ich suchen soll, im Netz nicht, wie ich es anpassen soll.

Im Moment sieht der Code noch so aus, der nicht funktioniert.

Code: Alles auswählen

var scriptExecution = Java.type('org.openhab.core.model.script.actions.ScriptExecution');
var zdt = Java.type('java.time.ZonedDateTime');
var text = '';                                // Text den Alexa ausgibt
var temperatur = 25;                          // Außentemperatur, die unterschritten sein muss, um das Skript auszuführen
var timerZeitMinuten = 10;                    // Zeit in Minuten, die der Timer laufen soll

if (typeof this.timers === 'undefined') {                                     
  this.timers = [];
}

function fTimerCode() {         // Code nach ablauf des Timers
  if (OpenWindows.state > 0                                                   // Wenn Fenster noch offen
      && SensEgg58_Temperatur.state < temperatur) {                           // UND wenn Temperatur noch unterschritten
    text = '';
    if (zdt.now().getHour() >= 20 || zdt.now().getHour() <= 5){
      text = text + '<amazon:effect name="whispered"> ';
      EchoKuche_SprichLautstarke.sendCommand(30);
      EchoWohnen_SprichLautstarke.sendCommand(30);
    }
    if (FensterkontaktBadezimmer_Wert1.state == 'OPEN') text = text + 'Bad <break time =\"200ms\"/>';
    if (FensterkontaktBalkon_Wert1.state == 'OPEN') text = text + 'Balkon <break time =\"200ms\"/>';
    if (FensterkontaktSchlafzimmer_Wert1.state == 'OPEN') text = text + 'Schlafzimmer <break time =\"200ms\"/>';
    if (FensterkontaktBuro_Wert1.state == 'OPEN') text = text + 'Niki <break time =\"200ms\"/>';
    if (FensterkontaktKinderzimmer_Wert1.state == 'OPEN') text = text + 'Kinder <break time =\"200ms\"/>';
    if (FensterkontaktWohnzimmer_Wert1.state == 'OPEN') text = text + 'Wohnen <break time =\"200ms\"/>';
    if (FensterkontaktKuche_Wert1.state == 'OPEN') text = text + 'Küche <break time =\"200ms\"/>';
    text = text + 'Fenster schließen';
    if (zdt.now().getHour() >= 20 || zdt.now().getHour() <= 5) text = text + '</amazon:effect>';
    if (zdt.now().getHour() <= 21 && zdt.now().getHour() >= 8) {                                           // Wenn im Zeitfenster
      EchoNici_Sprich.sendCommand(text);                                                         // Ausgabe Echo Nici
    }
    EchoWohnen_Sprich.sendCommand(text);                                                         // Ausgabe Echo Wohnen
    EchoKuche_Sprich.sendCommand(text);                                                          // Ausgabe Echo Küche
    EchoBad_Sprich.sendCommand(text);                                                            // Ausgabe Echo Bad
    EchoKuche_SprichLautstarke.sendCommand(20);
    EchoWohnen_SprichLautstarke.sendCommand(20);
    if (typeof this.timers['FensterTimer'] !== 'undefined') {                                              // Wenn Timer nicht das gleiche wie undefinierd
      this.timers['FensterTimer'].reschedule(zdt.now().plusMinutes(timerZeitMinuten));                     // Starte Timer neu 
    }
  }
//}

if (SensEgg58_Temperatur.state() < temperatur) {                                        // Nur ausführen, wenn Außentemperatur unter (Damit nicht Timer unnötig erstellt werden und die Lautstärke unnötig geändert wird)
  if (typeof this.timers['FensterTimer'] === 'undefined' || this.timers['FensterTimer'].hasTerminated()) {         // Wenn der Timer nicht definiert oder abgelaufen
    this.timers['FensterTimer'] = scriptExecution.createTimer(zdt.now().plusMinutes(timerZeitMinuten), fTimerCode) // Erstelle einen Timer und führe Funktion aus
  } 
  else {
    this.timers['FensterTimer'].reschedule(zdt.now().plusMinutes(timerZeitMinuten));                               // Setzt den Timer neu, wenn der Rule Trigger erneut auslöst und Bedingung (Temperatur) oben erfüllt ist
  }
}
Mit folgenden auskomentiert funktioniert es.

Code: Alles auswählen

// var scriptExecution = Java.type('org.openhab.core.model.script.actions.ScriptExecution');
// var zdt = Java.type('java.time.ZonedDateTime');
var text = '';                                // Text den Alexa ausgibt
var temperatur = 25;                          // Außentemperatur, die unterschritten sein muss, um das Skript auszuführen
var timerZeitMinuten = 10;                    // Zeit in Minuten, die der Timer laufen soll

/* if (typeof this.timers === 'undefined') {                                     
  this.timers = [];
} */

// function fTimerCode() {         // Code nach ablauf des Timers
  if (OpenWindows.state > 0                                                   // Wenn Fenster noch offen
      && SensEgg58_Temperatur.state < temperatur) {                           // UND wenn Temperatur noch unterschritten
    text = '';
    /* if (zdt.now().getHour() >= 20 || zdt.now().getHour() <= 5){
      text = text + '<amazon:effect name="whispered"> ';
      EchoKuche_SprichLautstarke.sendCommand(30);
      EchoWohnen_SprichLautstarke.sendCommand(30);
    } */
    if (FensterkontaktBadezimmer_Wert1.state == 'OPEN') text = text + 'Bad <break time =\"200ms\"/>';
    if (FensterkontaktBalkon_Wert1.state == 'OPEN') text = text + 'Balkon <break time =\"200ms\"/>';
    if (FensterkontaktSchlafzimmer_Wert1.state == 'OPEN') text = text + 'Schlafzimmer <break time =\"200ms\"/>';
    if (FensterkontaktBuro_Wert1.state == 'OPEN') text = text + 'Niki <break time =\"200ms\"/>';
    if (FensterkontaktKinderzimmer_Wert1.state == 'OPEN') text = text + 'Kinder <break time =\"200ms\"/>';
    if (FensterkontaktWohnzimmer_Wert1.state == 'OPEN') text = text + 'Wohnen <break time =\"200ms\"/>';
    if (FensterkontaktKuche_Wert1.state == 'OPEN') text = text + 'Küche <break time =\"200ms\"/>';
    text = text + 'Fenster schließen';
    /* if (zdt.now().getHour() >= 20 || zdt.now().getHour() <= 5) text = text + '</amazon:effect>';
    if (zdt.now().getHour() <= 21 && zdt.now().getHour() >= 8) {                                           // Wenn im Zeitfenster
      EchoNici_Sprich.sendCommand(text);                                                         // Ausgabe Echo Nici
    } */
    EchoWohnen_Sprich.sendCommand(text);                                                         // Ausgabe Echo Wohnen
    EchoKuche_Sprich.sendCommand(text);                                                          // Ausgabe Echo Küche
    EchoBad_Sprich.sendCommand(text);                                                            // Ausgabe Echo Bad
    EchoKuche_SprichLautstarke.sendCommand(20);
    EchoWohnen_SprichLautstarke.sendCommand(20);
    /* if (typeof this.timers['FensterTimer'] !== 'undefined') {                                              // Wenn Timer nicht das gleiche wie undefinierd
      this.timers['FensterTimer'].reschedule(zdt.now().plusMinutes(timerZeitMinuten));                     // Starte Timer neu 
    } */
  }
//}

/* if (SensEgg58_Temperatur.state() < temperatur) {                                        // Nur ausführen, wenn Außentemperatur unter (Damit nicht Timer unnötig erstellt werden und die Lautstärke unnötig geändert wird)
  if (typeof this.timers['FensterTimer'] === 'undefined' || this.timers['FensterTimer'].hasTerminated()) {         // Wenn der Timer nicht definiert oder abgelaufen
    this.timers['FensterTimer'] = scriptExecution.createTimer(zdt.now().plusMinutes(timerZeitMinuten), fTimerCode) // Erstelle einen Timer und führe Funktion aus
  } 
  else {
    this.timers['FensterTimer'].reschedule(zdt.now().plusMinutes(timerZeitMinuten));                               // Setzt den Timer neu, wenn der Rule Trigger erneut auslöst und Bedingung (Temperatur) oben erfüllt ist
  }
} */
Wie müssten die Code Zeilen angepasst werden, damit sie mit 4.0 konform gehen?


Edit: Und hier noch der Code, der mit 3.5 noch funktioniert hat.

Code: Alles auswählen

var scriptExecution = Java.type('org.openhab.core.model.script.actions.ScriptExecution');
var zdt = Java.type('java.time.ZonedDateTime');
var text = '';                                // Text den Alexa ausgibt
var temperatur = 15;                          // Außentemperatur, die unterschritten sein muss, um das Skript auszuführen
var timerZeitMinuten = 10;                    // Zeit in Minuten, die der Timer laufen soll

if (typeof this.timers === 'undefined') {                                     
  this.timers = [];
} 

function fTimerCode() {         // Code nach ablauf des Timers
  if (itemRegistry.getItem('OpenWindows').getState() > 0                                                   // Wenn Fenster noch offen
      && itemRegistry.getItem('SensEgg58_Temperatur').getState() < temperatur) {                           // UND wenn Temperatur noch unterschritten
    text = '';
    if (zdt.now().getHour() >= 19 || zdt.now().getHour() <= 6) text = text + '<amazon:effect name="whispered"> ';
    if (itemRegistry.getItem('FensterkontaktBadezimmer_Wert1').getState() == 'OPEN') text = text + 'Bad <break time =\"200ms\"/>';
    if (itemRegistry.getItem('FensterkontaktBalkon_Wert1').getState() == 'OPEN') text = text + 'Balkon <break time =\"200ms\"/>';
    if (itemRegistry.getItem('FensterkontaktSchlafzimmer_Wert1').getState() == 'OPEN') text = text + 'Schlafzimmer <break time =\"200ms\"/>';
    if (itemRegistry.getItem('FensterkontaktBuro_Wert1').getState() == 'OPEN') text = text + 'Niki <break time =\"200ms\"/>';
    if (itemRegistry.getItem('FensterkontaktKinderzimmer_Wert1').getState() == 'OPEN') text = text + 'Kinder <break time =\"200ms\"/>';
    if (itemRegistry.getItem('FensterkontaktWohnzimmer_Wert1').getState() == 'OPEN') text = text + 'Wohnen <break time =\"200ms\"/>';
    if (itemRegistry.getItem('FensterkontaktKuche_Wert1').getState() == 'OPEN') text = text + 'Küche <break time =\"200ms\"/>';
    text = text + 'Fenster schließen';
    if (zdt.now().getHour() >= 19 || zdt.now().getHour() <= 6) text = text + '</amazon:effect>';
    if (zdt.now().getHour() <= 21 && zdt.now().getHour() >= 8) {                                           // Wenn im Zeitfenster
      events.sendCommand('EchoNici_Sprich', text);                                                         // Ausgabe Echo Nici
    }
    events.sendCommand('EchoWohnen_Sprich', text);                                                         // Ausgabe Echo Wohnen
    events.sendCommand('EchoKuche_Sprich', text);                                                          // Ausgabe Echo Küche
    events.sendCommand('EchoBad_Sprich', text);                                                            // Ausgabe Echo Bad
    if (typeof this.timers['FensterTimer'] !== 'undefined') {                                              // Wenn Timer nicht das gleiche wie undefinierd
      this.timers['FensterTimer'].reschedule(zdt.now().plusMinutes(timerZeitMinuten));                     // Starte Timer neu 
    }
  }
}

if (itemRegistry.getItem('SensEgg58_Temperatur').getState() < temperatur) {                                        // Nur ausführen, wenn Außentemperatur unter (Damit nicht Timer unnötig erstellt werden)
  if (typeof this.timers['FensterTimer'] === 'undefined' || this.timers['FensterTimer'].hasTerminated()) {         // Wenn der Timer nicht definiert oder abgelaufen
    this.timers['FensterTimer'] = scriptExecution.createTimer(zdt.now().plusMinutes(timerZeitMinuten), fTimerCode) // Erstelle einen Timer und führe Funktion aus
  } 
  else {
    this.timers['FensterTimer'].reschedule(zdt.now().plusMinutes(timerZeitMinuten));                               // Setzt den Timer neu, wenn der Rule Trigger erneut auslöst und Bedingung (Temperatur) oben erfüllt ist
  }
}

Re: Regel von Openhab 3.5 auf 4.0 ändern

Verfasst: 21. Okt 2023 17:04
von udo1toni
Ich selbst nutze JavaScript nicht, aber es gab eine wichtige Änderung, openHAB 3 nutzte Nashorn als JavaScript Engine, während openHAB 4 GraalVM anbietet (Nashorn steht allerdings immer noch zur Verfügung).

Re: Regel von Openhab 3.5 auf 4.0 ändern

Verfasst: 21. Okt 2023 17:48
von N1d45
udo1toni hat geschrieben: 21. Okt 2023 17:04 ...
Nashorn steht allerdings immer noch zur Verfügung.
...
Kann/Muß man das irgendwie aktivieren?

Edit: Tausend Dank. Ich habe es gefunden. Unter Automation und instalieren. Und dann natürlich wieder als ECMAScript (ECMA - 262 Edition 5.1) laufen lassen.

Re: Regel von Openhab 3.5 auf 4.0 ändern

Verfasst: 21. Okt 2023 23:53
von udo1toni
:)

Allerdings möchte ich empfehlen, Dich dennoch mit der Umstellung zu beschäftigen (aber ohne den Druck, das "sofort" lauffähig zu haben).

Re: Regel von Openhab 3.5 auf 4.0 ändern

Verfasst: 22. Okt 2023 15:12
von N1d45
Gibt es da ein Beispiel für Timer, erstellen, erneuern (Verlängerung bzw. neu Setzen), und löschen?

Gibt es ein Beispiel für Funktionen? Weil das

Code: Alles auswählen

function fTest(){ 
  … 
}
gefiel dem System auch irgendwie nicht mehr.

gethour habe ich schon erfolgreich in einem Test lösen können.

Danke für die Ermutigung. Bin ja froh das es wieder wie gewohnt läuft. Da ist man schnell dabei es zu lassen.

Re: Regel von Openhab 3.5 auf 4.0 ändern

Verfasst: 22. Okt 2023 16:10
von Harka
Moin,
die Funktion als solche ist nicht das Problem. Änderungen solltest Du bei scriptExecution, zdt und dem Timer suchen. z.B reicht jetzt ein var zdt = time.ZonedDateTime;
Eine Übersicht findest Du unter https://www.openhab.org/addons/automation/jsscripting/ und aktuell auch hier.
Für die wiederkehrenden Timer ist setInterval imho die bessere Lösung.

Re: Regel von Openhab 3.5 auf 4.0 ändern

Verfasst: 22. Okt 2023 17:35
von N1d45
Danke.
Und ein Weg ohne JavaSkript?
In Rules DSL.
Gibt es ein Link dazu? Irgendwie such ich immer falsch.

Edit: Ich denke ich habe etwas gefunden https://www.openhab.org/docs/configurat ... elays.html

Blockly erstellt doch auch nur Rules DSL im Hintergrund?

Ich probiere mich mal.

Re: Regel von Openhab 3.5 auf 4.0 ändern

Verfasst: 22. Okt 2023 19:02
von Harka
Sehe gerade, Du nutzt ja auch noch itemRegistry.getItem. Ist auch veraltet.
Wenn es Dir nur um mehr Unterstützung geht - Blockly erzeugt nun auch den neuen Code (wenn auch manchmal nicht den schönsten, aber die Anforderungen sind ja auch andere). Diesen kannst Du dann in Deine Rules übernehmen.
E: Achtung, beim wiederholenden Timer ist in Blockly gerade ein Fehler enthalten

Re: Regel von Openhab 3.5 auf 4.0 ändern

Verfasst: 22. Okt 2023 19:53
von N1d45
Hmm. Ich habe jetzt gut zwei Stunden rumprobiert. Aber die Rules geben im Log immer einen Fehler aus. Selbst mit Blockly erstellt. Irgendwie fehlt mir eine Anzeige, was ich falsch geschrieben habe. Oder warum der Error eigentlich erfolgt. Ich bin es von C++ gewöhnt das mir der Compiler sagt, in welcher Zeile er ein Problem sieht und was für ein Problem er hat. Gibt es hier in openHAB so etwas wie ein Prüfprogramm, was aufzeigen kann, was in der Syntax falsch ist?

Wahrscheinlich brauche ich ein Buch der jeweiligen Sprache. Naja, ich sehe das Experiment gescheitert.

Re: Regel von Openhab 3.5 auf 4.0 ändern

Verfasst: 22. Okt 2023 21:29
von Harka
nix da! ;-)
Jetzt habe ich das Teil mal zur Fehlerbereinigen eines Blocks "Marke Eigenbau" benutzt und dabei ist folgendes Beispiel bei raus gekommen. Da, wo bei mir Bewegung 1 u.s.w. steht, kommen bei Dir die Kontakte hin und bei console.warn die Alexaausgabe.

Code: Alles auswählen

var nameTimer, WarteZeit, temperatur, text, iCounter;

nameTimer = 'FensterTimer';
WarteZeit = 10*60; 
temperatur = 15;
iCounter = 0;  

if (typeof(this[nameTimer]) != 'undefined') clearInterval(this[nameTimer]); 

this[nameTimer] = setInterval(function() {

  if (items.getItem('FensterGruppeTest').numericState > 0 && items.getItem('TemperaturTest').numericState < temperatur) {
    text = '';
	
    if (items.getItem('Bewegung_1').state == 'ON')  text += 'erster Text'; // hier die Kontakte und Alexas
    if (items.getItem('Bewegung_2').state == 'ON')  text += 'zweiter Text';
    console.warn(text);
	
  } else {
    if (typeof(this[nameTimer]) != 'undefined') clearInterval(this[nameTimer]);
  }
  iCounter++;
  
  if iCounter >= 10) clearInterval(this[nameTimer]); // max 10 Wiederholungen a 10 Minuten
}, WarteZeit*1000);