Ankündigung

Einklappen
Keine Ankündigung bisher.

In der Tiefe: Validierungskonzept

Einklappen
X
 
  • Filter
  • Zeit
  • Anzeigen
Alles löschen
neue Beiträge

  • enertegus
    antwortet
    Zitat von saft6luck Beitrag anzeigen
    Mal wieder eine Frage an Michael
    Warum kommt hier für Rollo_Sonnenaufgang_h und Rollo_Sonnenaufgang_m 7:50 heraus und nicht 7:00? Nach der ersten Änderung geht es dann aber ...
    Das Problem im Code ist ein (sicher unschönes) Verhalten der Verschachtelten if-Abfrage beim Initialisieren (siehe die vorigen mails): Einfach gesprochen: Jede if-Abfrage wird beim Initalisierungsvorgang auf einmal ausgewertet, egal ob verschachtelt oder nicht. Wir haben das auf dem Radar fürs nächste Relase.

    Einen Kommentar schreiben:


  • saft6luck
    antwortet
    Mal wieder eine Frage an Michael (und alle anderen, die das Validierungsschema verstanden haben ) zum Validierungsschema und Systemstart:
    Sonnenaufgang z.B. 06:57.
    Warum kommt hier für Rollo_Sonnenaufgang_h und Rollo_Sonnenaufgang_m 7:50 heraus und nicht 7:00? Nach der ersten Änderung geht es dann aber ...

    Sollte Copy&Paste prüfbar sein (Code ist zu Debugzwecken schon sehr umgebaut):
    [highlight=epc]
    // Rollo - Sonnenaufgang
    Rollo_Sonnenaufgang_vorziehen = 7s08
    Rollo_Sonnenaufgang_min_h = 07u08
    Rollo_Sonnenaufgang_min_m = 00u08
    Rollo_Sonnenaufgang_m = 60u08

    Rollo_Sonnenaufgang_h = sunrisehour()
    Rollo_Sonnenaufgang_m_s = convert( sunriseminute(), 0s08) - Rollo_Sonnenaufgang_vorziehen; /* -> Minuten: -15 <= m <= 44 */

    if change( Rollo_Sonnenaufgang_m_s ) or systemstart() then {
    if ( Rollo_Sonnenaufgang_m_s < 0s08 ) then {
    Rollo_Sonnenaufgang_m_s = Rollo_Sonnenaufgang_m_s + 60s08;
    Rollo_Sonnenaufgang_h = sunrisehour() - 1u08
    } endif;
    Rollo_Sonnenaufgang_m = convert( Rollo_Sonnenaufgang_m_s, 0u08 );
    if ( ( Rollo_Sonnenaufgang_h == Rollo_Sonnenaufgang_min_h ) and ( Rollo_Sonnenaufgang_m < Rollo_Sonnenaufgang_min_m ) ) then {
    Rollo_Sonnenaufgang_m = Rollo_Sonnenaufgang_min_m
    } endif;
    if ( Rollo_Sonnenaufgang_h < Rollo_Sonnenaufgang_min_h ) then {
    Rollo_Sonnenaufgang_m = Rollo_Sonnenaufgang_min_m;
    Rollo_Sonnenaufgang_h = Rollo_Sonnenaufgang_min_h
    } endif;
    } endif
    [/highlight]

    Einen Kommentar schreiben:


  • Tessi
    antwortet
    So, jetzt habe ich auch noch die vollständige Fassung lesen können.
    Die Sache mit dem Makro bekräftigt noch mal meine schon vorher aufgekommene Frage:
    Warum unterliegen Ausgabefunktionen nicht dem VK, so wie alle anderen auch? Rekursionen können auch anders entstehen und müssen sowiso irgendwie abgefangen werden, das zeigt ein dem Makro folgendes Beispiel. Dafür würde mit VK das Makro eher das machen, was ohne die Warnung sonst wohl die meisten von uns erwartet hätten: Es hätte zumindest bei Änderungen gesendet, auch wenn die Anweisungen dazu nicht im return-Zweig sondern im "globalen" Rumpf stehen.

    OK, es ist jetzt, wie es ist, und wenn man das jetzt verstanden hat, kommt man auch so ans Ziel, aber ich sehe jetzt immer noch keinen Vorteil darin, die Ausgabefunktionen aus dem VK herauszunehmen.

    Aber habe ich das den Beispielen jetzt richtig entnommen:
    1. Nur das, was im return-Zweig eines Makros steht, wird an den Stellen eingefügt, an der es aufgerufen wird? Der Rest steht funktional gesehen einmalig im globalen Code? Oder so oft, wie das Makro aufgerufen wird?
    2. Wenn ich ein Makro unbedingt aufrufe, steht dann der Code im Returnzweig genauso im globalen Kontext wie der restliche Makrocode und es greift auch hier das VK?
    3. Was bildet den Rückgabewert des Makroaufrufes, wenn im Returnzweig so viel Code stehen darf? Generell das letzte Statement? Was wäre dann, wenn dieses keinen Wert liefert? Oder das letzte Statement das einen Wert liefert? Was, wenn mehrere Statements einen Wert liefern? Werden dann alle Werte bis auf den letzten verworfen? Oder ist das nicht zulässig? Was ist, wenn kein Statement einen Wert liefert? Was ist, wenn an der Stelle des Aufrufes ein Wert erwartet wird? Fängt so etwas schon der Parser ab?

    Rekursion:
    Wie wird sie erkannt? Wann wird das Event PROC_REPITIONS generiert? Was passiert danach?

    Einen Kommentar schreiben:


  • Tessi
    antwortet
    Gut, bleibt für mich nur die Frage:
    [highlight=epc][EibPC]
    write("Schalter-1/2/10",!"Schalter-1/2/10")
    write("Schalter-1/2/10",blub)
    a=a+1u08
    a=b+1u08[/highlight]Zeile 2 und 3 sind erlaubt, aber führen zu nichts da die Argumente die Funktionen nicht triggern können.
    Zeile 4 würde sich gemäß VK selbst triggern und wird daher vom Parser an dieser Stelle nicht zugelassen.
    Zeile 5 würde gemäß VK getriggert werden und ist OK.

    Warum wird Zeile 2 nicht wie Zeile 4 und Zeile 3 wie Zeile 5 behandelt?
    Zeile 2 ist ein Risiko, aber Zeile 4 genauso.
    Wenn der Parser den Zirkelbezug in Zeile 4 erkennen und ablehnen kann, hätte man das doch genauso für Zeile 2 implementieren können. Ich fände es logischer, wenn Zeile 3 sich bei Änderungen der Argumente genau so erneut auswerten würde, wie dies Zeile 5 tut.

    Warum also diese unterschiedliche Behandlung?

    Einen Kommentar schreiben:


  • enertegus
    antwortet
    Zitat von Tessi Beitrag anzeigen
    Habe ich jetzt mal endlich geschafft!
    Schade, das es nach der 5. Seite zu Ende ist. Ich hätte doch gerne gewusst, was der Parser aus dem Makro am Ende macht.
    Ups, das habe ich versehentlich gemacht. => neu hochgeladen.
    Ich lese auf Seite 118: Ausgabefunktionen werden nie von ihren Argumenten invalidiert.
    Demnach funktionieren sie nur als Teil eines Ausdrucks, der von außen invalidiert wird, also in then- oder else-Zweigen.
    Ja, das ist richtig.

    Mir ist jetzt nicht klar, warum das wirklich ein Problem werden kann. OK, der Toggle-Befehl in Zeile 2 würde sich immer wieder selbst triggern, aber wenn ich das statt dessen so schreiben würde:
    Das ist der Hintergrund für diesen Verhalten.
    hätte ich das gleiche Problem.
    richtig, aber das setzt schon einiges voraus an gezieltem Handeln. Einfach nur ein write und dieses Verhalten, da erschien uns die Lernkurve zu krumm...
    Nicht ohne Grund mag der Parser so etwas ja nicht:
    Eben!
    Das macht für mich keinen Sinn! Entweder sende ich auch die Folge von Werten, die die verschiedenen write-Befehle hatten (weil die Sequenz für den Empfänger wichtig sein könnte), oder es geht tatsächlich nur um die letzte Änderung, aber dann sollte auch nur einmal pro Zyklus und GA ein Telegramm im Puffer landen.
    Welchen Sinn hat das derzeitige Verhalten?
    Das Argument ist gut. Hintergrund ist wohl (ich bin nicht der FW-Spezi) die Sache mit den unterschiedlichen Argumenten (Sequenz). Dass es bei Variablen so funktioniert ist wohl ein "Seiteneffekt", über den man nachdenken könnte.

    Einen Kommentar schreiben:


  • Tessi
    antwortet
    Zitat von enertegus Beitrag anzeigen
    Schau doch noch mal in Ruhe das PDF dieses Threads durch. Da ist das genau mit Beispielen erläutertet.
    Habe ich jetzt mal endlich geschafft!
    Schade, das es nach der 5. Seite zu Ende ist. Ich hätte doch gerne gewusst, was der Parser aus dem Makro am Ende macht.

    Ich lese auf Seite 118: Ausgabefunktionen werden nie von ihren Argumenten invalidiert.
    Demnach funktionieren sie nur als Teil eines Ausdrucks, der von außen invalidiert wird, also in then- oder else-Zweigen. Welche Katastrophe würde denn eintreten, wenn auch hier das VK gelten würde?

    [highlight=epc][EibPC]
    write("Temperatur-1/2/1",22.3)
    write("Schalter-1/2/10",!"Schalter-1/2/10")
    write("Temperatur-1/2/1",Temp)



    write("Schalter-1/2/10",Status)[/highlight]Zeile:
    1. -
    2. Kein Problem, die Konstante invalidiert ja sowiso nie.
    3. Hm, könnte ein ernstes Problem werden, aber so etwas sollte man an dieser Stelle dann auch nicht schreiben, bzw. der Parser könnte es ablehnen (wie er es an selbiger Stelle ja auch mit a=a+1u08 tun würde)
    4. Jede Änderung von Temp - egal wo im Code erfolgt - wird auch geschrieben, und hier maximal nur einmal pro Zklus. Problem?
    5. Wie zuvor
    Mir ist jetzt nicht klar, warum das wirklich ein Problem werden kann. OK, der Toggle-Befehl in Zeile 2 würde sich immer wieder selbst triggern, aber wenn ich das statt dessen so schreiben würde:

    [highlight=epc][EibPC]
    if ("Schalter-1/2/10") then {
    write("Schalter-1/2/10",!"Schalter-1/2/10")
    } else {
    write("Schalter-1/2/10",!"Schalter-1/2/10")
    } endif[/highlight]hätte ich das gleiche Problem. Nicht ohne Grund mag der Parser so etwas ja nicht:
    [highlight=epc][EibPC]
    a=a+1u08[/highlight]Statt dessen muß ich derzeit Zeile 3 und 4 (erstes Beispiel), damit eine Änderung auch auf den Bus kommt, so schreiben:
    [highlight=epc][EibPC]
    if change(Temp) write("Temperatur-1/2/1",Temp)
    if change(Status) write("Schalter-1/2/10",Status)[/highlight]Hier muß ich also explizit das schreiben, was das VK sonst implizit macht.

    OK, ich kann damit leben, aber dennoch interessiert mich der Grund für diese Art "Sonderbehandlung".

    Nächster Punkt:

    Ein Telegramm wird aus einem Zyklus heraus so oft in den Sendepuffer gestellt, wie in diesem Zyklus write-Befehle auf die GA invalidiert wurden. Klingt zunächst vernünftig, auch wenn das ggf. den Bus überlastet (ist aber dann ein Fehler des Programmierers). Gesendet wird dabei aber jedesmal der Wert den der zuletzt bearbeitete write-Befehl auf diese GA hatte. Das macht für mich keinen Sinn! Entweder sende ich auch die Folge von Werten, die die verschiedenen write-Befehle hatten (weil die Sequenz für den Empfänger wichtig sein könnte), oder es geht tatsächlich nur um die letzte Änderung, aber dann sollte auch nur einmal pro Zyklus und GA ein Telegramm im Puffer landen.
    Welchen Sinn hat das derzeitige Verhalten?

    Einen Kommentar schreiben:


  • enertegus
    antwortet
    Ich hab mal das Pdf aus dem internen Stand des Handbuch hochgeladen.
    Sind sicher noch jede Menge Tippfehler drinne.

    Einen Kommentar schreiben:


  • enertegus
    antwortet
    Zum Thema: Objektabhängigkeit und Validierung ein paar Bilder. Ich werde dies ins Handbuch einarbeiten.
    Dazu noch zum Thema if:
    Die if-Anweisung invaldiert alles im then-Zweig. Daher wird dort alles abhängig von der if-Anweisung ausgeführt. Wenn nun hier auch eine if-Anweisung steht, gilt für diese die Valdierung nicht vom Argument sondern direkt von der übergeordneten Anweisung.
    Nochmal zu Valdierung:
    • Eine Variablenausdruck ist invalid bedeutet: Berechne ihn und neu und invaldiere von ihm abhängige Variablen.
    • Eine Funktion ist invalid bedeutet: Führe die Funktion aus
    • Funktionen, die etwas auf den Bus schreiben, tun dies
    • Eine if-Anweisung ist invalid: Wenn die Bedingung wahr ist, dann führe den then Zweig aus.
    • Ein nicht von einer anderen if-Anweisung abhängige if-Anweisung (="Toplevel If") wird von ihrer Abfragebedingung abhängig invaldiert.
    • Ein von einer anderen if-Anweisung abhängige if-Anweisung (="verschachteltes If") wird NICHT von ihrer Abfragebedingung abhängig invaldiert

    Ich mach da noch ein paar Bilder, aber wahrscheinlich nicht vor Mitte nächster Woche.
    Vielleicht klärt sich das noch auf. Der pio hat es schön mit seiner Tabelle gezeigt und exakt richtig formuliert.
    Angehängte Dateien

    Einen Kommentar schreiben:


  • saft6luck
    antwortet
    Ehrlich gesagt frage ich mich schon, wieso die Programmierung des eibPCs eine solch Komplexe Angelegenheit sein muss. Mir wäre mehr daran gelegen, dass die Anleitung (und damit die Interpretation der Programmierung) so einfach wie möglich wird. Daraus folgt, dass die Programmierung robust wird.

    Und robust ist für mich eine Sprache, wenn sie eindeutig und deterministisch ist und das nicht erst nach mehreren Iterationen. Ich bin zwar ein Schachspieler, will aber trotzdem nicht jede Zeile Code "5 Ausführungszyklen weit" voraus betrachten müssen, schon gar nicht, um triviale Prüfungen zu implementieren.

    Leider erfüllt der eibPC mit seiner Programmiersprache meine Anforderungen nicht. Robustheit und Determinismus sind für mich wesentliche Aspekte der Automatisierung und da hatte ich evtl. zu viel erwartet.

    Einen Kommentar schreiben:


  • pio
    antwortet
    Zitat von enertegus Beitrag anzeigen
    d=a+b+c+1u08

    if (d>=0) then write('2/3/4'u08, d)[/highlight]
    richtig
    Nein, die werden sofort im Zyklus sich ändern, nur change() reagiert darauf erst im folgenden.
    gar nix, weil ja d=>0 schon zum Systemstart gültig ist.
    Es hat absolut nichts mit Geheimniskrämerei zu tun. Ich bin drüber, da wa zu malen.
    Um das noch weiter zu erklären:
    nach dem Neustart ist d=0, d.h. die Bedingung d>=0 ist erfüllt.
    Nach meinem Verständniss wird dann auch beim Neustart, d.h. beim allerersten Zyklus NICHTS gesendet, da die Bedingung zwar erfüllt ist, aber sich "nichts geändert" hat.
    Das gilt dann für den zweiten Verarbeitungszyklus und alle weiteren: obwohl auf der GA ein neuer Wert (=1) ankommt, ist die Bedingung >= 0 immer noch erfüllt, hat sich also gegenüber dem vorigen Zyklus nicht verändert, ergo wird der Then-Zweig auch nicht ausgeführt.

    Mein Vorschlag an Enertex zur Doku:
    Macht eine Tabelle, mit einer Zeile pro Verarbeitungszyklus, und listet in jeder Spalte die Zustände der einzelnen "Elemente" auf.
    Beispiel siehe Bild.
    Angehängte Dateien

    Einen Kommentar schreiben:


  • makki
    antwortet
    Naja, die "Sprache" des EibPC ist glaube ich für jemanden der schonmal programmiert hat (nicht verwechseln mit dem parametrieren in der ETS oder dem beklicken einer SPS bitte!) - zumindest gewöhnungsbedürftig.
    Dann gehts recht gut..

    Aber ich finds garnicht so schlecht, jeder der <=2007 mit dem HS angefangen hat und es nun gewohnt ist 15 Minuten (in Worten -> bis heute: eine Viertelstunde!) ohne jeglichen Support/gescheite Doku vom Hersteller (Anwesende im Forum ausgenommen) sich mal überraschen zu lassen, was nach dem Neustart passiert Der liebt das bestimmt, nach 10sek ggfs. sogar einen Bug zu finden (der nicht in 2 J sondern in 2 Tagen gefixed wird..)
    Man betrachtet das dann vielleicht auch anders

    Makki

    Einen Kommentar schreiben:


  • enertegus
    antwortet
    Ich werde da heute abend noch etwas malen und verdeutlichen (soweit es mir gelingt)
    Aber schon mal hierzu:
    [QUOTE=Tessi;141323]
    [highlight=epc]
    a=0u08
    b=0u08
    c=0u08
    d=0u08

    a='1/2/3'u08
    b=a+1u08
    c=a+b+1u08
    d=a+b+c+1u08

    if (d>=0) then write('2/3/4'u08, d)[/highlight]
    Kommt über '1/2/3' eine 0 passiert nichts - a ist ja schon 0.
    richtig
    Kommt über '1/2/3' eine 1 wird dann im selben Zyklus nur a=1 und b,c und d bekommen die Änderung von a erst im folgenden Zyklus mit?
    Nein, die werden sofort im Zyklus sich ändern, nur change() reagiert darauf erst im folgenden.
    Was wird dabei wann über '2/3/4' gesendet?
    gar nix, weil ja d=>0 schon zum Systemstart gültig ist.
    Wie gesagt, solche Fragen könnte ich mir selbst beantworten, wenn ich mehr über die internen Vorgänge im EPC wüßte...
    Es hat absolut nichts mit Geheimniskrämerei zu tun. Ich bin drüber, da wa zu malen.

    Einen Kommentar schreiben:


  • Tessi
    antwortet
    Es muß da aber doch noch einen besseren Weg geben das VS eindeutig und vollständig zu beschreiben, als seitenlange Prosa, die offenbar immer irgendwie Interpretationsspielraum für Missverständnisse läßt, und Beispiele, die ohnehin nicht alles abdecken können und teilweise gleich neue Fragen aufwerfen.

    Oben wurde erwähnt, das der Parser/Compiler den Code in Objekte und eine Abhängigkeitsstruktur umsetzt. Ich finde, für komplexere Logiken ist es hilfreich zu wissen, wie in etwa so ein Objekt und die Abhängigkeitsstruktur aussieht und was die Laufzeitumgebung im EPC damit macht, also wie der Ablauf beim Auftreten eines Events denn ist. Das schließt auch vorhandene Queues, Buffer und deren Verwaltung ein.

    Bis dahin habe ich aber noch eine konkrete Frage:

    [highlight=epc]
    a=0u08
    b=0u08
    c=0u08
    d=0u08

    a='1/2/3'u08
    b=a+1u08
    c=a+b+1u08
    d=a+b+c+1u08

    if (d>=0) then write('2/3/4'u08, d)[/highlight]
    Kommt über '1/2/3' eine 0 passiert nichts - a ist ja schon 0.
    Kommt über '1/2/3' eine 1 wird dann im selben Zyklus nur a=1 und b,c und d bekommen die Änderung von a erst im folgenden Zyklus mit?
    Wenn dem so ist, ändert sich c dann zweimal einmal wegen a und dann im folgenden Zyklus wegen b und ändert sich d dann analog dazu dreimal in drei aufeinanderfolgenden Zyken?
    Was wird dabei wann über '2/3/4' gesendet?
    Bei "reiner" Programmierlogik sollte nur einmal 8 gesendet werden.
    Wenn aber Änderungen der Variablen immer erst im Folgezyklus bearbeitet werden, dann würde ich 2,4 und 8 in dichter Folge erwarten - unter der Annahme, das es einen FIFO für zu sendende Botschaften gibt.
    Oder wird dennoch nur 8 gesendet, weil während des Sendens der dann aktuelle Wert verwendet wird und der bis dahin auf jeden Fall schon 8 ist?
    Wird dann drei mal 8 gesendet? Oder wird das zu einem Telegramm zusammengefasst? Falls ja, woher will die Ablaufsteuerung denn wissen, das ich nicht doch drei Botschaften wollte?

    Wie gesagt, solche Fragen könnte ich mir selbst beantworten, wenn ich mehr über die internen Vorgänge im EPC wüßte...

    Einen Kommentar schreiben:


  • no sleep
    antwortet
    Zitat von enertegus Beitrag anzeigen
    Da zieh ich mal den Stecker, PLONK.
    Wer im Glashaus sitzt...ich sage nur FSF und nicht vorhandene Flash-Kompetenz.
    DOPPELPLONK & Mail an die entsprechenden Stellen ist raus.

    Einen Kommentar schreiben:


  • enertegus
    antwortet
    Zitat von no sleep Beitrag anzeigen
    Gut, dass ich das auch nicht verstehen muss, weil ich mir "sowas" nie antun würde.
    Ich glaube, Du solltest hier nicht einfach was in die Runde schmeißen, so quasi auf Verdacht mal was gesagt.

    Da zieh ich mal den Stecker, PLONK.

    Einen Kommentar schreiben:

Lädt...
X