Hallo zusammen,
Ich sitze jetzt seit einiger Zeit an folgendem Problem.
Ich habe eine Bewässerungsanlage. (8 Ventile) welche nicht gleichzeitig laufen dürfen (ohne Feuchte Sensoren). Ich will nur, dass bei dem schalten eines Schalters Zeiten berechnet werden und zu diesen dann die einzelnen Ventile an sind. Wenn der Schalter ausgeschalten wird, werden die Zeiten zurückgesetzt.
Datzu habe ich jewils ein startzeit dummy und ein endzeit dummy
Bsp:
defmod bewaesserung_gemuesebeet_endzeit dummy
defmod bewaesserung_gemuesebeet_startzeit dummy
nach dem schalten steht in diesen exemplarisch dann auch der gewünschte Zeitbereich.
z.B.
startzeit:
state 22:08
endzeit:
state 23:08
In einem doif verwerte ich dann die beiden states:
defmod bewaesserung_zeitsteuerung DOIF ([[bewaesserung_gemuesebeet_startzeit]-[bewaesserung_gemuesebeet_endzeit]])(set sps.draussen.sprenger.gemuesebeet on)
Problem meines erachtens ist, dass in dem doif die Zeitstempel falsch verwertet werden:
cmd 0 2020-08-04 22:10:00
mode enabled 2020-08-04 22:10:00
state initialized 2020-08-04 22:10:00
timer_01_c01 05.08.2020 22:08:00 2020-08-04 22:10:00
timer_02_c01 04.08.2020 23:08:00 2020-08-04 22:10:00
Er macht hier automatisch von dem Startzeitpunkt den nächsten Tag und nicht den aktuellen.
Oder sehe ich das falsch? (Problem ist, es schaltet nichts :) )
Das sieht eher gut aus. Anscheinend wurden die Zeiten um 22:10 kalkuliert. Dann ist es normal, dass 01_c01 am nächsten Tag ist.
Jetzt sollte auch 02_c01 am 05.04 sein.
Wenn es nicht schaltet, hängt das wahrscheinlich am fehlenden do alwayw Attribut.
Zur Analyse wäre es besser, nächstes Mal ein "list" vom DOIF zu liefern.
Danke dir das hat geholfen. Jetzt schalten der Reihe nach die Ventile. Problem ist noch, dass diese nicht mehr ausgeschalten werden.
das doIf schaut jetzt so aus ( es gibt einen Schalter (bewaesserung_aktivieren) der auf auto mode, deactivate auto mode und manuell gesetzt werden kann)
jedes Ventil hat sein DoIf
defmod bewaesserung_zeitsteuerung_gemuesebeet DOIF ([bewaesserung_aktivieren] eq "startAutoMode" and [[bewaesserung_gemuesebeet_startzeit]-[bewaesserung_gemuesebeet_endzeit]])(set sps.draussen.sprenger.gemuesebeet on) DOELSEIF ([bewaesserung_aktivieren] eq "deactivateAutoMode" or [bewaesserung_aktivieren] eq "startAutoMode") (set sps.draussen.sprenger.gemuesebeet off)
Warum aktiviert er nicht den zweiten zweig wenn der Zeitbereich verlassen wurde?
Ich hab jetzt noch ein attr bewaesserung_zeitsteuerung_gemuesebeet selftrigger all dazu gesetzt das hilft aber nicht
so wie ich das sehe fehlt ihm beim verlassen des ersten Zeitbereichs irgend ein trigger. (obwohl ich das selftrigger all gesetzt habe)
Du hast keinen DOELSE-Zweig, der ausgeführt werden würde, wenn die Endzeit erreicht ist.
Zitat von: Damian am 05 August 2020, 23:48:29
Du hast keinen DOELSE-Zweig, der ausgeführt werden würde, wenn die Endzeit erreicht ist.
Den brauche ich eigentlich nicht da alle Zustände die ich behandeln will mit dem anderen zweigen abgedeckt sind. Bzw. Was sollte ich dann darin machen? Oder ist das nur für die richtige Funktion? Der Zweig wäre bei mir dann leer.
hab den else zweig jetzt eingesetzt und der strang wird dort dann deaktiviert. Ist es richtig, dass dieser Else Zweig nur erreicht wird wenn das erste DOIF deaktiviert wurde?
Zitat von: tunguskar am 06 August 2020, 09:20:23
hab den else zweig jetzt eingesetzt und der strang wird dort dann deaktiviert. Ist es richtig, dass dieser Else Zweig nur erreicht wird wenn das erste DOIF deaktiviert wurde?
Der ELSE-Zweig wird dann ausgeführt, wenn ein DOIF-Zweig aufgrund eines Triggers geprüft wurde und die Bedingung nicht wahr ist.
Zitat von: Damian am 06 August 2020, 11:46:38
Der ELSE-Zweig wird dann ausgeführt, wenn ein DOIF-Zweig aufgrund eines Triggers geprüft wurde und die Bedingung nicht wahr ist.
Komisch ist da nur, dass es mit dem else zweig funktioniert und mit dem ifelse zweig nicht
Abfrage schaut so aus (nur exemplarisch)
doif (aktiverZeitbereich AND schalterStehtAufAuto) (schalteVentilEin) elseIf (schalterStehtAufAuto OR schalterStehtAufDeaktivieren) (schalteVentilAus)
so geht es:
doif (aktiverZeitbereich AND schalterStehtAufAuto) (schalteVentilEin) elseIf (schalterStehtAufAuto OR schalterStehtAufDeaktivieren) (schalteVentilAus) else (schalteVentilAus)
Zitat von: tunguskar am 06 August 2020, 14:37:16
Komisch ist da nur, dass es mit dem else zweig funktioniert und mit dem ifelse zweig nicht
Abfrage schaut so aus (nur exemplarisch)
doif (aktiverZeitbereich AND schalterStehtAufAuto) (schalteVentilEin) elseIf (schalterStehtAufAuto OR schalterStehtAufDeaktivieren) (schalteVentilAus)
so geht es:
doif (aktiverZeitbereich AND schalterStehtAufAuto) (schalteVentilEin) elseIf (schalterStehtAufAuto OR schalterStehtAufDeaktivieren) (schalteVentilAus) else (schalteVentilAus)
Ich glaube, Du kannst ruhig die Aussagen von Damian (Entwickler von DOIF) trauen... und auch DOIF besser verstehen.
Zitatdoif (aktiverZeitbereich AND schalterStehtAufAuto) (schalteVentilEin) elseIf (schalterStehtAufAuto OR schalterStehtAufDeaktivieren) (schalteVentilAus)
Die Zeit triggert nur die erste Bedingung. Wenn das Ende der Zeitperiode erreicht ist, hat ohne DOELSE das DOIF keine Ausweichmöglichkeit und bleibt im ersten Zustand. Die zweite (DOELSEIF) Bedingung wird gar nicht geprüft, da sie keine Zeittrigger hat.
Die DOELSE Bedingung wird dagegen immer getriggert, wenn ein Trigger dazu führt, dass die Bedingung wo dieses Trigger enthalten ist nicht mehr wahr ist.
Was vielleicht ohne DOELSE funktionieren würde, wäre:
Zitatdoif (aktiverZeitbereich AND schalterStehtAufAuto) (schalteVentilEin) elseIf (nichtaktiverZeitbereich OR schalterStehtAufAuto OR schalterStehtAufDeaktivieren) (schalteVentilAus)
Zitat von: amenomade am 06 August 2020, 19:31:08
Ich glaube, Du kannst ruhig die Aussagen von Damian (Entwickler von DOIF) trauen... und auch DOIF besser verstehen.
Die Zeit triggert nur die erste Bedingung. Wenn das Ende der Zeitperiode erreicht ist, hat ohne DOELSE das DOIF keine Ausweichmöglichkeit und bleibt im ersten Zustand. Die zweite (DOELSEIF) Bedingung wird gar nicht geprüft, da sie keine Zeittrigger hat.
Die DOELSE Bedingung wird dagegen immer getriggert, wenn ein Trigger dazu führt, dass die Bedingung wo dieses Trigger enthalten ist nicht mehr wahr ist.
Was vielleicht ohne DOELSE funktionieren würde, wäre:
Sorry ich glaube das natürlich was er sagt. Ich will es nur verstehen. Komme aus der c Welt und bin etwas irritiert. Das mit dem nicht im Zeitbereich geht leider nicht und der else zweig macht mich grad nicht ganz glücklich, da ich dieses ventil nur von doif ausschalten will wenn der autoMode an ist. Im manuellen mode soll das nicht ausgeschalten werden. wenn irgend ein trigger kommt.
Zitat von: tunguskar am 06 August 2020, 21:50:57
Das mit dem nicht im Zeitbereich
Wie hast Du denn versucht, es zu implementieren?
Das ganze hat nicht wirklich mit C oder perl zu tun, sondern mit Events und Triggern
Zitatda ich dieses ventil nur von doif ausschalten will wenn der autoMode an ist
Dann mach einfach ein IF im Befehl deines DOELSE
Zitat von: amenomade am 06 August 2020, 21:55:25
Wie hast Du denn versucht, es zu implementieren?
Das ganze hat nicht wirklich mit C oder perl zu tun, sondern mit Events und Triggern
Prinzipiell schon da in c ein If()elseif()...else immer komplett abgearbeitet wird wenn die Bedingung darüber nicht wahr ist
DOIF (not[Zeitbereich] and schalterStehtAufAutoMode)(ventilZu) DOELSEIF ([zeitbereich] and schalterStehtAufAutoMode) (ventilAuf)
ich denke aber ich bin noch weit von dem Verstehen entfernt :-)
not[begin-end] geht ja nicht... aber [end-begin] geht.
Zum Verständnis hilft das Lesen von CommandRef:
ZitatDie Angaben werden immer von links nach rechts abgearbeitet. Logische Abfragen werden in DOIF/DOELSEIF-Bedingungen vornehmlich mit Hilfe von and/or-Operatoren erstellt. Zu beachten ist, dass nur die Bedingungen überprüft werden, die zum ausgelösten Event das dazughörige Device bzw. die dazugehörige Triggerzeit beinhalten. Kommt ein Device in mehreren Bedingungen vor, so wird immer nur ein Kommando ausgeführt, und zwar das erste, für das die dazugehörige Bedingung in der abgearbeiteten Reihenfolge wahr ist.
Das DOIF-Modul arbeitet mit Zuständen. Jeder Ausführungszweig DOIF/DOELSEIF..DOELSEIF/DOELSE stellt einen eigenen Zustand dar (cmd_1, cmd_2, usw.). Das Modul merkt sich den zuletzt ausgeführten Ausführungszweig und wiederholt diesen standardmäßig nicht. Ein Ausführungszweig wird erst dann wieder ausgeführt, wenn zwischenzeitlich ein anderer Ausführungszweig ausgeführt wurde, also ein Statuswechsel des DOIF-Moduls stattgefunden hat. Dieses Verhalten ist sinnvoll, um zu verhindern, dass zyklisch sendende Sensoren (Temperatur, Feuchtigkeit, Helligkeit, usw.) zu ständiger Wiederholung des selben Befehls oder Befehlsabfolge führen.
Du musst im Sinn von EVENTS denken. Das kann man auch in C++ machen, das ist aber ein andere Art von Programmierung als eine sequenzielle Programmierung.
Wenn ich grob schematisiere:
DOIF([begin-end]) bedeutet irgendwie "wenn begin oder end erreicht werden (das sind Zeit Events), ist diese Bedingung betroffen, und es wird getestet, ob es wahr ist, und ggf den Befehl ausgeführt".
DOIF ([device:reading] eq "blabla") bedeutet "wenn ein Event auf Device / Reading kommt, ist diese Bedingung betroffen, und ...
Du kannst es einfacher, und vielleicht verständlicher machen: Ich versuch es mal in Deiner Schreibweise:
Zitatdoif (aktiverZeitbereich AND schalterStehtAufAuto) (schalteVentilEin) elseIf (schalterStehtAufAuto OR schalterStehtAufDeaktivieren) (schalteVentilAus) else (schalteVentilAus)
könnte auch so aussehen:
doif (Startzeit AND schalterStehtAufAuto) (schalteVentilEin) DoelseIf (Stoppzeit OR schalterStehtAufAuto OR schalterStehtAufDeaktivieren) (schalteVentilAus)
wenn Du in DOIF einen Zeitbereich angibst [xx:xx-yy:yy] passiert nichts anderes, als dass 2 timer angelegt werden mit den Zeiten xx:xx und yy:yy. Zum Zeitpunkt xx:xx wird der "Zeitbereich" in der Bedingung wahr (true), zum Zeitpunkt yy:yy wird er unwahr (false). Mehr nicht! Das DOIF "denkt" da nicht irgendwie innerhalb oder ausserhalb eines Bereiches, es geht nur um Zeitpunkte, die den "Zeitbereich" triggern.
Der Hinweis auf die CommandRef von amenomade bzgl. Abarbeiten der bedingungen und wann damit aufgehört wird ist allerdings sehr wichtig fürs Verständnis von DOIF.
Gruß
Sany
P.S. wie auch schon häufigst erwähnt und gebeten: Code, Device-Definitionen und Lists von Devices in Code-tags, das ist viel leserlicher und man könnte auch einfach mal eine (funktionierende) Korrektur machen.
Zitat von: amenomade am 06 August 2020, 22:15:33
not[begin-end] geht ja nicht... aber [end-begin] geht.
Zum Verständnis hilft das Lesen von CommandRef:
Du musst im Sinn von EVENTS denken. Das kann man auch in C++ machen, das ist aber ein andere Art von Programmierung als eine sequenzielle Programmierung.
Wenn ich grob schematisiere:
DOIF([begin-end]) bedeutet irgendwie "wenn begin oder end erreicht werden (das sind Zeit Events), ist diese Bedingung betroffen, und es wird getestet, ob es wahr ist, und ggf den Befehl ausgeführt".
DOIF ([device:reading] eq "blabla") bedeutet "wenn ein Event auf Device / Reading kommt, ist diese Bedingung betroffen, und ...
Jetzt hab ich's dank dir so gehts.
Zitat von: Sany am 06 August 2020, 23:19:00
Du kannst es einfacher, und vielleicht verständlicher machen: Ich versuch es mal in Deiner Schreibweise:
könnte auch so aussehen:
doif (Startzeit AND schalterStehtAufAuto) (schalteVentilEin) DoelseIf (Stoppzeit OR schalterStehtAufAuto OR schalterStehtAufDeaktivieren) (schalteVentilAus)
wenn Du in DOIF einen Zeitbereich angibst [xx:xx-yy:yy] passiert nichts anderes, als dass 2 timer angelegt werden mit den Zeiten xx:xx und yy:yy. Zum Zeitpunkt xx:xx wird der "Zeitbereich" in der Bedingung wahr (true), zum Zeitpunkt yy:yy wird er unwahr (false). Mehr nicht! Das DOIF "denkt" da nicht irgendwie innerhalb oder ausserhalb eines Bereiches, es geht nur um Zeitpunkte, die den "Zeitbereich" triggern.
Der Hinweis auf die CommandRef von amenomade bzgl. Abarbeiten der bedingungen und wann damit aufgehört wird ist allerdings sehr wichtig fürs Verständnis von DOIF.
Gruß
Sany
P.S. wie auch schon häufigst erwähnt und gebeten: Code, Device-Definitionen und Lists von Devices in Code-tags, das ist viel leserlicher und man könnte auch einfach mal eine (funktionierende) Korrektur machen.
Dank dir für die Erklärung, jetzt wird's klarer. Das mit der device-Definition Kommt dann noch :)