WebUI Programmlogik - einfach erklärt am "lebenden Objekt"

Problemlösungen und Hinweise von allgemeinem Interesse zur Haussteuerung mit HomeMatic

Moderator: Co-Administratoren

gzi
Beiträge: 450
Registriert: 12.01.2015, 23:37
System: CCU
Hat sich bedankt: 15 Mal
Danksagung erhalten: 14 Mal

WebUI Programmlogik - einfach erklärt am "lebenden Objekt"

Beitrag von gzi » 13.07.2018, 18:28

Hallo Leute!
Das Thema wurde schon oft diskutiert. Zuletzt wieder hier. An Beschreibungen herrscht kein Mangel (z.B. hier). Die Frage ist: Wie kann man das möglichst einfach (aber doch korrekt) erklären?

Update 21.2.2019: Testfall 6 und 7 im Skript ergänzt,
Update 27.2.2019: Auslösebedingung exakter beschrieben
Update 5.3. 2019: Auslösebedingung im Beispiel rot markiert

Also mal ein neuer Ansatz. Nicht beschreiben, sondern am "lebenden Objekt" zeigen.

Dazu habe ich
  • Systemvariablen angelegt _test_var1 - _test_var3 (jeweils integer) sowie Trace (string)
  • Ein Skript mit Testfällen erstellt, das den _test_var unterschiedliche Werte zuweist

    Code: Alles auswählen

    ! Testscript: manuell starten!
    ! .
    ! Testfall 1
    ! .
       WriteLine("Testfall 1: ");
    !  Reset
       dom.GetObject("_test_var1").State(0);
       dom.GetObject("_test_var2").State(0);
       dom.GetObject("_test_var3").State(0); 
       dom.GetObject("Trace").State("none");
    !  Programm _test_pgm auslösen
       dom.GetObject("_test_var2").State(1);
       WriteLine("_test_pgm: Auslöser _test_var1, var2=1, var3=0");
       dom.GetObject("_test_var1").State(1);
    !  Ergebnis ausgeben - die wiederholten GetObject Anweisungen dienen nur dazu, dass nach dem Auslösen 
    !  des Programms ein wenig Zeit vergeht, damit das Programm die Trace Variable setzen kann, bevor sie im
    !  WriteLine weiter unten ausgegeben wird.
       dom.GetObject("Trace").Value();
       dom.GetObject("Trace").Value();
       dom.GetObject("Trace").Value();
       dom.GetObject("Trace").Value();
       dom.GetObject("Trace").Value();
       dom.GetObject("Trace").Value();
       dom.GetObject("Trace").Value();
       dom.GetObject("Trace").Value();
       dom.GetObject("Trace").Value();
       dom.GetObject("Trace").Value();
       dom.GetObject("Trace").Value();
          WriteLine("Testergebnis: "#dom.GetObject("Trace").Value());
    ! .
    ! Testfall 2a
    ! .
       WriteLine("Testfall 2a: ");
    !  Reset
       dom.GetObject("_test_var1").State(0);
       dom.GetObject("_test_var2").State(0);
       dom.GetObject("_test_var3").State(0); 
       dom.GetObject("Trace").State("none");
    !  Programm _test_pgm auslösen
       dom.GetObject("_test_var2").State(2);
        WriteLine("Auslöser _test_var1, var2=2, var3=0");
        dom.GetObject("_test_var1").State(1);
    !  Ergebnis ausgeben
       dom.GetObject("Trace").Value();
       dom.GetObject("Trace").Value();
       dom.GetObject("Trace").Value();
       dom.GetObject("Trace").Value();
       dom.GetObject("Trace").Value();
       dom.GetObject("Trace").Value();
       dom.GetObject("Trace").Value();
       dom.GetObject("Trace").Value();
       dom.GetObject("Trace").Value();
       dom.GetObject("Trace").Value();
       dom.GetObject("Trace").Value();
       WriteLine("Testergebnis: "#dom.GetObject("Trace").Value());
    ! .
    ! Testfall 2b
    ! .
       WriteLine("Testfall 2b: ");
    !  Reset
       dom.GetObject("_test_var1").State(0);
       dom.GetObject("_test_var2").State(0);
       dom.GetObject("_test_var3").State(0); 
       dom.GetObject("Trace").State("none");
    !  Programm _test_pgm auslösen
       dom.GetObject("_test_var2").State(2);
        WriteLine("Auslöser _test_var3");
        dom.GetObject("_test_var3").State(1);
    !  Ergebnis ausgeben
       dom.GetObject("Trace").Value();
       dom.GetObject("Trace").Value();
       dom.GetObject("Trace").Value();
       dom.GetObject("Trace").Value();
       dom.GetObject("Trace").Value();
       dom.GetObject("Trace").Value();
       dom.GetObject("Trace").Value();
       dom.GetObject("Trace").Value();
       dom.GetObject("Trace").Value();
       dom.GetObject("Trace").Value();
       dom.GetObject("Trace").Value();
       WriteLine("Testergebnis: "#dom.GetObject("Trace").Value());
    ! .
    ! Testfall 3
    ! .
       WriteLine("Testfall 3: ");
    !  Reset
       dom.GetObject("_test_var1").State(0);
       dom.GetObject("_test_var2").State(0);
       dom.GetObject("_test_var3").State(0); 
       dom.GetObject("Trace").State("none");
    !  Programm _test_pgm auslösen
       dom.GetObject("_test_var2").State(3);
       WriteLine("Auslöser _test_var3, var1=0, var2=3");
       dom.GetObject("_test_var3").State(1);
    !  Ergebnis ausgeben
       dom.GetObject("Trace").Value();
       dom.GetObject("Trace").Value();
       dom.GetObject("Trace").Value();
       dom.GetObject("Trace").Value();
       dom.GetObject("Trace").Value();
       dom.GetObject("Trace").Value();
       dom.GetObject("Trace").Value();
       dom.GetObject("Trace").Value();
       dom.GetObject("Trace").Value();
       dom.GetObject("Trace").Value();
       dom.GetObject("Trace").Value();
       WriteLine("Testergebnis: "#dom.GetObject("Trace").Value());
    ! .
    ! Testfall 5
    ! .
       WriteLine("Testfall 5: ");
    !  Reset
       dom.GetObject("_test_var1").State(0);
       dom.GetObject("_test_var2").State(0);
       dom.GetObject("_test_var3").State(0); 
       dom.GetObject("Trace").State("none");
    !  Programm _test_pgm auslösen
       WriteLine("Auslöser _test_var1, var2=0, var3=0");
       dom.GetObject("_test_var1").State(1);
    !  Ergebnis ausgeben
       dom.GetObject("Trace").Value();
       dom.GetObject("Trace").Value();
       dom.GetObject("Trace").Value();
       dom.GetObject("Trace").Value();
       dom.GetObject("Trace").Value();
       dom.GetObject("Trace").Value();
       dom.GetObject("Trace").Value();
       dom.GetObject("Trace").Value();
       dom.GetObject("Trace").Value();
       dom.GetObject("Trace").Value();
       dom.GetObject("Trace").Value();
    
       WriteLine("Testergebnis: "#dom.GetObject("Trace").Value());
    ! .
    ! Testfall 5b
    ! .
       WriteLine("Testfall 5b: ");
    !  Reset
       dom.GetObject("_test_var1").State(0);
       dom.GetObject("_test_var2").State(0);
       dom.GetObject("_test_var3").State(0); 
       dom.GetObject("Trace").State("none");
    !  Programm _test_pgm auslösen
       WriteLine("Auslöser _test_var3, var2=1, var3=0");
       dom.GetObject("_test_var2").State(1);
       dom.GetObject("_test_var3").State(1);
    !  Ergebnis ausgeben
       dom.GetObject("Trace").Value();
       dom.GetObject("Trace").Value();
       dom.GetObject("Trace").Value();
       dom.GetObject("Trace").Value();
       dom.GetObject("Trace").Value();
       dom.GetObject("Trace").Value();
       dom.GetObject("Trace").Value();
       dom.GetObject("Trace").Value();
       dom.GetObject("Trace").Value();
       dom.GetObject("Trace").Value();
       dom.GetObject("Trace").Value();
       WriteLine("Testergebnis: "#dom.GetObject("Trace").Value());
    ! .
    ! Testfall 5c
    ! .
       WriteLine("Testfall 5c: ");
    ! reset
       dom.GetObject("Trace").State("none");
    !  Auslöservariable auf irgendeinen wert ändern   
        WriteLine("test_var1=57, var2=1, var3=0");
       dom.GetObject("_test_var1").State(57);
    !  Ergebnis ausgeben - die wiederholten GetObject Anweisungen dienen nur dazu, dass nach dem Auslösen 
    !  des Programms ein wenig Zeit vergeht, damit das Programm die Trace Variable setzen kann, bevor sie im
    !  WriteLine weiter unten ausgegeben wird.
       dom.GetObject("Trace").Value();
       dom.GetObject("Trace").Value();
       dom.GetObject("Trace").Value();
       dom.GetObject("Trace").Value();
       dom.GetObject("Trace").Value();
       dom.GetObject("Trace").Value();
       dom.GetObject("Trace").Value();
       dom.GetObject("Trace").Value();
       dom.GetObject("Trace").Value();
       dom.GetObject("Trace").Value();
       dom.GetObject("Trace").Value();
       WriteLine("Testergebnis: "#dom.GetObject("Trace").Value());
    ! Testscript: manuell starten!
    ! .
    ! Testfall 6
    ! .
       WriteLine("Testfall 6: ");
    !  Reset
       dom.GetObject("_test_var1").State(0);
       dom.GetObject("Trace").State("");
    
    !  Programm _test_pgm_sonst auslösen
       dom.GetObject("_test_var1").State(150);
       WriteLine("Auslöser _test_var1=150");
    
    !  Ergebnis ausgeben - die wiederholten GetObejt Anweisungen dienen nur dazu, dass nach dem Auslösen 
    !  des Programms ein wenig Zeit vergeht, damit das Programm die Trace Variable setzen kann, bevor sie im
    !  WriteLine weiter unten ausgegeben wird.
       dom.GetObject("Trace").Value();
       dom.GetObject("Trace").Value();
       dom.GetObject("Trace").Value();
       dom.GetObject("Trace").Value();
       dom.GetObject("Trace").Value();
       dom.GetObject("Trace").Value();
       dom.GetObject("Trace").Value();
       dom.GetObject("Trace").Value();
       dom.GetObject("Trace").Value();
       dom.GetObject("Trace").Value();
       dom.GetObject("Trace").Value();
          WriteLine("Testergebnis: "#dom.GetObject("Trace").Value());
    ! .
    ! Testfall 7
    ! .
       WriteLine("Testfall 7: ");
    !  Programm _test_pgm_sonst auslösen
       dom.GetObject("_test_var1").State(300);
       WriteLine("Auslöser _test_var1=300");
    
    !  Ergebnis ausgeben - die wiederholten GetObejt Anweisungen dienen nur dazz, dass nach dem Auslösen 
    !  des Programms ein wenig Zeit vergeht, damit das Programm die Trace Variable setzen kann, bevor sie im
    !  WriteLine weiter unten ausgegeben wird.
       dom.GetObject("Trace").Value();
       dom.GetObject("Trace").Value();
       dom.GetObject("Trace").Value();
       dom.GetObject("Trace").Value();
       dom.GetObject("Trace").Value();
       dom.GetObject("Trace").Value();
       dom.GetObject("Trace").Value();
       dom.GetObject("Trace").Value();
       dom.GetObject("Trace").Value();
       dom.GetObject("Trace").Value();
       dom.GetObject("Trace").Value();
          WriteLine("Testergebnis: "#dom.GetObject("Trace").Value());
    ! .
       
    
  • zwei Programme erstellt, die durch Werteänderungen von _test_var1 und _test_var3 ausgelöst werden.
    testskript.jpg
    _test_pgm
    Unbenannt.JPG
    _test_pgm_sonst
  • Dann mit "Skript Testen" das Skript laufen lassen.
Das ergibt folgendes Ergebnis:

Code: Alles auswählen

Testfall 1: 
_test_pgm: Auslöser _test_var1, var2=1, var3=0
Testergebnis: _test: 1. Dann... (_test_var2=1)
Testfall 2a: 
Auslöser _test_var1, var2=2, var3=0
Testergebnis: _test: 2. Sonst, wenn... _test_var2 =2
Testfall 2b: 
Auslöser _test_var3
Testergebnis: _test: 2. Sonst, wenn... _test_var2 =2
Testfall 3: 
Auslöser _test_var3, var1=0, var2=3
Testergebnis: _test: 3. Sonst, wenn... (_test_var2 = egal) =1
Testfall 5: 
Auslöser _test_var1, var2=0, var3=0
Testergebnis: _test: 5. Sonst... (Zweig ohne Bedingungen)
Testfall 5b: 
Auslöser _test_var3, var2=1, var3=0
Testergebnis: _test: 5. Sonst... (Zweig ohne Bedingungen)
Testfall 5c: 
test_var1=57, var2=1, var3=0
Testergebnis: none
Testfall 6: 
Auslöser _test_var1=150
Testergebnis: _test_pgm_sonst: Aktivität:Dann durchlaufen
Testfall 7: 
Auslöser _test_var1=300
Testergebnis: _test_pgm_sonst: Aktivität:Sonst durchlaufen 
Mit diesem "Handwerkszeug" kann man natürlich recht einfach auch andere Situationen durchspielen. Zum Beispiel prüfen, was passiert wenn man die CCU neu bootet, oder das Programm manuell startet (der erste Aktivitäten Zweig wird durchlaufen und "Trace" steht auf: "_test: 1. Dann... (_test_var2=1)" auch wenn _test_var2 = 0 ist).

Als Erklärung, warum das alles so ist, am Ende doch noch der Versuch einer möglichst kurzen Beschreibung. Unterscheide zwischen
  • dem Ereignis (Auslöser)
  • der Bedingung, ob ein Programm ausgelöst(gestartet) wird (Auslösebedingung) und
  • den Bedingungen, die steuern welcher "Aktivität:"-Block im Programm ausgeführt wird (Auswahlbedingung)
Zwischenablage01.jpg
Auslöser, Auslösebedingung und Auswahlbedingung

  • Programme werden ausgelöst, wenn sie entweder
    • manuell (übers WebUI) gestartet werden,
    • wenn die CCU neu gestartet wird **) oder
    • wenn irgendeine im Programm angegebene Auslösebedingung *) zutrifft. Das kann die Änderung einer Systemvariaben, die kein String ist (wie im Beispiel oben) sein, die Änderung eines Geräte-Datenpunkts oder eine Zeit-Steuerung . Das _test_pgm wird also ausgelöst wenn sich entweder _test_var1 oder _test_var3 ändert
    • Es ist egal wo, also in welchem "Bedingung:"-Abschnitt eine Auslösebedingung steht. Sie kann also auch unterhalb des "Aktivität: Dann..."-Blocks stehn, der zur Ausführung kommt bzw. in irgend einem "Bedingung: "-Block stehen. Siehe Testfall 2b
  • Nach dem Starten/Auslösen des Programms wird der erste (und kein weiterer!) "Aktivität: Dann..."- Block ausgeführt für den die Auswahlbedingungen (im obigen Beispiel grün eingerahmt) in dem unmittelbar davor stehenden "Bedingung:"-Block zutreffen **).
    • Das sind neben "nur prüfen"-Bedingungen auch Bedingungen die in der selben Zeile wie ein Auslöser stehen (oben z.B. "im Wertebereich von bis").
    • AUSNAHME: Wird das Programm manuell gestartet/ausgelöst dann wird immer der erste "Aktivität: Dann..."- Block ausgeführt, egal welche Auslöse- oder Auswahlbedingungen davor stehen.
  • Alle anderen "Aktivität: Dann..."-Blöcke werden nicht durchlaufen. Es gibt also keine geschachtelten IF's wie in anderen Programmiersprachen.
  • Wird das Programm zwar ausgelöst, aber es trifft keine Auswahlbedingung für einen "Aktivität: Dann..."-Block zu, dann wird der "Aktivität: Sonst..."-Block durchlaufen
*) Auslösebedingungen (Im obigen Beispiel rot eingerahmt) bestehen aus Auslöser "bei Änderung auslösen", "bei Aktualisierung auslösen" oder "zu Zeitpunkten auslösen" (Im obigen Beispiel blau eingerahmt) plus die davorstehende Wertebereichs oder Zeitraumangabe (siehe Testfall 6)
**) Beim Neustarten der CCU werden vor dem Auslösen von Programmen alle Systemvariablen und Datenpunkte (Status von Geräten) auf den zuletzt bekannten Zustand gesetzt. Ausnahme ist die Systemvariable "Anwesenheit": diese wird immer auf "wahr" gesetzt. Das kann man dazu verwenden, um zu verhindern, dass ein "Aktivität:"-Block bei Neustart ausgeführt wird (siehe z.B. hier).

gzi
Zuletzt geändert von gzi am 05.03.2019, 22:13, insgesamt 6-mal geändert.
Lichtsteuerung, Heizungssteuerung, Überwachung (Feuer, Wasser, Einbruch, Stromausfall, Heizungsausfall, Wetter, Kamera), Alarmierung (optisch, akustisch, mail, SMS, voice call) - CCU, diverse HM- und HMIP Aktoren und Sensoren, Rauchmeldeanlage, UPS, GSM-Alarmwähler, Zugriff aus dem Internet via HTTPS und htdigest authentication, kein Datenkraken-Interface (Google, Amazon, China-Cloud, BND, NSA...) - HomeMatic Sicherheits-Kompendium - Checkliste für Auswahl von IP Kameras - Vergleich aktueller HomeMatic Zentralen - und alle Antworten für das gesamte Universum und den Rest

66er
Beiträge: 3083
Registriert: 23.08.2015, 11:06
System: CCU
Hat sich bedankt: 116 Mal
Danksagung erhalten: 111 Mal

Re: WebUI Programmlogik - einfach erklärt am "lebenden Objekt"

Beitrag von 66er » 13.07.2018, 19:51

Hallo gzi,

Ich gehe davon aus, dass Du mit Deinem Beitrag Anfängern lobenswerter Weise helfen wolltest. Und genau wegen der (unterstellten) Adressatengruppe kann ich das nicht unkommentiert stehen lassen, da leider Fehler und Halbwahrheiten enthalten sind. :shock:

In "Rot" füge ich mal meine Korrekturen/Ergänzungen ein:
gzi hat geschrieben:
13.07.2018, 18:28
...
Als Erklärung, warum das alles so ist, doch noch der Versuch einer möglichst kurzen Beschreibung:
  • Programme starten immer, wenn sie entweder
    • manuell ausgelöst werden, wobei dann automatisch und ohne Berücksichtigung der WENN-Bedingungen der 1. DANN-Zweig ausgeführt wird :!: Deine Aussage impliziert, dass die Programme starten und regulär abgearbeitet werden. :wink:
    • wenn die CCU neu gestartet wird oder hierzu sei auf die Vermeidbarkeit/Einflussnahmemöglichkeit, die in diesem Thread beschrieben wird, hingewiesen
    • wenn eine Auslösebedingung zutrifft.... Es ist egal wo, also in welchem "Bedingung:"-Abschnitt wine Auslösebedingung stehen. Kann also auch weiter unten in irgend einem "Bedingung: Sonst"-Block stehen. :shock: Seit wann löst ein SONST-Zweig ein Programm aus :?: Vermutlich sollte hier ein "SONSTWENN" stehen :?: :!:
  • Nach dem Starten/Auslösen des Programms wird der erste (und kein weiterer!) "Aktivität: Dann..."- Block ausgeführt für den alle Bedingungen (Ausnahme siehe oben) in dem davorstehenden "Bedingung:"-Block zutreffen. Das sind neben "nur prüfen"-Bedingungen aber Bedingungen bei Auslösern (oben z.B. "im Wertebereich von bis").
    ...
Versuch gescheitert, sorry.

LG
Stefan

Benutzeravatar
JRiemann
Beiträge: 3903
Registriert: 12.11.2015, 21:05
Wohnort: Aurich
Danksagung erhalten: 3 Mal

Re: WebUI Programmlogik - einfach erklärt am "lebenden Objekt"

Beitrag von JRiemann » 13.07.2018, 20:01

Programme starten auch nicht wenn eine Auslösebedingung zutrifft!
Ausgelöst wird wenn sich der Wahrheitsgehalt der Bedingung ändert. Egal ob die Bedingung dann falsch/richtig ist.
"bei Aktualisierung" löst bei JEDER Statusmeldung des Objekts aus, egal ob sich der Status ändert oder nicht.
Viele Grüße!
Jörg

66er
Beiträge: 3083
Registriert: 23.08.2015, 11:06
System: CCU
Hat sich bedankt: 116 Mal
Danksagung erhalten: 111 Mal

Re: WebUI Programmlogik - einfach erklärt am "lebenden Objekt"

Beitrag von 66er » 13.07.2018, 20:04

Danke für Deine Ergänzungen, Jörg.

Die Punkte hatte ich leider übersehen. :(

LG
Stefan

gzi
Beiträge: 450
Registriert: 12.01.2015, 23:37
System: CCU
Hat sich bedankt: 15 Mal
Danksagung erhalten: 14 Mal

Re: WebUI Programmlogik - einfach erklärt am "lebenden Objekt"

Beitrag von gzi » 14.07.2018, 17:45

66er hat geschrieben:
13.07.2018, 19:51
kann ich das nicht unkommentiert stehen lassen, da leider Fehler und Halbwahrheiten enthalten sind. :shock:
...Deine Aussage impliziert, dass die Programme starten und regulär abgearbeitet werden
Du hast übersehen, dass beim zweiten Punkt auch explizit steht, dass beim manuellen Programmstart immer der erste Aktivität:-Block ausgeführt wird. Ich habe aber jetzt einen Satz vorangestellt um klarzumachen, dass ich zuerst die Programm-Auslösung und dann erst die Auswahl des Aktivät-Blocks beschreibe.
66er hat geschrieben: hierzu sei auf die Vermeidbarkeit/Einflussnahmemöglichkeit, die in diesem Thread beschrieben wird, hingewiesen
Ja, das kann man ergänzen. Aber ein Fehler ist es nicht.
66er hat geschrieben: ... Es ist egal wo ... eine Auslösebedingung stehen. Kann also auch weiter unten in irgend einem "Bedingung: Sonst"-Block stehen. :shock: Seit wann löst ein SONST-Zweig ein Programm aus :?: Vermutlich sollte hier ein "SONSTWENN" stehen :?: :!:
Da bei einem "Sonst"-Block gar keine Bedingungen stehen können, ist natürlich ein "Sonst, wenn"-Block gemeint.
66er hat geschrieben: Versuch gescheitert, sorry.
Na, wenn Du das meinst, Stefan.
JRiemann hat geschrieben:
13.07.2018, 20:01
Programme starten auch nicht wenn eine Auslösebedingung zutrifft!
Meinst Du damit, dass es auch sein kann, dass ein Programm zwar ausgelöst wird, aber dann keine Aktivität erfolgt? Das stimmt, widerspricht meiner Beschreibung aber nicht.
JRiemann hat geschrieben: Ausgelöst wird wenn sich der Wahrheitsgehalt der Bedingung ändert. Egal ob die Bedingung dann falsch/richtig ist.
Das stimmt so nicht (jedenfalls nicht generell), oder ich verstehe nicht was Du sagen willst. Beispiel?
JRiemann hat geschrieben: "bei Aktualisierung" löst bei JEDER Statusmeldung des Objekts aus, egal ob sich der Status ändert oder nicht.
Ja, denn "bei Aktualisierung" ist genau die Auslösebedingung. Ich habe das in der überarbeiteten version in einer Fußnote klargestellt.

Wie ich anfangs geschrieben habe. Die WebUI Logik kurz und knapp und doch so zu beschreiben, dass es keiner missversteht, ist eben schwierig.

gzi
Lichtsteuerung, Heizungssteuerung, Überwachung (Feuer, Wasser, Einbruch, Stromausfall, Heizungsausfall, Wetter, Kamera), Alarmierung (optisch, akustisch, mail, SMS, voice call) - CCU, diverse HM- und HMIP Aktoren und Sensoren, Rauchmeldeanlage, UPS, GSM-Alarmwähler, Zugriff aus dem Internet via HTTPS und htdigest authentication, kein Datenkraken-Interface (Google, Amazon, China-Cloud, BND, NSA...) - HomeMatic Sicherheits-Kompendium - Checkliste für Auswahl von IP Kameras - Vergleich aktueller HomeMatic Zentralen - und alle Antworten für das gesamte Universum und den Rest

Benutzeravatar
JRiemann
Beiträge: 3903
Registriert: 12.11.2015, 21:05
Wohnort: Aurich
Danksagung erhalten: 3 Mal

Re: WebUI Programmlogik - einfach erklärt am "lebenden Objekt"

Beitrag von JRiemann » 14.07.2018, 18:55

Nun ja, wenn Du einen Thread schreibst in dem Du die Logik erklären willst, dann solltest Du sie selbst zu 100% verstehen.
Oder wenn Du sie verstanden hast auch alles so erklären das keine Zweifel aufkommen.

Ich gehe jetzt mal nur auf die mich betreffenden Punkte ein, Stefan wird sich das selbe für seinen Teil tun.
Das stimmt so nicht (jedenfalls nicht generell), oder ich verstehe nicht was Du sagen willst. Beispiel?
Du hast geschrieben: wenn eine im Programm angegebene Auslösebedingung *) zutrifft.
(Erst durch die nachträglich angelegte Fußnote könnte man es als halbwegs richtig durchgehen lassen. Fußnoten machen eine Erklärung aber nicht verständlicher für Anfänger).
Ohne Fußnote betrachtet ist die Aussage aber falsch, egal ob nur missverständlich ausgedrückt oder aus Unwissenheit. Zumindest wird der unerfahrene Leser es garantiert falsch auffassen.
Wenn Du von Bedingung sprichst wird allgemein davon ausgegangen das die Bedingung der Zeile gemeint ist (z.B. WENN - Astrozeit Tag - zu Zeitpunkten). Hier ist eben TAG die Bedingung und die Änderung von Astrozeit TAG der Auslöser. Zum auslösen des Programms kommt es aber nicht nur wenn diese Bedingung erfüllt ist, sondern eben wenn sich der Wahrheitsgehalt ändert. Also bei Wechsel von Nacht zu Tag (true) aber auch bei Tag zu Nacht (false). Nicht ohne Grund nennt sich der Auslöser "zu Zeitpunkten auslösen". Erst nach dem Auslösen wird der Wahrheitsgehalt der Bedingung relevant und entscheidet den weiteren Ablauf.
Meinst Du damit, dass es auch sein kann, dass ein Programm zwar ausgelöst wird, aber dann keine Aktivität erfolgt?
Das ist dann die logische Folge aus der vorherigen Erklärung. Also nochmal das Beispiel:

Code: Alles auswählen

WENN - Astrozeit Tag - zu Zeitpunkten auslösen
DANN - ROLL - öffnen
Wechselt der Status von Nacht zu Tag wird das Programm ausgelöst, jetzt wird die Bedingung "Tag" geprüft, sie ist jetzt wahr, das DANN wird ausgeführt.
Wechselt der Status von Tag zu Nacht wird das Programm ausgelöst, jetzt wird die Bedingung "Tag" geprüft, sie ist jetzt falsch, keine Aktion erfolgt.
Anders wäre es mit einem SONST-Zweig:

Code: Alles auswählen

WENN - Astrozeit Tag - zu Zeitpunkten auslösen
DANN - ROLL - öffnen
SONST - ROLL - schließen
Wechselt der Status von Nacht zu Tag wird das Programm ausgelöst, jetzt wird die Bedingung "Tag" geprüft, sie ist jetzt wahr, das DANN wird ausgeführt.
Wechselt der Status von Tag zu Nacht wird das Programm ausgelöst, jetzt wird die Bedingung "Tag" geprüft, sie ist jetzt falsch, das SONST wird ausgeführt.
Ein Programm mit einem SONST führt somit bei jedem Durchlauf zu einer Aktion.
Ja, denn "bei Aktualisierung" ist genau die Auslösebedingung.
Auch hier gilt die selbe Anmerkung wie oben. Missverständlich ausgedrückt oder falsch verstanden. Der Auslöser sagt nur aus das der Status des Objekts sich aktualisieren muss damit eine Prüfung angestoßen wird. Auch hier ist es fürs auslösen egal ob die enthaltene Bedingung erfüllt ist oder nicht.
Der Unterschied zwischen "Änderung" und "Aktualisierung" liegt lediglich in der Häufigkeit des auslösens.
Die WebUI Logik kurz und knapp und doch so zu beschreiben, dass es keiner missversteht, ist eben schwierig.
Ich würde behaupten das ist kurz und knapp nicht zu realisieren. Darum hat Deine Beschreibung auch dieses "böse" Echo. Selbst wenn man das richtige meint ist es sehr schwer es so zu schreiben das wirklich jeder es richtig versteht.
Viele Grüße!
Jörg

Xel66
Beiträge: 14085
Registriert: 08.05.2013, 23:33
System: Alternative CCU (auf Basis OCCU)
Wohnort: Nordwürttemberg
Hat sich bedankt: 580 Mal
Danksagung erhalten: 1492 Mal

Re: WebUI Programmlogik - einfach erklärt am "lebenden Objekt"

Beitrag von Xel66 » 14.07.2018, 19:09

JRiemann hat geschrieben:
14.07.2018, 18:55
Der Unterschied zwischen "Änderung" und "Aktualisierung" liegt lediglich in der Häufigkeit des auslösens.
Kleine Ergänzung. Die Häufigkeit ist gleich, lediglich wird bei "Änderung" der Wahrheitsgehalt noch zusätzlich mit dem vorherigen Status abgeglichen. Ergibt also nur WAHR, wenn sich der Zustand des Triggers geändert hat. Im Falle von "bei Aktualisierung" ist diese Teilprüfung immer WAHR.

Insofern ist die Erklärung am Beispiel Tag/Nacht etwas unglücklich, weil nicht aktualisiert werden kann. Ein Bewegungsmelder ist vielleicht geeigneter. Wenn man ein Programm hat, welches bei erkannter Bewegung einen Aktor einschaltet und auf "Änderung" prüft/triggert, wird der Aktor auch bei dauerhafter Bewegung nur einmalig bei der ersten erkannten Bewegung eingeschaltet. Erst wenn zwischenzeitlich "keine Bewegung" erkannt wird, wird wieder eingeschaltet. Darum benutzt man in diesem Falle z.B. "bei Aktualisierung". Dieses triggert immer wieder nach, weil jede Übermittlung der Bewegung nach der Mindestabstandszeit ein WAHR ergibt. Eine solche Anwendung würde man im Normalfall aber durch eine Direktverknüpfung lösen, die das Nachtriggern selbst erledigt.


Gruß Xel66
-------------------------------------------------------------------------------------------
524 Kanäle in 146 Geräten und 267 CUxD-Kanäle in 34 CUxD-Geräten:
343 Programme, 334 Systemvariablen und 183 Direktverknüpfungen,
RaspberryMatic Version: 3.65.11.20221005 + Testsystem: CCU2 2.61.7
-------------------------------------------------------------------------------------------
Einsteigerthread, Programmlogik-Thread, WebUI-Handbuch

Benutzeravatar
JRiemann
Beiträge: 3903
Registriert: 12.11.2015, 21:05
Wohnort: Aurich
Danksagung erhalten: 3 Mal

Re: WebUI Programmlogik - einfach erklärt am "lebenden Objekt"

Beitrag von JRiemann » 14.07.2018, 19:49

Die Häufigkeit ist gleich,
In dem Beispiel Tag/Nacht mag das wohl richtig sein, allgemein ist es in den meisten Fällen so das "Aktualisierung" häufiger ausgelöst wie Änderung.
Im Fall des BWM würde das Programm mit "Aktualisierung" ca. alle 6 Minuten bei jeder Statusmeldung ausgelöst werden.
Mit "bei Änderung" beschränkten sich die Auslöser eben auf die Änderung des Wahrheitsgehaltes. Je nach Bedingung kann das eben häufig oder fast nie der Fall sein.
Darum benutzt man in diesem Falle z.B. "bei Aktualisierung"
Wann und warum welcher Auslöser gewählt werden soll hat ja mit der Grundsätzlichen Frage nichts zu tun. Die Behauptung lautete sinngemäß doch: "Das Programm wird ausgelöst wenn die Bedingung wahr ist". Und das ist eben falsch.

Und auch hier sieht man wieder das wir wahrscheinlich alle das selbe meinen und es anders beschreiben. Allein diese Abweichungen geben bereits großen Spielraum für Missverständnisse. Eine vernünftige anfängertaugliche Erklärung zu erstellen, die alles abdeckt und nicht die Ausmaße einer Bibel annimmt, ist aus meiner Sicht fast unmöglich weil unzählige Konstellationen eben auch individuelle Beschreibungen benötigen.
Viele Grüße!
Jörg

66er
Beiträge: 3083
Registriert: 23.08.2015, 11:06
System: CCU
Hat sich bedankt: 116 Mal
Danksagung erhalten: 111 Mal

Re: WebUI Programmlogik - einfach erklärt am "lebenden Objekt"

Beitrag von 66er » 14.07.2018, 20:31

JRiemann hat geschrieben:
14.07.2018, 18:55
... Stefan wird sich das selbe für seinen Teil tun....
Nur bedingt, da ich bislang in anderen Threads von gzi statt EInsicht eher verzweifelte Erklärungsversuche kenne.

Wer eine Anleitungen für Einsteiger schreiben will, darf sich keine Fehler in der Erklärung leisten :!:

Beispiel:
gzi hat geschrieben:
14.07.2018, 17:45
...
Du hast übersehen, dass beim zweiten Punkt auch explizit steht, ...
Erwartet man etwa, dass Punkt 2 vor Punkt 1 gelesen wird :?: :shock:

Von meiner Seite war es das zum Thema, den Anfängern steht es nun frei, wie sie damit umgehen. :wink:

LG
Stefan

gzi
Beiträge: 450
Registriert: 12.01.2015, 23:37
System: CCU
Hat sich bedankt: 15 Mal
Danksagung erhalten: 14 Mal

Re: WebUI Programmlogik - einfach erklärt am "lebenden Objekt"

Beitrag von gzi » 15.07.2018, 17:16

Ich kann aus den genannten Beispiel-Skizzen/Diskussionen keine Fehler in meiner obigen Logik-Beschreibung herauslesen. Wer meint, dass ich mich irre: bitte nachprüfbaren Code einstellen.

Über die Qualität der Verständlichkeit, kann man natürlich immer unterschiedlicher Meinung sein. Wer meint, es besser zu können, kann es ja selber versuchen!

gzi
Lichtsteuerung, Heizungssteuerung, Überwachung (Feuer, Wasser, Einbruch, Stromausfall, Heizungsausfall, Wetter, Kamera), Alarmierung (optisch, akustisch, mail, SMS, voice call) - CCU, diverse HM- und HMIP Aktoren und Sensoren, Rauchmeldeanlage, UPS, GSM-Alarmwähler, Zugriff aus dem Internet via HTTPS und htdigest authentication, kein Datenkraken-Interface (Google, Amazon, China-Cloud, BND, NSA...) - HomeMatic Sicherheits-Kompendium - Checkliste für Auswahl von IP Kameras - Vergleich aktueller HomeMatic Zentralen - und alle Antworten für das gesamte Universum und den Rest

Antworten

Zurück zu „HomeMatic Tipps & Tricks - keine Fragen!“