Wenn dies dein erster Besuch hier ist, lies bitte zuerst die Hilfe - Häufig gestellte Fragen durch. Du musst dich vermutlich registrieren, bevor du Beiträge verfassen kannst. Klicke oben auf 'Registrieren', um den Registrierungsprozess zu starten. Du kannst auch jetzt schon Beiträge lesen. Suche dir einfach das Forum aus, das dich am meisten interessiert.
Ich finde die Uhr schon ganz brauchbar. Haben wir jetzt eigentlich zwei Uhrplugins?
Den Support von Perl Plugins in neueren Wiregates (Python) sollte man genau abwägen. Ggf. sind diese mit weniger Aufwand schnell neu geschrieben, wenn es eine beherrschbare Logikengine gibt. Vl. ist die Zeit in der Logikengine besser aufgehoben, als in Perl2CC Adaptoren...
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.
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 ...
Und dann wäre noch die Frage, ob jedes EIB-Kommando überhaupt einen erkennbaren Status hinterlässt: Ein Rolladenaktor reagiert zwar auf das Kommando "runter fahren", aber bei meinen Aktoren kann man trotzdem den Zustand "oben" oder "unten" nicht auslesen, was logisch ist, weil die Rolladenmotoren keine derartigen Zustände kennen,.
Ich schlage daher so was in der Art vor:
Code:
my $toleranz = 59;
foreach .... {
...
(defined $Zeit->{letzteAktion} && time - $Zeit->{letzteAktion} < $toleranz) and next;
...
knx_write($Zeit->{GA},$Zeit->{Wert},$Zeit->{DPT});
$Zeit->{letzteAktion} = time;
}
was aber nur geht, wenn die Variablen des Plugins von Aufruf zu Aufruf persistent sind (so habe ich es allerdings verstanden).
@Makki
Volle Übereinstimmung. Der o.g. Ansatz ist für sicher für vieles geeignet, aber eine richtige Zeitschaltuhr zu sein kann es vielleicht nicht beanspruchen.
@makki: Wenn Du hier perl c-compiler schreibst, meinst Du aber nicht perlcc oder?
Um gottes willen nein, man darf ja IMHO Fehler machen, aber nicht denselben 3x
Ich meine dann damit gcc, perlembed, pthread (bzw. pth/pthsem).
Mehr als nen proof-of-concept gibts aber nicht dazu..
(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" ..
.
Die genaue Uhrzeit wage ich gewährleisten zu können.. Eine abweichung von 10ms ist für mich schon ein total kaputtes Gerät
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,
Die Drift flickt der ntpd sehr gut (individuell, solange er einmal für ein paar Stunden kontakt zum NTP-Server hat passt das)
Aber das Problem: das ein Plugin binnen einer Minute aufgerufen wird ist zwar wahscheinlich aber nicht sicher!
Die Perl-jungs haben leider threads mit forks und RAM mit unbegrenztem Swapspace verwechselt, muss man halt nur erst wissen, der Rest ist Geschichte
Die Plugins sind dafür gemacht mal ein CUL oder nen Denon anzubinden, nen PI-Regler vielleicht, exaktes Timing stand einfach nicht auf der Wunschliste (und geht so single-threaded auch schwer bei einem daemon der 30sek zum starten braucht und sich leider komplett selbst kacheln muss, wenn ein Plugin blockiert weil es sonst 20 Speicherlecks gibt)
-> Ergo, sorry, da muss man einigen Grips reinstecken, damit sowas rund läuft.
Ich würde mir aus der Hüfte für jeden Befehl merken wann ($plugin_info) und ein Zeitfenster machen; wiegesagt: auf die Zeit kann man sich verlassen, auf den Aufrufzeitpunkt eher nicht.
Ich hab da auch schon Tage verschwendet mit POE::Wheels und dgl.. leider alles Schrott..
Das mag sich irgendwann vielleicht ändern (ich hab da was im Kopf..) aber ehrlichgesagt würde ich die knappen resourcen lieber in eine richtige Lösung statt weiteren Perl-Workarounds stecken. -> Die Perl-Plugins werden/sollen laufen wie sie sind aber mehr=?
Die Perl-Plugins sind für manche Sachen IMHO recht gut, man kann damit ohne grosse Detailkenntniss mal schnell was an KNX bringen oder die wildesten Sachen wie VPN per GA machen..
Aber für andere Sachen eben nicht so -> Keine Logikengine.
Im konkreten Fall würde ich auch lieber mal mit dem eh installierten cron sprechen, das ist >20J ausgereift, funktioniert und ist tausendfach dokumentiert..
Ok Sehr schön. Die Variante gefällt mir auch sehr gut. Ich möchte etwas ähnliches bei mir auch noch nachrüsten.
Und noch eine Idee am Rande...
Um kein Ereignis zu verpassen und um keine unnötigen Telegramme auf den BUS zu senden würde ich die Zykluszeit doch auf z.B. 30s setzen und dafür eine Warheitsprüfung einbauen. z.B. so:
Code:
foreach my $Zeit (@Schaltzeiten) {
if (knx_read($Zeit->{ga},0,$Zeit->{DPT}) ne $Zeit->{Wert}) {
(defined $Zeit->{Aktiv} && !$Zeit->{Aktiv}) and next;
(defined $Zeit->{Min} && !&matches($lMin, $Zeit->{Min})) and next;
(defined $Zeit->{Std} && !&matches($lStu, $Zeit->{Std})) and next;
(defined $Zeit->{MTag} && !&matches($lMTag, $Zeit->{MTag})) and next;
(defined $Zeit->{Mon} && !&matches($lMon, $Zeit->{Mon})) and next;
(defined $Zeit->{WTag} && !&matches($lWTag, $Zeit->{WTag})) and next;
(defined $Zeit->{Msg}) and print "$Zeit->{Msg}, [URL="http://redaktion.knx-user-forum.de/lexikon/GA/"]GA[/URL][$Zeit->{GA}]\n";
knx_write($Zeit->{GA},$Zeit->{Wert},$Zeit->{DPT});
} else {
next;
}
Damit wird ein Schaltpunkt direkt übersprungen, wenn der Aktor bereits den Wert des Schaltpunktes besitzt (z.B. Ist der Aktorkanal bereits EIN dann braucht man nicht noch ein EIN-Befehl senden).
Und ich würde die Optionen auch noch um den DPT erweitern (wegen z.B. Dimmwerten).
(exists $Zeit->{Mon} && !&matches($lMon, $Zeit->{Mon})) and next;
auf NEXT springen würde
Eiei, da hat sich auf dem Weg von meinem Linux-Test hier zum für mich untestbaren wiregate-Code ein Vertipper eingeschlichen :-)
Es muss natürlich tatsächlich 'defined' statt 'exists' heissen.
Vielen Dank für die Antwort :-) Ansonsten müsste es jetzt gehen.
Die wesentlichen Unterschiede zur Version vorne im Thread:
In diesem Script können auch Komma-separierte Listen für Zeiteinträge verarbeitet werden, z.B. Std=>'12-14' # entspricht 12-14 Uhr
Listen sind in allen Zeiteinträgen möglich, z.B. Mon=>'1,4, 8' # entspricht Januar, April und August.
Es können auch Listen aus Bereichen angegeben werden: Std=>'7-13, 20-23' # entspricht 7-13 Uhr, und 20-23 Uhr.
beide Formen können beliebig gemischt werden: MTag=>'1-5, 15,17, 20-30' # entspricht jeden Monat den Tagen 1 bis 5, 15, 17 und 20-30.
Einträge die immer gelten sollen, werden einfach 'undef' gesetzt, oder schlicht ganz weggelassen.
Blanks und Tabs in den Zeiteinträgen spielen keine Rolle.
Die Uhrzeit wird einmal vor der Schleife gelesen, und gilt damit für alle Einträge als Vergleichsbasis. Damit ist sichergestellt, dass alle Einträge die gleiche Ausgangsuhrzeit, nämlich die, als das Script gestartet wurde (genauer: bevor die Schleife gestartet wurde) verwenden, und es spart Ausführungszeit.
(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. Man bräuchte nur den Zeit-Eintrag aus @Zeiten in Epoch umzurechnen, eine Toleranz von _cycle/2 (also 30 Sekunden) draufrechnen, und dann schauen, ob der Eintrag noch im Zeitfenster liegt. Dann sollte alles paletti sein.
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.
Genau genommen kommt es dabei nicht auf die Sekunde an, sondern nur darauf, das es mit der Ausführungszeit des Plugins und dem nächsten Minutenwechsel nicht zu knapp wird. Sofern also Wiregate garantieren kann, dass dieses Plugin immer rechtzeitig vor dem Minutenwechsel (also z.B. am Anfang einer Minute) ausgeführt wird, sollte das passen.
Frage an Makki: Ist das ein realistischer Wunsch?
Aber Achtung: Es könnte auf Dauer noch andere Plugins mit ähnlichen Anforderungen geben, und dann bräuchten wir wieder einen Parameter, der dem Framework sagt, was unsere bevorzugte Startsekunde ist, z.B.:
$plugin_info{$plugname.'_triggerSecond'} = 20;
Wenn das alles zu viel Zirkus verursacht, wäre vielleicht doch cron das Mittel der Wahl ...
Hier noch die gefixte Version:
Code:
# Plugin zum Zeitabhängigen Schalten von GA's (Schaltuhr)
# License: GPL (v2)
# version von emax
####################
###Einstellungen:###
####################
my @Zeiten =
(
{ Name=>'Test', Aktiv=>'1', Std=>undef, Min=>undef, MTag=>undef, Mon=>undef, WTag=>undef, Wert=>'1', GA=>'1/1/30' },
{ Name=>'Bewaesserung', Aktiv=>'1', Std=>'7', Min=> '0', MTag=>'3', Mon=>'4-9', WTag=>'1-5', Wert=>'1', GA=>'1/1/30', Msg=>'Bewaesserung ein'},
{ Name=>'AussenlichtEin', Aktiv=>'1', Std=>'19', Min=>'30', MTag=>'4', Mon=>undef, WTag=>'1,3,5', Wert=>'1', GA=>'1/2/40' },
{ Name=>'AussenlichtAus', Aktiv=>'1', Std=>'7', Min=> '0', MTag=>undef, Mon=>undef, WTag=>'2,4,6', Wert=>'0', GA=>'1/2/40' }
);
######################
##ENDE Einstellungen##
######################
use POSIX;
# Eigenen Aufruf-Zyklus auf 20sek. setzen
# $plugin_info{$plugname.'_cycle'} = 20; ------> Das wird so nicht vernünftig gehen, siehe Anmerkung.
# Anmerkung:
# Wenn man keine Sekunden verarbeitet,
# muss dieses Plugin alle 60 Sekunden aufgerufen werden, weil die aktuellen Ereignisse
# sonst 3 mal pro Minute getriggert werden.
#
# Es ist überdies sinnvoll, dafür zu sorgen, dass die Startzeit dieses Plugins
# mit der Zeit nicht "abdriftet", es sollte immer _exakt_ zur gleichen Sekunde laufen,
# da sonst bei einem Minutenüberlauf Ereignisse verloren gehen können.
$plugin_info{$plugname.'_cycle'} = 60;
###################################################################
# 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;
}
my ($lSec,$lMin,$lStu,$lMTag,$lMon,$lJahr,$lWTag,$lJTag,$isdst) = localtime(time);
$lJahr += 1900;
foreach my $Zeit (@Zeiten)
{
(defined $Zeit->{Aktiv} && !$Zeit->{Aktiv}) and next;
(defined $Zeit->{Min} && !&matches($lMin, $Zeit->{Min})) and next;
(defined $Zeit->{Std} && !&matches($lStu, $Zeit->{Std})) and next;
(defined $Zeit->{MTag} && !&matches($lMTag, $Zeit->{MTag})) and next;
(defined $Zeit->{Mon} && !&matches($lMon, $Zeit->{Mon})) and next;
(defined $Zeit->{WTag} && !&matches($lWTag, $Zeit->{WTag})) and next;
(defined $Zeit->{Msg}) and print "$Zeit->{Msg}, GA[$Zeit->{GA}]\n";
knx_write($Zeit->{GA},$Zeit->{Wert},1);
}
..oder mit dem Script-Komfort von Perl (interessiert mich nich, was besser wäre, hauptsache einfach) - aber am Ende des Tages in richtig und auch "a bisserl" schneller.. ca. eben so Faktor 100
Perl ist in C geschrieben
Und in C funktioniert das mit threading - im Gegensatz zu Perl..
Also gäbe es die Option, die Perl-Plugins in einem C daemon (der dabei 1/100 des speichers & CPU verbrät) multithreaded, also fast gleichzeitig laufen zu lassen..
Theoretisch..
Wo kann ich den was zur Persistenz der Variablen finden? Wie wird so ein Plugin ausgeführt, mit 'do', 'eval' ...?
Mit eval, zukünftig (irgendwann) mit pre-compiled eval ausm C-daemon.
Ich merke schon, da haben wir einen wertvollen Kenner
Da gibts doch sicher irgendwo was zu lesen?
Nee, auf diesem Niveau sicher nichts anderes als den Source-Code (für den ich mich Stellenweise richtig schäme.. aber es funktioniert..)
Es gäbe nen Plan dazu aber der hat weniger mit Perl zu tun, eher mit C worin Perl geschrieben ist (das threading z.B. ist nun leider nach wie vor komplett kaputt/unbrauchbar in Perl )
Ja ich meinte mit aussteigen überspringen (nächster Eintrag verarbeiten). Dann würde es aber trozdem nicht alle Bedingungen die du oben in der Definition einsetzt verarbeiten.
Wo kann ich den was zur Persistenz der Variablen finden? Wie wird so ein Plugin ausgeführt, mit 'do', 'eval' ...?
Wann wird es geladen/verworfen?
Da gibts doch sicher irgendwo was zu lesen?
Wenn nämlich die Lebensdauer der Variablen ausreichend ist, ließe sich doch ganz prima eine Statemachine bauen - sofern man das angedachte Konzept mit allen den möglichen Problemen beibehalten will: Es wird unvermeidliche Raceconditions geben, und daraus resultierende Ereignisverluste zu analysieren ist nicht so prickelnd.
Ich wüsste deshalb gerne was über das Framework in dem die Plugins laufen, wo gibt es ein bisschen Doku dazu?
Ja: 'next' liest den nächsten Array-Eintrag. Den Ausstieg würde man stattdessen mit 'last' machen.
Ich hoffe, ich habe Deine Frage richtig verstanden: Ausstieg = Ende der Schleifenausführung. 'next' beendet aber die Schleife nicht, sondern führt sie wieder von vorne aus, allerdings mit dem nächsten Element. Richtig ist, dass in diesem Fall nichts auf den Bus gesendet wird.
Wir verarbeiten personenbezogene Daten über die Nutzer unserer Website mithilfe von Cookies und anderen Technologien, um unsere Dienste bereitzustellen. Weitere Informationen findest Du in unserer Datenschutzerklärung.
Indem Du unten auf "ICH stimme zu" klickst, stimmst Du unserer Datenschutzerklärung und unseren persönlichen Datenverarbeitungs- und Cookie-Praktiken zu, wie darin beschrieben. Du erkennst außerdem an, dass dieses Forum möglicherweise außerhalb Deines Landes gehostet wird und bist damit einverstanden, dass Deine Daten in dem Land, in dem dieses Forum gehostet wird, gesammelt, gespeichert und verarbeitet werden.
Einen Kommentar schreiben: