Hallo,
stolpere gerade über einen Timer.
Ich will meine Jalousien über eignes Modul fahren (Zeitgesteuer) und dabei die chance nutzen etwas Perl/FHEM zu lernen.
ich habe ein notify das auf die Taster up/down reagiert und die Jalousien (über gpio) verfährt. Bei längerem Druck fährt die Jalousie in die jeweilige Endposition. Über weiteres Tasten kann die jalousie auch jederzeit gestoppt werden.
Über die Laufzeit/Gesamtlaufzeit zwischen den Ereignissen ermittle ich die aktuelle Position am Ende des Vorgangs, einen ununterbrochenen Lauf nutze ich immer zum "kalibrieren" auf 0 zw. 100%. Das funktioniert auch alles gut.
Jetzt wollte ich über smartvisu gerne flexibler werden und via schieberegler oder basic.shutter in "realtime" regeln. den aktuellen wert des gads (shutter und pos) bekomme ich auch in FHEM angezeigt.
Wenn ich aktuelle pos und pos aus dem gad vergleiche kann ich aus der differenz die benötigte laufzeit berechnen. soweit so gut.
mein problem dabei ist, dass das genau einmal funktioniert, wenn ich den basic.shutter mit einem! click auf eine position befördere.
über ein notify auf das userreading des gads wird die berechnung gestartet und der lauf geht für die berechnete zeit los. das problem ist, dass die laufzeit der jalousie (und damit die position) immer erst ermitelt wird, wenn die jalousie stoppt. ich kann damit nicht 1:1 schiebregler und jalousie bewegen, denn wenn ich nach dem ersten click den slider weiterschiebe, läuft die jalousie ja schon und die position stimmt nicht.
meine idee war nun, dass ganze über DOIF zu regeln. wenn also die aktuelle (in einem reading der jalousie gespeicherte )jalousie position <> dem ist wert des gads ist, soll die jalousie losfahren und zwar solange, bis der sollwert erreicht ist. dazu wäre es aber notwendig, das sich die position der jalousie im reading während des laufs immer aktualisiert (und zwar in möglichst kleinne intervallen). dann könnte ich den vergleich starten und die jalousie "live" mit smartvisu basic.slider "schieben".
Ich habe leider keine idee, wie ich das reading der laufzeit (ud damit position) nach dem start automatisiert und in definierten intervallen aktualisieren kann. in anderen objektorientierten sprachen würde ich einen timer oder parallelthread erzeugen der mir das erledigt, aber da kann ich den timer dann auch im subsekunden intervall takten bzw. für min. intervalle den workerthread sogar in die endlosschleife schicken. die timer hier mit "at" kann ich irgendwie nicht für meine zwecke verwenden, denn der ist wohl nur im sekundenintervall. Eine funktion im hauptthread während des laufs in die endlosschleife zu jagen scheidet auch aus.
wie kann ich das machen?
gruss
...offenbar hat keiner eine idee.
dann probier ich das mal anders, vllt. erbarmt sich ja ein perl fachmann:
wie implementiere ich in perl bzw. in die 99_myutils das modul tk::repeat ? (tk:.after)
leider sind meine kenntnisse in perl noch zu rudimentär um mich da völlig alleine (in diesem leben) durchzuwursteln. ich finde das im netz immer nur im zusammenhang mit grafischen oberflächen und mainwindow(). irgendwie fehlt mir da noch das verständnis.
ich will lediglich eine callback sub cb() in myutil aufrufen ala: repeat(1000 => \&cb()). ich hab mir mal nen dummy gebastelt, der in der sub getogglet wird. pack ich den repeat aufruf in ein notify und löse das über dummy2 aus, so wird der dummy1 bei jedem aufruf von dummy2 getriggert, aber eben nur 1 mal, es blinkt also nicht, was ja die funktion anzeigen würde.
Wie implepementiere ich repeat/after in einer perl-sub?
gruss
...m.E. ist das Problem etwas anderes: FHEM ist nicht für Echtzeitaktionen gemacht, das wird also innerhalb FHEM vermutlich nie zur Zufriedenheit klappen. (Ob ein forken ginge, kann ich nicht sagen).
FHEM arbeitet eben grundsätzlich alles in einer Schleife nacheinander ab, wenn also ein Prozess länger dauert, ist das timing hinüber.
Alternativen:
- Die GPIO's von einem anderen Programm verwalten lassen (keine Ahnung wie), oder eben forken; dann kann aber die Synchronisation der Elemente Probleme bereiten
- Die Ansteuerung auf eine mcu auslagern (Arduino&Co) und die das Timing (und v.a. die Verriegelung der Kanäle zueinander!) machen lassen. Ist aber natürlich auch damit nicht ganz trivial.
Just my2ct.
Gruß, Beta-User
Hi,
also erst einmal würde ich auch sagen, dass so etwas ein wenig nicht-FHEM-ig ist. Wie Beta-User sagt: FHEM ist kein Realtime-System.
Meiner Meinung nach gibt es aber durchaus ein paar Ansätze, die Dir helfen können:
- Ein "at" kann einmal pro Sekunde aufgerufen werden, darin kannst Du Dir dann Deine Readings setzen. Man muss da aber ein bisschen aufpassen, da das Setzen eines Readings durchaus ein bisschen dauern kann, je nachdem wie viele und welche notify/DOIF/FileLog etc. darauf reagieren wollen.
- Eine Alternative zum at ist die Funktion InternalTimer. Damit kommt man theoretisch auf Millisekunden-Auflösung.
- Ich würde das "Problem" anders herum betrachten. Wenn Dir das UI einen Befehl schickt (ich weiß nicht, wie das genau aussieht), dann kannst Du in dem moment mit gettimeofday() millisekundengenau einen Timestamp holen. Daraus könntest Du Dir ja berechnen, woe die Jalousie jetzt stehen müsste. Daraus kannst Du dann weitere Aktionen ableiten.
Gruß,
Thorsten
Schau Dir doch mal das inoffizielle ROLLO-Modul an:
https://wiki.fhem.de/wiki/ROLLO (https://wiki.fhem.de/wiki/ROLLO)
Da kannst Du über eine Laufzeitenkalibrierung feste Positionen anfahren lassen. Ist bei mir im Einsatz und funktioniert recht gut.
Viele Grüße
Christoph