ich habe neben dem Studium gerade ein bisschen langeweile und will nun
mein FHEM/CUL auf ein RaspberryPI (ggf auch Beagle) "portieren". Dabei
kam mir die Idee z.B. einen Temperatursensor, Schalter oder so direkt
an die GPIOs anzuschließen und das entsprechende Protokoll/Endgerät zu
simulieren.
Ich kenn mich recht gut mit dem FS20 Protokoll und dem Hardwarekram
aus. Einziges Problem könnte der Treiber unter Linux werden. Ich habe
schonmal einen geschrieben (mit viel Fachliteratur Unterstützung), der
an einem GPIO Pin eine "1" oder eine "0" ausgibt. Mehr weiß ich leider
noch nicht über diese Thematik.
Daher wollte ich mal fragen, was FHEM braucht um einen CUL zu
initialisieren. Reicht das Zugriffsrecht (Lese/Schreibrecht) auf den
File aus oder muss da mehr vom CUL zurückkommen (Statusanfrage oder
so)? Die Befehle, die der "simulierte" CUL aussenden/empfangen muss,
kann ich ja in der Übersicht nachlesen.
> Daher wollte ich mal fragen, was FHEM braucht um einen CUL zu
> initialisieren. Reicht das Zugriffsrecht (Lese/Schreibrecht) auf den
> File aus oder muss da mehr vom CUL zur ckkommen (Statusanfrage oder
> so)?
00_CUL_HM.pm fragt nach der Version (V), und wertet die Rueckgabe aus
(muss V <version> sein).
Ich wuerde aber vorschlagen kein CUL zu simulieren, sondern ein eigenes
Fhem-Modul fuer die GPIO zu schreiben, und daraus (aehnlich wie CUL und FHZ)
Dispatch() aufrufen.
Danke für die schnelle Antwort! Wenn ich den Initialisierungsvorgang
richtig verstanden habe, löst FHEM nach OPEN- den WRITE-Sytemcall auf
und schreibt dann nur ein "V" in den Treiber. Dann wartet es auf eine
Antwort ala "V 1.30" oderso. Sind das alles blockierende Aufrufe? kann
ich diese also in Queues stecken und wieder aufwecken?
> Ich wuerde aber vorschlagen kein CUL zu simulieren, sondern ein eigenes
> Fhem-Modul fuer die GPIO zu schreiben, und daraus (aehnlich wie CUL und FHZ)
> Dispatch() aufrufen.
Das wäre sicherlich eine schönere Lösung, allerdings bin ich beim
Programmieren eher eine Niete und kenne mich auch nur mit C aus. Ich
versuche immer möglichst viel auf uController runterzubrechen (wie
hier 2-Drahtkommunikation mit RaspberryPI, relais usw. werden vom uC
gesteuert). Ich habe noch nie mit Perl gearbeitet und schätze die
Einarbeitungszeit in den Aufbau von FHEM auch für erheblich länger
ein.
Danke für die schnelle Antwort! Wenn ich den Initialisierungsvorgang
richtig verstanden habe, löst FHEM nach OPEN- den WRITE-Sytemcall auf
und schreibt dann nur ein "V" in den Treiber. Dann wartet es auf eine
Antwort ala "V 1.30 CUL868" oderso. Sind das alles blockierende
Aufrufe? kann ich diese also in Queues stecken und wieder aufwecken?
> Ich wuerde aber vorschlagen kein CUL zu simulieren, sondern ein eigenes
> Fhem-Modul fuer die GPIO zu schreiben, und daraus (aehnlich wie CUL und FHZ)
> Dispatch() aufrufen.
Das wäre sicherlich eine schönere Lösung, allerdings bin ich beim
Programmieren eher eine Niete und kenne mich auch nur mit C aus. Ich
versuche immer möglichst viel auf uController runterzubrechen (wie
hier 2-Drahtkommunikation mit RaspberryPI, relais usw. werden vom uC
gesteuert). Ich habe noch nie mit Perl gearbeitet und schätze die
Einarbeitungszeit in den Aufbau von FHEM auch für erheblich länger
ein.
Letzter Eintrag leider doppelt... Da habe ich wohl einmal zu viel gedrückt, als die Session abgelaufen war.
Ich habe mich jetzt einmal etwas länger mit der 00_CUL.pm und der DevIO.pm beschäftigt um den Open, Read und Write Prozess zu verstehen - Perl sieht doch sehr komisch aus, wenn man aus C kommt...
In der Funktion DevIo_OpenDev() erscheint der Openbefehl open($po, "+<$dev"). "+<" ist soweit ich gefunden haben also ein READ/WRITE Befehl, da kein O_NONBLOCK Flag gesetzt ist, müsste der zugriff blockierend sein.
In CUL_DoInit() ist auch die Abfrage nach der Version ersichtlich:
CUL_SimpleWrite($hash, "V");
($err, $ver) = CUL_ReadAnswer($hash, "Version", 0, undef);
Leider sehe ich in meinem Treiber das "V" noch nicht, werde jetzt also mal die FHEM Logs auswerten (an welchen man sich auch ganz gut durch den Quellcode hangeln kann).
Nachtrag:
Erwartungsgemäß sehe ich einen Fehler in den Logs: "Inappropriate ioctl for device". Im Quelltext finde ich jedoch keinmal den Aufruf ioctl() <- wenn es in Perl nicht noch eine andere Aufrufmöglichkeit gibt. Was erwartet FHEM hier? FHEM austicksen mit einem einfachen "return 0" funktioniert nicht.
Es ist egal, welche Verzweigung ich wähle (mit "directio"), ich erhalte immer die Fehlermeldung: "Can't open /dev/rf_fs20: Inappropriate ioctl for device"
Ich weiß nicht, woher die Rückmeldung "ENOTTY" kommt. Ich habe im Internet gelesen, dass Perl bei Open() (macht new Device::Serialport /dev/XXXX das gleiche?) automatisch auf TTY Device prüft, daher ioctl() automatisch aufgerufen wird. Diesen Ansatz werde ich erstmal weiter verfolgen, jedoch habe ich bis jetzt keine infos, was ioctl im Treiber machen soll.
> Ich wei nicht, woher die R ckmeldung "ENOTTY" kommt.
Dann starte mal perl mit strace, damit Du die systemcalls siehst.
> dass Perl bei Open() (macht new Device::Serialport /dev/XXXX das > gleiche?) automatisch auf TTY Device pr ft, daher ioctl() automatisch > aufgerufen wird.
Das habe ich auch bei anderen Programmen gesehen, wenn diese wissen wollen, ob
man seek verwenden kann.
Ich hab jetzt mal ein einfaches Perl Programm geschrieben um das mit strace aufzurufen (FHEM liefert einfahc viel zu viele Rückgabewerte...). Kernelement lautet:
Man sieht also, dass ioctl wirklich aufgerufen wird und den gleichen Fehler auswirft. Jedoch übt sich dieser in keinsterweise aus. In FHEM wird ja scheinbar in dem Abschnitt
eine negative Rückmeldung gegeben. Ich muss wohl überprüfen, ob noch irgendwo anders der Fehler Log(3, "Can't open $dev: $!"); in Log geschrieben wird.
was hälst Du von der Alternative statt eines Devices ein TCP-Netzwerkgerät über Sockets zu simulieren? Auf diese Weise ersparst Du Dir evtl. betriebsystemspezifische Probleme mit Devices.
Dein Modul ist dann auch universeller über Netzwerk nutzbar und kann auch ohne root laufen..
Ich nutze bei meinem Code (TRX, RFXCOM) meist TCP für die Tests (über die Programme netcat, nc) zur Simulation. Damit ich die Initialisierung nicht nachstellen muss, haben meine Module eine "noinit"-Option.
Am Dienstag, 22. Mai 2012 07:09:37 UTC+2 schrieb Willi:
> Hallo Survi,
> was hälst Du von der Alternative statt eines Devices ein TCP-Netzwerkgerät > über Sockets zu simulieren? Auf diese Weise ersparst Du Dir evtl. > betriebsystemspezifische Probleme mit Devices.
> Dein Modul ist dann auch universeller über Netzwerk nutzbar und kann auch > ohne root laufen..
> Ich nutze bei meinem Code (TRX, RFXCOM) meist TCP für die Tests (über die > Programme netcat, nc) zur Simulation. Damit ich die Initialisierung nicht > nachstellen muss, haben meine Module eine "noinit"-Option.
Wäre sicherlich auch eine Möglichkeit, jetzt verfolg ich aber erstmal den Ansatz mit dem Treiber (ab einem bestimmten Punkt will man es einfach durchziehen^^)
Interessanter Weise kam der Fehler nach einer erneuten Installation nicht mehr auf. Jetzt pass ich den Treiber noch weiter an. Ich hab allerdings öfter das Problem, dass ich mit "define XXX CUL XXXX" keinen neuen CUL anlegen kann. In den meisten Fällen hab ich vorher einen gelöscht um Fehler in dem Init Teil zu sehen. Es kommt auch keine Fehlermeldung oder so, es wird nur kein neues Gerät angelegt. Gibts dafür eine Erklärung?
Ich habe noch ein bisschen weiter an meinem Treiber geschrieben und musste feststellen, dass ich noch nicht alle Teile des FHEM Programm Codes verstehe. Gibt es eine Übersicht über dei gesamten Datenstruktur eines CUL Devices? Momentan habe ich ein Problem in der 00_CUL.pm:
Was passiert in dieser Zeile? Warum kommt es hier zu einem Timeout? Diese Werte in USBDev werden doch nur von FHEM beeinflusst und nicht vom CUL oder? Ruft "->read" oder "->write" eine Funktion auf?
Ich komme mit den ganzen Werten nicht zurecht, die in hash->XXX festgehalten sind.....
>Ich habe noch ein bisschen weiter an meinem Treiber geschrieben und musste >feststellen, dass ich noch nicht alle Teile des FHEM Programm Codes >verstehe. Gibt es eine Übersicht über dei gesamten Datenstruktur eines CUL >Devices? Momentan habe ich ein Problem in der 00_CUL.pm:
>Was passiert in dieser Zeile? Warum kommt es hier zu einem Timeout? Diese >Werte in USBDev werden doch nur von FHEM beeinflusst und nicht vom CUL >oder? Ruft "->read" oder "->write" eine Funktion auf? >Ich komme mit den ganzen Werten nicht zurecht, die in hash->XXX >festgehalten sind.....
>-- >To unsubscribe from this group, send email to >cul-fans+unsubscribe@googlegroups.com
Ich hatte mir schon gedacht, dass ein systemcall erfolgt - über das read(999) erfolgt doch irgendwo (wo genau?) anders ein Funktionsaufruf oder?. Soweit ich weiß, versteht der CUL nur Anweisungen, die mit A a B C c D d E e F f G I i M l O P q R s T t u V W w X beginnen. Wo wird den der Parameter "999" aufgelöst?
Kommt irgendwann dann wieder ein DevIO Aufruf?
Auf jeden Fall schonmal danke für die schnelle Antwort!
Treiber läuft jetzt recht gut, er wird voll initialisiert und ich kann Daten ausgeben. Allerdings hab ich auch inzwischen zwei Perl Bücher hier liegen und komm mit dem CU-Modul ganz gut zu recht. Vielleicht werd ich doch noch ein eigenes schreiben...
Daten einlesen funktioniert leider nicht, alles was ich in den Treiber schreibe kommt nicht in FHEM an (zumindest nichts aus der Global Loop), die CUL_Answers sind kein Problem("V", "T01" usw. wird beantwortet)
Der CUL wird scheinbar nicht passiv ausgelesen, es gibt keinen InternalTimer in CUL_Define($$).
Mechanismus fuer aktive Readings*: TODO: Mechanismus mit ParseFn, GetFn, Match usw. beschreiben (wie in fhem 4.x)!*
Verdammt ;-)
Dennoch vielen Dank für die Hilfe -> bin mit dem Ergebinis sehr zufrieden. Steuere gerade 6 indirekte Beleuchtungen hinter meinem Fernsehr (raum voll beleuchtet -> kino flair -> komplette Dunkelheit) - Danke!
> Der CUL wird scheinbar nicht passiv ausgelesen, es gibt keinen > InternalTimer in CUL_Define($$).
Unter Linux wird nicht gepollt, sondern via select auf Daten gewartet. Unter
Windows pollt fhem alle USB Geraete (da Windows select nur fuer sockets
anbietet), wenn Du also Deinen Treiber schnell noch unter Windows
implementierst, dann musst Du fhem nicht aendern :)
Ich bin mir nicht sicher, ob ich select() verstanden habe... Im Grunde genommen prüft select doch nur, ob an dem FD Daten anliegen oder nicht (ohne das Device zu blockieren und mit Timeout). Somit müsste dieser auch die Daten "finden", die ich in meinen Treiber schreibe. Ich sag dann ja zum Beispiel "F12345600\n\n" (z.b. fernsehr wurde ausgeschaltet) und gebe dem Treiber bekannt, dass 11 Byte zum schreiben bereit sind.
select() wird glaub ich auch in CUL_ReadAnswer verwendet und funktioniert dabei auch. Ich prüf mal meine write funktion....
> Ich sag dann ja zum Beispiel "F12345600\n\n" (z.b. fernsehr wurde
> ausgeschaltet) und gebe dem Treiber bekannt, dass 11 Byte zum schreiben
> bereit sind.
Aus meiner grauer Vorzeit als Kernel-Programmierer meine ich noch zu wissen,
dass der Treiber select aktiv unterstuetzen muss, da select eine Kernel und
nicht "nur" Bibliotheksfunktion ist. Evtl. wird im Linux Kernel select unter
dem SYSV Namen poll implementiert.
> Aus meiner grauer Vorzeit als Kernel-Programmierer meine ich noch zu > wissen, > dass der Treiber select aktiv unterstuetzen muss, da select eine Kernel > und > nicht "nur" Bibliotheksfunktion ist. Evtl. wird im Linux Kernel select > unter > dem SYSV Namen poll implementiert.
Ja absolut richtig. Gerade nochmal nachgeschlagen: im Treiber muss eine Funktion driver_poll exisiteren, die für poll() und select() benötigt wird. Es funktioniert jetzt auch alles soweit, leider schneidet FHEM die letzten beiden elemente ab.
Ich muss nur noch herausfinden, was der Ausdruck if("$dmsg =~ m/^[AFTKEHRS]([A-F0-9][A-F0-9])+$/") abfragt. dmsg ist F12345600, da die IF Abfrage wahr ist, wird dann zwei Elemente abgeschnitten und FHEM versteht die Nachricht "F123456" nicht. Der Ausdruck heißt doch ...beginnt mit AFTK... dann hexkette (bis 9?) +$/(???) - ich versteh die abfrage nicht, normalerweise überträgt der CUL das extended byte doch nur wenns benötigt wird... naja ein bisschen weiter probieren