Ankündigung

Einklappen
Keine Ankündigung bisher.

- √ - Zeitschaltuhr Plugin?

Einklappen
Dieses Thema ist geschlossen.
X
X
 
  • Filter
  • Zeit
  • Anzeigen
Alles löschen
neue Beiträge

  • emax
    antwortet
    Hat geklappt, aber es lag gestern nicht an Euch: Ich habe zwei SF-Accounts, und gestern natürlich das falsche Passwort verwendet ...

    Einen Kommentar schreiben:


  • makki
    antwortet
    Zitat von emax Beitrag anzeigen
    Es sind auch eine Menge Dinge drin, die ich selber (in Perl) noch nie gemacht habe, zum Beispiel Threads. Kühn eben :-)
    Ja, den Fehler macht aber auch nur 1x: Jegliches threading in Perl ist nämlich einfach nur substantiell "kaputt" - oder das was man sonst als einen Prozess mit 100% overhead bezeichen würde

    PS: Konnte im SVN übrigens nicht commiten. Entweder habe ich nur Leserechte, oder mein SF-User 'e.max' macht Probleme, weil ein Punkt drin ist. Oder vielleicht braucht's fürs SVN einen extra-Usernamen/Passwort ... ?
    Nee, das sollte schon alles passen.. aber vielleicht müssen wir da auch noch lernen: wenns morgen nicht geht bitte melden, die rechte sollten passen soweit ich sehe..

    Makki

    Einen Kommentar schreiben:


  • emax
    antwortet
    Danke für die Info. Ich hatte es mir schon selber rausgesucht.

    Spagetthicode würde ich es nicht nennen, aber eine gewisse Kühnheit ist unverkennbar ;-) Soll heißen: Ich würde es nur ungern ändern müssen, wenn es sich dabei um wesentliche Eingriffe handelte. Es sind auch eine Menge Dinge drin, die ich selber (in Perl) noch nie gemacht habe, zum Beispiel Threads. Kühn eben :-)



    PS: Konnte im SVN übrigens nicht commiten. Entweder habe ich nur Leserechte, oder mein SF-User 'e.max' macht Probleme, weil ein Punkt drin ist. Oder vielleicht braucht's fürs SVN einen extra-Usernamen/Passwort ... ?

    Einen Kommentar schreiben:


  • makki
    antwortet
    Zitat von emax
    Mal ne Frage: Wie of wird $plugin_info{_cycle} ausgewertet?

    - ein einziges Mal beim eval und dann nie mehr
    - vor oder nach jedem Plugin-Aufruf

    Vielleicht kannst Du mir ja das aufrufende Perl script, welches den eval macht, mal Posten, das würde mir helfen - egal wie der Code aussieht, das mir ziemlich egal ;-)

    Viele Grüße
    Edgar
    Vor dem Aufruf bzw. ständig:
    Code:
          if ((time() > $plugin_info{$plugname.'_last'} + $plugin_info{$plugname.'_cycle'} ...
    Sprich wenn das Plugin selbst den cycle verändert - so wie oben umgesetzt - wird das auch so wie erwartet dann eben wieder aufgerufen..
    Den source findet man in /usr/sbin/wiregated.pl - aber achtung, böser Spaghetticode

    Makki

    Einen Kommentar schreiben:


  • emax
    antwortet
    Ich habe jetzt mal eine Version gebaut, die ihre Ausführungszeit dynamisch selbst kontrolliert und korrigiert. Dokumentation ist im Quelltext. Hinzugekommen ist eine Möglichkeit, bei Versand eines KNX-Telegramms automatisch einen Eintrag ins Plugin-Logfile zu schreiben.

    Ich checke das script unter dem Namen 'emx_uhr.pl' ins svn ein.

    Code:
    # Plugin zum Zeitabhängigen Schalten von GA's (Schaltuhr)
    # License: GPL (v2)
    # version von emax
    # Version 1, 8.7.2011
    # Copyright: Edgar (emax) Hermanns, emax at berlios Punkt de
    
    ####################
    ###Einstellungen:###
    ####################
    
    my @Zeiten = 
        ( 
          { Name=>'Test',           Aktiv=>'1', Std=>undef, Min=>undef, MTag=>undef, Mon=>undef, WTag=>undef,   Wert=>'1', DPT=>'1', GA=>'1/1/30', Log=>'1' }, 
          { Name=>'Bewaesserung',   Aktiv=>'1', Std=>'7',   Min=> '0',  MTag=>'3',   Mon=>'4-9', WTag=>'1-5',   Wert=>'1', DPT=>'1', GA=>'1/1/30' },
          { Name=>'AussenlichtEin', Aktiv=>'1', Std=>'19',  Min=>'30',  MTag=>'4',   Mon=>undef, WTag=>'1,3,5', Wert=>'1', DPT=>'1', GA=>'1/2/40' },
          { Name=>'AussenlichtAus', Aktiv=>'1', Std=>'7',   Min=> '0',  MTag=>undef, Mon=>undef, WTag=>'2,4,6', Wert=>'0', DPT=>'1', GA=>'1/2/40' }
        );
    
    ######################
    ##ENDE Einstellungen##
    ######################
    
    use POSIX;
    
    ############################################################
    # Eigenen Aufruf-Zyklus setzen
    # Das script verarbeitet keine Sekunden, weshalb die kleinste 
    # Granulaität ohne zusätzlioche Statusverarbeitung eine Minute ist. 
    ############################################################
    my $cycleTime = 60;
    
    ############################################################
    # definiert die Sekunde, ab der neu synchronisiert wird    #
    ############################################################
    my $slotEnd = 10; 
    
    ############################################################
    # Die Versionsnummer ist Teil des plugin_info hashes und dient
    # dazu, dass das script definierte Anfangskonditionen findet 
    # auch ohne alles neu starten zu müssen. Die Nummer 
    # einfach nach einer Änderung des scripts um eins erhöhen.
    ############################################################
    my $version = 1;
    
    ###################################################################
    # Auswertung von Bereichs und Listenvergleichen                   #
    # Prüft, ob ein Wert zu einer Liste oder in einen Bereich passt   #
    ###################################################################
    sub matches
    {
        my ($value, $def) = @_;  # Zu prüfender Wert, Bereichsdefinition
        (!$def) and return 1;
        foreach (split(/,/, $def))
        {        
            s/\s+//g;
            (/^$value$/) and return 1;
            (/^([\d]+)-(\d+)/) and return ($value >= $1 && $value <= $2);
        }
        return 0;
    }
    
    ##########
    # main() #
    ##########
    
    # kontrollierte Startkonditionen setzen
    if (!defined $plugin_info{$plugname.$version.'firstRun'}) 
    {
        $plugin_info{$plugname.$version.'firstRun'} = 1;
        plugin_log($plugname, "Started plugin version $version, first have to sync with time slot.");
        # die Anpassungs der Zyklyzweit erfolgt dynamisch, s.u.
        $plugin_info{$plugname.'_cycle'} = 1;
    }
    
    my ($curSec,$curMin,$curStu,$curMTag,$curMon,$curJahr,$curWTag,$curJTag,$isdst) = localtime(time);
    $curJahr += 1900;
    
    #######################################################################
    # Es ist sinnvoll, dafür zu sorgen, dass die Startzeit dieses Plugins 
    # mit der Zeit nicht "abdriftet", da sonst über lange Laufzeiten ein 
    # Minutenüberlauf entstehen könnte, und so Ereignisse verloren gingen.
    # Aus diesem Grund prüft das script, ob es innerhalb der ersten 10 Sekunden 
    # einer Minute läuft, Wenn das nicht der Fall ist, wird so lange eine 
    # verkürzte Zykluszeit verwendet, bis die Ausführung wieder im vorgesehenen 
    # Zeitraum abläuft.
    #
    # Bei der Erstausführung des Plugins nimmt dieses erst nach Erreichen 
    # des vorgesehenen Zeitfensters die eigentliche Arbeit auf, weil der 
    # Abstand zwischen zwei sonst zu klein werden könnte.
    #######################################################################
    
    if ($curSec >= $slotEnd)
    {
        if ($plugin_info{$plugname.'_cycle'} != 1)
        {
            plugin_log($plugname, "lost time-slot due to time drift, reducing cycle time to 1 second");
                $plugin_info{$plugname.'_cycle'} = 1;
        }
        
        # bei Erstausführung auf Zeitfenster warten
        ($plugin_info{$plugname.$version.'firstRun'} == 1) and return;
    }
    
    # prüfen, ob in dieser Minute bereits ausgeführt
    (defined $plugin_info{$plugname.$version.'lastMinute'} && $plugin_info{$plugname.$version.'lastMinute'} == $curMin) and return;
    
    foreach my $Zeit (@Zeiten) 
    {
        (defined $Zeit->{Aktiv} && !$Zeit->{Aktiv}) and next;
    
        (defined $Zeit->{Min}  && !&matches($curMin,  $Zeit->{Min}))  and next;
        (defined $Zeit->{Std}  && !&matches($curStu,  $Zeit->{Std}))  and next;
        (defined $Zeit->{MTag} && !&matches($curMTag, $Zeit->{MTag})) and next;
        (defined $Zeit->{Mon}  && !&matches($curMon,  $Zeit->{Mon}))  and next;
        (defined $Zeit->{WTag} && !&matches($curWTag, $Zeit->{WTag})) and next;
        (defined $Zeit->{Log}  && $Zeit->{Log} eq '1') and 
            plugin_log($plugname, "Sending $Zeit->{Name}, GA[$Zeit->{GA}], Value[$Zeit->{Wert}]"); 
    
        knx_write($Zeit->{GA},$Zeit->{Wert}, $Zeit->{DPT});   
    }
    
    $plugin_info{$plugname.$version.'lastMinute'} = $curMin;
    $plugin_info{$plugname.$version.'firstRun'} = 0;

    Einen Kommentar schreiben:


  • emax
    antwortet
    Zitat von swiss Beitrag anzeigen
    Ich bin nur Elektriker und programmiere als Hobby.
    Lass mal ruhig das 'nur' weg: Gerade diejenigen, die das aus Begeisterung machen, geben in der Regel ihr Bestes. :-)

    Einen Kommentar schreiben:


  • makki
    antwortet
    Zitat von greentux Beitrag anzeigen
    Den Support von Perl Plugins in neueren Wiregates (Python) sollte man genau abwägen.
    Für die Perl-Plugins gibts "bestandsschutz", also die werden/müssen 100% auf lange Sicht weiter so funktionieren wie sie sind. Das wars aber dann auch
    Das wird gehen, bei einem "V2.0"-design halte ich das aber für irrelevant.. Soviel Platz habe wir auf de der HW locker

    Weil:
    Zitat von emax Beitrag anzeigen
    es sieht vielleicht doller aus als es ist: Perl ist "nur" mein Helferlein für alles Mögliche, ganz so wie Larry Wall das mal gedacht hatte :-)
    Dito.. Wann Perl so richtig nicht mehr brauchbar ist, stellt man leider erst fest, wenn man an der Glasscheibe (Script vs. echte Programmiersprache) mal sauber abgeschmiert ist
    Ich mag Perl.. Aber mittlerweile nur noch unter bestimmten Umständen..

    Wie komme ich an den SVN-Zugang
    Eine eMail/PN genügt gewöhnlich, es wurde noch keiner abgelehnt der weningstens seinen Namen richtig buchstabieren konnte

    Makki

    Einen Kommentar schreiben:


  • Chris M.
    antwortet
    Zitat von emax Beitrag anzeigen
    Ich nehme an, Du meinst nicht die Engine selbst, sondern das Frontend für die User?
    Klar das Frontend - aber das bedingt die Implementierung des Backend, insbesondere wenn man nicht nur über Events sondern auch (kontinuierliche) Signale spricht.
    Das was dabei schwierig dabei ist, ist aber schon gelöst... Eigentlich fehlt nur noch Zeit, das ganze sauber zu machen, die Infrastruktur sauber hin zu setzen und einen Web-Entwickler, der sich des Editors annimmt. Der mag zwar prinzipiell schon, würde aber noch eine gescheite Optimierung benötigen.

    Für diesen Thread ist das jedoch OT. => ENDE

    Einen Kommentar schreiben:


  • swiss
    antwortet
    @Chris:

    Nein, einen Vorschlag habe ich nicht, da das ganz von der restlichen Implementierung abhängt. Wichtig ist nur, dass man diesen Status per GA lesen und schreiben können muss.
    Da kommt mir schon wieder eine neue Idee...

    Vieleicht wäre es sinnvoll, wenn man jeder Option (Stunden, Minuten, Datum, EIN/AUS, Urlaub, Sondertage usw...) entweder einen statischen Wert im Plugin oder eine GA zuweisen könnte. Dann könnte jeder selbst entscheiden, was er statisch und was dynamisch über den KNX steuern will. Oder denke ich da schon wieder zu kompliziert?

    Einen Kommentar schreiben:


  • emax
    antwortet
    Zitat von Chris M. Beitrag anzeigen
    Dazu dann noch ein geeigneter Reset-Mechanismus
    Das ist des Pudels Kern :-)
    Zitat von Chris M. Beitrag anzeigen
    Eine Logik-Engine die hier ernsthaft antreten will, muss IMHO eine grafische Programmiersprache sein.
    Ich nehme an, Du meinst nicht die Engine selbst, sondern das Frontend für die User?
    Zitat von Chris M. Beitrag anzeigen
    Makki oder mir schreiben.
    Mach ich.

    Einen Kommentar schreiben:


  • Chris M.
    antwortet
    Zitat von swiss Beitrag anzeigen
    Hast du da einen Vorschlag? Die Urlaubs und Sondertage könnte man in ein eigenes Array packen und in den Einstellungen der Schaltpunkte eine Option Sondertage => 1 /0 hinzufügen. Oder sogar noch eine Option Urlaub => 1 / 0 Für Schalpunkte die zwar an den Feiertagen NICHT aber wärend der Urlaubszeit SCHON geschaltet werden sollen.
    Nein, einen Vorschlag habe ich nicht, da das ganz von der restlichen Implementierung abhängt. Wichtig ist nur, dass man diesen Status per GA lesen und schreiben können muss.

    Zitat von emax Beitrag anzeigen
    Man könnte ein "Fenster" bzw. eine Toleranz einbauen, innerhalb derer der Zeitpunkt 'gültig' ist, naheliegend wäre alles, was eindeutig unter 60 Sekunden liegt.
    Zitat von emax Beitrag anzeigen
    (Mindestens) ein Problem bleibt: Die Drift-Problematik, die ich weiter oben schon erwähnte. Wenn WireGate garantieren könnte, dass ein Plugin auch auf Dauer zeitlich nicht nach hinten "abhaut", dann wäre das relativ einfach lösbar.
    [...]
    Wenn aber die Ausführungszeit innerhalb jeder Minute auf lange Zeit nicht garantiert werden kann, weil "über die Monate" eben eine kontinuierliche Abdrift zu erwarten ist, dann geht das so nicht so ohne weiteres. Irgenwann, nach Monaten, wird nämlich ein Event verloren gehen, und wenn das zufällig das Schalten einer Alarmanlage ist, oder die Aktivierung der Winterheizung im Ferienhaus, dann wär das schlecht.
    Nein, dass können die Plugins IMHO nicht garantieren. Und genau das ist einer der Punkte, auf die ich oben eingegangen bin.

    Triviale Lösung:
    • Zykluszeit deutlich kleiner (z.B. 30s) und merken, ob ein Event ausgelöst wurde

    Die vertmutlich bessere Lösung (ähnlich anachron, wäre wohl auch deutlich fehlertoleranter):
    • Man schreibt Code in der Art von:
      Code:
      If( EventZeit < IstZeit && !EvenetAusgeführt )
      {
        EventAusgeführt = True;
        DoEvent();
      }
      Dazu dann noch ein geeigneter Reset-Mechanismus für sich wiederholende Aufgaben.


    Zitat von emax Beitrag anzeigen
    Wenn nämlich die Lebensdauer der Variablen ausreichend ist, ließe sich doch ganz prima eine Statemachine bauen
    Statemachine geht mit den Plugins ganz gut, hab ich bei mir auch ein paar laufen
    Zitat von greentux Beitrag anzeigen
    aha. ok.
    so eine Art LUA
    Nur dass es viel mehr Sprachen gibt, die sich embedden lassen...


    Zitat von emax Beitrag anzeigen
    Python: Nicht jedem gefällt das. Ein Sprache, deren Logik von der Einrückung abhängt, ist vielen (auch mir) obskur
    Eine Logik-Engine die hier ernsthaft antreten will, muss IMHO eine grafische Programmiersprache sein.
    Die Funktionsblöcke selbst können dann selbst in der grafischen Sprache oder einer beliebigen anderen Programmiersprache implementiert sein.

    Proof of Concept dafür existiert bereits im SVN
    Zitat von emax Beitrag anzeigen
    Wie komme ich an den SVN-Zugang (ich war jetzt ehrlich gesagt zu faul sum suchen, und bin außerdem bei meinem Kunden, da muss ich mich kurz fassen) ...?
    Makki oder mir schreiben.

    Einen Kommentar schreiben:


  • swiss
    antwortet
    @emax:

    noch kurz:
    Thema Telegramme auf dem Bus sparen: Das Lesen verursacht auch Telegramme. Die Lösung mit der Busabfrage um festzustellen, ob der Zeiteintrag noch abgearbeitet werden muss, kann sowieso in die Hose gehen: man weiß ja nie, ob das EIB-Kommando nicht manuell übersteuert wurde.
    Die werte werden aus dem internen Speicher des WG gelesen, wenn sie nicht zu "alt" sind. Sollte also nach dem ersten schreiben auf den Bus durch den Schaltpunkt nicht direkt vom BUS sondern aus dem internen Speicher lesen.

    Beispiel: Rolladen runter. Draußen ist aber der tollste Sonnenuntergang, also stoppe ich das. Kurz darauf fangen die Dinger wieder an, runter zu fahren.
    Oder die Bewässerung geht an, aber ich habe die Liege noch auf dem Rasen stehen und schalte das ganz schnell manuell wieder ab ...
    Ist bei einer "gültigkeitsdauer" von 60s und einem Pluginintervall von 30s eher unwarscheinlich. Könnte man aber mit 31s sicher ausschliessen.

    Gilt aber nur bei meinem Plugin da eine fixe Zeit eingegeben wird. Bei deinem Plugin in dem man auch ein Zeitbereich angeben kann ist das Problem, dass ca. alle 60s der Befehl erneut gesendet wird. Wenn du also einen Befehl nach dem auslösen manuell zurücksetzt, musst du das alle 60s machen. Bei mir wird das Ereigniss genau 1x TRUE danach immer FALSE bis zum nächsten Tag (ohne datum, KW usw..). Allerdings muss ich den Intervall dazu auch auf 31s einstellen, damit innerhalb einer Minute das Plugin nur 1x ausgeführt wird.

    ...was aber nur geht, wenn die Variablen des Plugins von Aufruf zu Aufruf persistent sind (so habe ich es allerdings verstanden).
    Um Werte über einen Pluginaufruf hinaus zu "retten" musst du die Werte in der Form:

    $plugin_info{$plugname.'_toleranz'} = $toleranz;

    zwischenspeichern. Ist wie eine Art "globale Variabel". Alle anderen Variabeln sind nur innerhalb des Plugins gültig und werden beim verlassen gelöscht.

    Und zu guter letzt...

    Freut mich, wenn's Dir gefällt :-=)
    Na logo. Ich bin nur Elektriker und programmiere als Hobby. Durch solche tollen Beispiele lerne ich auch immer wieder neue Tricks dazu

    Einen Kommentar schreiben:


  • emax
    antwortet
    Hallo Stefan,

    danke für die Blumen, es sieht vielleicht doller aus als es ist: Perl ist "nur" mein Helferlein für alles Mögliche, ganz so wie Larry Wall das mal gedacht hatte :-)

    So richtigen Hardcore-Perlisten kann ich das Wasser nicht reichen, aber andererseits soll das Wiregate ja auch keine Plattform für durchgeknallte Nerds sein, sondern möglichst verständlich bleiben - und das kommt auch mir sehr entgegen.

    Wie komme ich an den SVN-Zugang (ich war jetzt ehrlich gesagt zu faul sum suchen, und bin außerdem bei meinem Kunden, da muss ich mich kurz fassen) ...?



    PS: Auf meine Lieferung freue ich mich schon wie ein Schnitzel :-))

    Einen Kommentar schreiben:


  • StefanW
    antwortet
    Ich finde den Vorschlag schonmal sehr gut, weil Zeitschaltuhren fehlen im WG. Das diese nicht unbedingt perfekt sind oder man sich alles noch schöner und besser vorstellen kann ist klar. Aber es ist ein guter Anfang.

    @Edgar: Du kannst Dir gerne einen SF-Zugang anlegen und selbst einchecken, bei uns ist alles offen. Deine PERL-Kenntnisse sind sehr hilfreich für die Community.

    Hab ich schon erwähnt, dass wir noch eine Anleitung für die Plugins bräuchten?

    Das WireGate Multifunktionsgateway wird sicher bald bei Dir sein.


    LG

    Stefan

    Einen Kommentar schreiben:


  • emax
    antwortet
    Da ich keinen SVN Zugang habe, und ich meinen Vorschlag eben nur als Vorschlag angesehen habe, ist es eben nur ein Vorschlag ;-)

    Wenn das script gefällt, und es jemand testen kann (ich habe noch kein Wiregate), kann swiss es ja vielleicht einchecken ...?

    Python: Nicht jedem gefällt das. Ein Sprache, deren Logik von der Einrückung abhängt, ist vielen (auch mir) obskur, egal ob die Threads besser gelöst sind oder nicht. Makkis Vorschlag einer hybriden Umgebung (embedded Perl) finde ich dagegen sehr gut. Aber die Implementierung ist nicht trivial.

    Einen Kommentar schreiben:

Lädt...
X