[gelöst] Rasenbewässerung - Code Probleme

Begonnen von Christian_M, 18 Juni 2022, 22:00:45

Vorheriges Thema - Nächstes Thema

Christian_M

Hallo zusammen,

ich glaube ich habe mich in meine perl Unkenntnis in einem oder mehreren Fehlern verstrickt.
Über ein Dumme Device löse ich eine Bewässerungszeit und möchte in Abhängigkeit von der Zeit verschiedene Aktoren der Reihe nach schalten (Ich hab nicht genug Druck auf der Leitung um alle gleichzeitig laufen zu lassen).
WelcheBewässerung laufen soll, möchte ich ebenfalls über Dummy Devices schalten.
Welche Bewässerung gerade läuft möchte ich in dem State des Dummy Device anzeigen.
Hier mein Versuch aus einem Notify: (Nicht wundern, ich teste derzeit noch mit Stehlampen)
define n_SprengerZeit notifySprengerZeit {
  fhem "setstate SprengerZeit Gestartet";
  if (ReadingsVal("Bewaesserung_Mulchrand", "state", "Nein") eq "Ja") {
    fhem "set Tischlampe_EZ on-for-timer $EVENT; setstate SprengerZeit Mulch; sleep $EVENT";
  }
  if (ReadingsVal("Bewaesserung_Rasen", "state", "Nein") eq "Ja") {
    fhem "set Tischlampe_Kueche on-for-timer $EVENT; setstate SprengerZeit Rasen; sleep $EVENT";
  }
  fhem "setstate SprengerZeit Inaktiv";
}


Was passiert ist:
- Ich setze ein Event mit 10 an
- Die erste Lampe schaltet für 10 Sek
- Die zweite Lampe schaltet gar nicht
- Der State von SprengerZeit bleibt immer auf Inaktiv.

Für Hilfe wäre ich dankbar. Vermutlich mutmaße, dass ich in perl etwas grundlegend falsch gemacht habe

VG
Christian

Jamo

0) Dein code hat SprengerZeit immer sofort auf inaktiv gesetzt. SprengerZeit soll aber erst nach dem sleep auf inaktiv gesetzt werden.
1) nach jedem sleep muss noch ein fhem befehl kommen, sonst blockiert fhem.
2) Wenn die 2-te lampe nicht schaltet, kann sein das deine Bedingung fuer (ReadingsVal("Bewaesserung_Rasen", "state", "Nein") eq "Ja") nicht erfuellt ist.

Wenn, dann so:

define n_SprengerZeit notifySprengerZeit {
  fhem "setstate SprengerZeit Gestartet";
  if (ReadingsVal("Bewaesserung_Mulchrand", "state", "Nein") eq "Ja") {
    fhem "set Tischlampe_EZ on-for-timer $EVENT; setstate SprengerZeit Mulch; sleep $EVENT; setstate SprengerZeit Inaktiv";
  }
  if (ReadingsVal("Bewaesserung_Rasen", "state", "Nein") eq "Ja") {
    fhem "set Tischlampe_Kueche on-for-timer $EVENT; setstate SprengerZeit Rasen; sleep $EVENT; setstate SprengerZeit Inaktiv";
  }
}
Bullseye auf iNUC, Homematic + HMIP(UART/HMUSB), Debmatic, HUEBridge, Zigbee/Conbee III, FB7690, Alexa (fhem-lazy), Livetracking, LaCrosse JeeLink, LoRaWan / TTN / Chirpstack, Sonos, ESPresence

Christian_M

Hi Jamo,

danke für die schnelle Antwort.
Das Verhalten hat sich dadurch schon einmal geändert aber etwas ist noch falsch.
Jetzt geht nur die erste Lampe (Tischlampe_EZ) an aber der Status geht direkt auf "Rasen" (also der Status von der zweiten Lampe) und nach der Dauer direkt auf Inaktiv.

Jamo

Zitataber der Status geht direkt auf "Rasen"
Ja, das hast Du auch so programmiert. Ich nehme mal an, das die states fuer Bewaesserung_Mulchrand und Bewaesserung_Rasen beide "Ja" sind, ist das so?
Dann wird die Tischlampe EZ mit on for timer gestartet, und auch sofort die SprengerZeit auf Mulch gesetzt.
Gleichzeitig wird die Tischlampe Kueche mit on for timer gestartet, und auch hier sofort die Sprengerzeit auf Rasen gesetzt (also das SprengerZeit Mulch wuerde direkt ueberschrieben).
Du hattest gesagt das entweder die obere oder die untere Bedingung gelten sollen, ich verstehe jetzt das beides gleichzeitig gilt, oder?

Wie ist denn der wert fuer ReadingsVal("Bewaesserung_Rasen", "state", "Nein")?

Wenn die bedinungen nicht gleichzeitig gelten sollen, wuerde ich aus dem 2-ten if ein elsif machen.

define n_SprengerZeit notifySprengerZeit {
  fhem "setstate SprengerZeit Gestartet";
  if (ReadingsVal("Bewaesserung_Mulchrand", "state", "Nein") eq "Ja") {
    fhem "set Tischlampe_EZ on-for-timer $EVENT; setstate SprengerZeit Mulch; sleep $EVENT; setstate SprengerZeit Inaktiv";
  }
  elsif (ReadingsVal("Bewaesserung_Rasen", "state", "Nein") eq "Ja") {
    fhem "set Tischlampe_Kueche on-for-timer $EVENT; sleep $EVENT; setstate SprengerZeit Inaktiv";
  }
}
Bullseye auf iNUC, Homematic + HMIP(UART/HMUSB), Debmatic, HUEBridge, Zigbee/Conbee III, FB7690, Alexa (fhem-lazy), Livetracking, LaCrosse JeeLink, LoRaWan / TTN / Chirpstack, Sonos, ESPresence

Christian_M

Ehrlich gesagt ist es sogar noch etwas anders gedacht.
Es soll immer nur ein Sprenger gleichzeitig an sein. Es können aber beide, keiner oder nur einer aktiv sein.
Sind mehrere Aktiv sollten sie nacheinander geschaltet werden.
Ein Elseif sollte dann ja nur funktionieren wenn die erste Bedingung falsch ergibt, sofern ich das richtig verstehen. Das wäre dann nicht im Ziel.

Jamo

#5
PS: habe noch ein sleep eingefuegt.
Dann musst Du sowas machen, geht bestimmt auch schoener, aber ist schon spaet:
define n_SprengerZeit notifySprengerZeit {
  fhem "setstate SprengerZeit Gestartet";
  if (ReadingsVal("Bewaesserung_Mulchrand", "state", "Nein") eq "Ja" && ReadingsVal("Bewaesserung_Rasen", "state", "Nein") eq "Ja") {
    fhem "set Tischlampe_EZ on-for-timer $EVENT; setstate SprengerZeit Mulch; sleep $EVENT ; set Tischlampe_EZ on-for-timer $EVENT; setstate SprengerZeit Mulch; sleep $EVENT; setstate SprengerZeit Inaktiv";
  }
  elsif (ReadingsVal("Bewaesserung_Mulchrand", "state", "Nein") eq "Ja") {
    fhem "set Tischlampe_EZ on-for-timer $EVENT; setstate SprengerZeit Mulch; sleep $EVENT; setstate SprengerZeit Inaktiv";
  }
  elsif (ReadingsVal("Bewaesserung_Rasen", "state", "Nein") eq "Ja") {
    fhem "set Tischlampe_Kueche on-for-timer $EVENT; sleep $EVENT; setstate SprengerZeit Inaktiv";
  }
else {fhem "setstate SprengerZeit Inaktiv";}
}


Ansonsten schau auch mal in den EVENTMONITOR, damit solltest Du immer sehen in welcher Reihenfolge die befehle abgearbeitet werden. Nach fhem eventmonitor googlen.
Bullseye auf iNUC, Homematic + HMIP(UART/HMUSB), Debmatic, HUEBridge, Zigbee/Conbee III, FB7690, Alexa (fhem-lazy), Livetracking, LaCrosse JeeLink, LoRaWan / TTN / Chirpstack, Sonos, ESPresence

Christian_M

Nochmals danke für deinen Einsatz.

Dein Ansatz wird für die zwei Geräte sicherlich funktionieren, da ich jedoch ca. 15-20 Geräte steuern möchte, ergäbe das zu viele Kombinationsmöglicheiten.
Ich bin naiv davon ausgegangen, dass ich 20 unabhängige Abfragen machen kann und bei jeder die zu trift ein sleep einbauen, damit keine zweite parallel angeht. Da scheine ich aber einen Denkfehler zu haben!?
Auch aus dem Event Log kommen keine neuen Informationen, außer dass komischerweise der an und aus Befehl für Tischlampe_EZ jeweils doppelt gesendet wird.
Ansonsten geht weiterhin die TischlampeEZ an und der Status wird auf Rasen gesetzt.
Komisch.

defmod n_SprengerZeit SprengerZeit {
  fhem "setstate SprengerZeit Gestartet";
  if (ReadingsVal("Bewaesserung_Mulchrand", "state", "Nein") eq "Ja") {
    fhem "set Tischlampe_EZ on-for-timer $EVENT; setstate SprengerZeit Mulch; sleep $EVENT; setstate SprengerZeit Inaktiv";
  }
  if (ReadingsVal("Bewaesserung_Rasen", "state", "Nein") eq "Ja") {
    fhem "set Tischlampe_Kueche on-for-timer $EVENT; setstate SprengerZeit Rasen; sleep $EVENT; setstate SprengerZeit Inaktiv";
  }
}

Jamo

ja, das liegt an deinem notify. Das triggert auf ALLE und JEDE änderung von Sprengerzeit, also auch wenn Du Sprengerzeit auf Gestartet, Mulch und Rasen und Inaktiv setzt. Du willst aber nur eine Zahl übergeben, also muss das notify regexp eingeschränkt werden:
defmod n_Sprengerzeit notify Spengerzeit:[0-9]+

Deswegen ja mein Tip, mal in den Eventmonitor zu schauen.
Deswegen wurde auch das 2-te on-for-timer nie ausgeführt, on-for-timer Gestartet geht eben nicht.

Hier kann man das regexp prima testen https://regex101.com/
Bullseye auf iNUC, Homematic + HMIP(UART/HMUSB), Debmatic, HUEBridge, Zigbee/Conbee III, FB7690, Alexa (fhem-lazy), Livetracking, LaCrosse JeeLink, LoRaWan / TTN / Chirpstack, Sonos, ESPresence

Christian_M

Ahhhhh das macht total Sinn. Werd ich heute Abend direkt testen danke!  :)

Jamo

Für deine 15-20 Geräte ist dann die folgende Lösung:
Immer wenn einer deiner zweige Bewässerung_xyz eq 'ja' ist, wird jeder weitere Zweig einfach um n*Event verzögert.
Also bei nur einer ja bedingug bleibt es wie es ist
bei 2 ja bedingungen muss dann vor den nächsten Zweig ein sleep mit der $Event Zeit,
bei 3 dann entsprechend.

das war glaube ich auch schon deine Idee, aber hatte ich erstmal nicht verstanden.

Kann ich Dir heute Abend mal für 3 hinschreiben, das ist dann auf jedenfall generisch
Bullseye auf iNUC, Homematic + HMIP(UART/HMUSB), Debmatic, HUEBridge, Zigbee/Conbee III, FB7690, Alexa (fhem-lazy), Livetracking, LaCrosse JeeLink, LoRaWan / TTN / Chirpstack, Sonos, ESPresence

Jamo

#10
So in etwa, kannste ja mal probieren:
Das $delay habe ich initial auf 0.1 gesetzt, weil ich glaube das es ein sleep 0 nicht gibt - macht ja auch keinen Sinn.

define n_SprengerZeit notify SprengerZeit:[0-9]+ {
  my $delay = 0.1;
  fhem "setstate SprengerZeit Gestartet";

  if (ReadingsVal("Bewaesserung_Mulchrand", "state", "Nein") eq "Ja") {
    fhem "sleep $delay;set Tischlampe_EZ on-for-timer $EVENT; setstate SprengerZeit Mulch";
    $delay = $delay + $EVENT;
  }

  if (ReadingsVal("Bewaesserung_Rasen", "state", "Nein") eq "Ja") {
    fhem "sleep $delay; set Tischlampe_Kueche on-for-timer $EVENT; setstate SprengerZeit Rasen";
    $delay = $delay + $EVENT;
  }
 
  if (ReadingsVal("Bewaesserung_Zaun", "state", "Nein") eq "Ja") {
    fhem "sleep $delay; set Tischlampe_WZ on-for-timer $EVENT; setstate SprengerZeit Zaun";
    $delay = $delay + $EVENT;
  }

  if (ReadingsVal("Bewaesserung_Terasse", "state", "Nein") eq "Ja") {
    fhem "sleep $delay; set Tischlampe_WZ on-for-timer $EVENT; setstate SprengerZeit Terasse";
    $delay = $delay + $EVENT;
  }

  fhem "sleep $delay;setstate SprengerZeit Inaktiv";
}
Bullseye auf iNUC, Homematic + HMIP(UART/HMUSB), Debmatic, HUEBridge, Zigbee/Conbee III, FB7690, Alexa (fhem-lazy), Livetracking, LaCrosse JeeLink, LoRaWan / TTN / Chirpstack, Sonos, ESPresence

Christian_M

Cool, der Code wirkt gut. Ich habe nur das Event zu einem EVENT machen müssen.
Leider ändert sich das Verhalten nur nicht  :o
Der State wird jetzt korrekt gesetzt aber er bricht wieder nach der ersten Lampe ab und gibt die Schaltbefehle wieder doppelt.
Auszug Event Log:
2022-06-19 22:02:29 dummy SprengerZeit 10
2022-06-19 22:02:29 TRX_LIGHT Tischlampe_EZ an
2022-06-19 22:02:29 TRX_LIGHT Tischlampe_EZ an
2022-06-19 22:02:39 TRX_LIGHT Tischlampe_EZ aus
2022-06-19 22:02:39 TRX_LIGHT Tischlampe_EZ aus

States von Bewaesserung_Rasen und Bewaesserung_Mulchrand stehen beide auf Ja und sind richtig geschrieben. Irgendwo steckt doch der Wurm drin.

Jamo

#12
Wir kriegen das hin. Kannst Du mal den code wie folgt erweitern, und dann den Logfile posten?
Und auch mal ein list von deinem device Sprengerzeit machen, also oben in der Commandozeile "list Sprengerzeit" eingeben.

PS: und aus dem 0.1 eine 1 machen? Ich weiss nicht ob on-for-timer auch bruchteile kann.

define n_SprengerZeit notify SprengerZeit:[0-9]+ {
  my $delay     = 1;
  my $sub       = 'n_Sprengerzeit';
  my $Mulchrand = ReadingsVal("Bewaesserung_Mulchrand", "state", "Nein");
  my $Rasen     = ReadingsVal("Bewaesserung_Rasen", "state", "Nein");
  my $Zaun      = ReadingsVal("Bewaesserung_Zaun", "state", "Nein");
  my $Terasse   = ReadingsVal("Bewaesserung_Terasse", "state", "Nein");

  Log 3, "[$sub] EVENT=$EVENT, delay=$delay, M=$Mulch, R=$Rasen";

  fhem "setstate SprengerZeit Gestartet";

  if ($Mulchrand eq "Ja") {
    fhem "sleep $delay;set Tischlampe_EZ on-for-timer $EVENT; setstate SprengerZeit Mulch";
    $delay = $delay + $EVENT;
    Log 3, "[$sub] Zweig Mulchrand, EVENT=$EVENT, delay=$delay";
  }

  if ($Rasen eq "Ja") {
    fhem "sleep $delay; set Tischlampe_Kueche on-for-timer $EVENT; setstate SprengerZeit Rasen";
    $delay = $delay + $EVENT;
    Log 3, "[$sub] Zweig Rasen, EVENT=$EVENT, delay=$delay";
  }
 
  if ($Zaun eq "Ja") {
    fhem "sleep $delay; set Tischlampe_WZ on-for-timer $EVENT; setstate SprengerZeit Zaun";
    $delay = $delay + $EVENT;
  }

  if ($Terasse eq "Ja") {
    fhem "sleep $delay; set Tischlampe_WZ on-for-timer $EVENT; setstate SprengerZeit Terasse";
    $delay = $delay + $EVENT;
  }
  Log 3, "[$sub] Ende, EVENT=$EVENT, delay=$delay";

  fhem "sleep $delay;setstate SprengerZeit Inaktiv";
}
Bullseye auf iNUC, Homematic + HMIP(UART/HMUSB), Debmatic, HUEBridge, Zigbee/Conbee III, FB7690, Alexa (fhem-lazy), Livetracking, LaCrosse JeeLink, LoRaWan / TTN / Chirpstack, Sonos, ESPresence

Christian_M

 ;D ;D ;D
Es funktioniert!
Vielen Dank. Dein Code für das Log hat mir meinen peinlichen Fehler vor Augen geführt.
Ein Tippfehler im Device Namen den ich zig mal überlesen habe war dennoch da.  :-[

Der Code hat mir auf jeden Fall auch sehr geholfen.
Einziges was noch komisch ist. Die Schaltbefehle werden weiterhin doppelt gegeben und die das nächste Device geht an, bevor das vorige ausgeht. Das ist n der Praxis egal, wundert mich nur.

Jamo, dir auf jeden Fall besten Dank!

Jamo

#14
Schön!
Schaltbefehle: Sind das Homematic IP devices? Da habe ich das bei mir auch schon mal gesehen mit dem doppelten Event.
Hast Du auch das das 'attr Tischlampe_EZ event-on-change-reading state' gesetzt?

Wenn das vorherige device noch nicht aus ist, wenn das naechste an geht, einfach den delay sleep um 1 erhoehen, damit das angehen des naechsten devices nochmal verzoegert wird. Sooooo genau scheduled fhem das mit dem sleep/delay/on-for-timer dann auch nicht, weil alles in verschiedenen Zweigen gestartet wird.
Bullseye auf iNUC, Homematic + HMIP(UART/HMUSB), Debmatic, HUEBridge, Zigbee/Conbee III, FB7690, Alexa (fhem-lazy), Livetracking, LaCrosse JeeLink, LoRaWan / TTN / Chirpstack, Sonos, ESPresence