ProJet LevelJet Ausgabe empfangen

Begonnen von housekeeper, 27 April 2013, 14:03:53

Vorheriges Thema - Nächstes Thema

housekeeper

Seit Kurzem habe ich ein ProJet LevelJet-WL gerät an unserem Öltank installiert.

Der Aufbau besteht aus drei Komponenten: Ultraschall-Sensorkopf 125 KHz, Funk Sender 868 MHz - wasserdicht und Funk Anzeigeeinheit 868 MHz.

Die Funk Anzeigeeinheit stellt die empfangenen Daten über eine serielle Schnittstelle (RS232 mit TTL-Pegel) an einer 6-poligenn RJ11 Buchse zur Verfügung.

Ich habe nun ein RJ11 Kabel mit einem FTDI USB to Serial Konverter verbunden, und das Ganze meinem PC über die USB Schnittstelle angeboten. Sowohl über Windows 7 (COM32 und PUTTY) als auch Linux (/dev/ttyUSB0 und Minicom) kann ich die Datenpakete ( 12 bytes einmal in der Minute empfangen und mitloggen.

Leider sind meine FHEM-Kenntnisse eher rudimentär :-( , im Log finde ich Folgendes

2013.04.27 12:17:08 1: usb create starting
2013.04.27 12:17:08 3: Opening TCM310 device /dev/ttyUSB0
2013.04.27 12:17:08 3: Setting TCM310 baudrate to 57600
2013.04.27 12:17:09 3: TCM310 device opened
2013.04.27 12:17:09 3: Opening TCM120 device /dev/ttyUSB0
2013.04.27 12:17:09 3: Setting TCM120 baudrate to 9600
2013.04.27 12:17:09 3: TCM120 device opened
2013.04.27 12:17:09 3: Opening FHZ device /dev/ttyUSB0
2013.04.27 12:17:09 3: Setting FHZ baudrate to 9600
2013.04.27 12:17:09 3: FHZ device opened
2013.04.27 12:17:09 3: Opening TRX device /dev/ttyUSB0
2013.04.27 12:17:09 3: Setting TRX baudrate to 38400
2013.04.27 12:17:09 3: TRX device opened
2013.04.27 12:17:10 3: Opening ZWDongle device /dev/ttyUSB0
2013.04.27 12:17:10 3: Setting ZWDongle baudrate to 115200
2013.04.27 12:17:10 3: ZWDongle device opened
2013.04.27 12:17:10 1: usb create end


Devices werden nicht erzeugt.

Der Event Monitor zeigt auch bei noch so gespanntem Draufschauen  ... NICHTS

Vermutlich muß man dazu nicht einmal ein Perl-Modul bauen, sondern könnte einfach über einen AT Befehl mit einem Oneliner á la

while true; do read line < /dev/ttyUSB0; echo $line; done

in Intervallen Stichproben machen.

Wer weiß Rat ?

P.S. Das Signal über CUL zu empfangen kann man m.E. ausschließen, da ProJet nach eigenen Angaben ein proprietäres Übertragungsverfahren einsetzt, aber wer weiß ?

housekeeper

Hmmmm.... Das allgemeine Interesse hält sich offensichtlich in Grenzen.

Jedenfalls bin ich einen Schritt weiter, mit

socat - /dev/ttyUSB0,b19200,readbytes=12

bekomme ich das Telegramm angezeigt, allerdings als hex-string. Mit

{ my $result = `socat - /dev/ttyUSB0,b19200,readbytes=12`;; $result }

in der Web-Oberfläche von FHEM ebenfalls.

Im nächsten Schritt versuche ich

define LevelJet at +*00:01:00 {my $leveljet=unpack ('h*',`socat - /dev/ttyUSB0,b19200,readbytes=12`);; Log 1, "Leveljet: $leveljet"} Man beachte 'h*', damit werden die Bytes schon richtig angeordnet.

Leider funktioniert das nur sporadisch (manchmal ja - manchmal nein, mit dem Schwerpunkt auf nein). Deshalb verwende ich erst mal ein "workaround"

Ein shell Skript wird gestartet:

define ReadLevelJet notify global:INITIALIZED "( while true; do socat - /dev/ttyUSB0,b19200,readbytes=12 > /var/InternerSpeicher/leveljet; sleep 60; done ) &"

und der at geändert in

define LevelJet at +*00:01:00 {my $leveljet=unpack ('h*',`cat /var/InternerSpeicher/leveljet`);; Log 1, "Leveljet: $leveljet"}

Im Log erscheint jetzt brav
2013.04.29 07:56:08 1: Leveljet: 00015f20be30a710c30005eb


Ein Tipp von den Perl Gurus, wie das elegant in lesbare Form gebracht werden kann, wäre jetzt hilfreich, bitte nicht alle auf einmal ;-)

housekeeper

So, aktuell vorletzter Stand ist jetzt, Anlage eines Dummy

define LevelJetStatus dummy

und Einrichten eines at Hilfs-Moduls

define ReadLevelJet at +*00:10:00 {my $leveljet = unpack('H*',`socat - /dev/ttyUSB0,b19200,nonblock,raw,echo=0,readbytes=12`);; fhem "set LevelJetStatus $leveljet"}

(Alles eine Zeile)

Die Anzeige im Webfrontend sieht damit so

dummy

LevelJetStatus      0010f502eb037a013c0050be
aus.

Jetzt fehlt noch die Umwandlung des Hex-Wurms in menschenlesbare Zahlen, und eine Überwachungsfunktion für schnelle Pegeländerungen (= Loch im Tank), das war eigentlich der Hauptantrieb für diese wilde Bastelei.


housekeeper

Zitat von: housekeeper schrieb am Mo, 29 April 2013 18:40Jetzt fehlt noch die Umwandlung des Hex-Wurms in menschenlesbare Zahlen, und eine Überwachungsfunktion für schnelle Pegeländerungen (= Loch im Tank), das war eigentlich der Hauptantrieb für diese wilde Bastelei.


Da der LevelJet einige Informationen liefert, die jedoch, bis auf den Abstand vom Sensor zur Flüssigkeitsoberfläche, alle errechnet werden, habe ich mich auf das eine Byte gestürzt, das den Füllgrad in % angibt. Daraus kann ich den Bestand in Litern errechnen.

Damit landen wir bei

define LevelJet at +*00:15:00 {my $prozent = hex(substr(unpack('H*',`socat -u /dev/ttyUSB0,b19200,echo=0,readbytes=12 -`),16,2));; my $liter = 6230 * $prozent / 100;; fhem "set LevelJetStatus Tankinhalt $liter Liter $prozent %"}


für das at device.

Mit

createlog LevelJetStatus

legt FHEM eine Logdatei an, in der der Verlauf aufgezeichnet wird.




kct-networx

#4
Hi housekeeper,

habe eben gerade erst diesen Beitrag gefunden und kann nur sagen: "Hut ab!"
Das was du hier zusammen gestellt hast funktioniert auf Anhieb und ist perfekt für alle LevelJet Besitzer!! Cool!  8)

Ich habe den Abfragestring etwas modifiziert, da mein LevelJet durch Umstellung am Gerät die Daten wie "Füllstand in Litern", "Abstand zur Oberfläche in mm" und " Füllhöhe in mm" nun bei mir im Klartext ausgibt als Komma separierte Werte.

Hier ein Beispiel wie die Daten dann vom LevelJet ankommen:
5200 , 377 , 1143
Der Mode am LevelJet kann im Menü verändert werden ("serial mode" --> "verbose" liefert die Klartext Daten ohne Hex Umwandlung)

Hier ein Beispiel wie ich deine Vorlage ändern musste, damit es mit dem Klartext geht:
define ReadLevelJet at +*00:15:00 {my $leveljetreading = `socat - /dev/ttyUSB0,b19200,nonblock,raw,echo=0,readbytes=18`;; fhem "set Oeltank $leveljetreading"}

Per RegEx lässt sich so der gesetzte Wert noch mit dem attribut "stateFormat" in einen verständliches Format bringen (sofern man nur die Literangabe sehen will).

Beispiel:
attr Oeltank stateFormat {sprintf("%d",ReadingsVal("Oeltank","state",0))." Liter"}

Was mir derzeit noch unklar ist:
Wie kann ich die anderen beiden Werte verwenden (Abstand, Füllhöhe)?
Kann ein dummy mehr als ein Wert haben (ähnlich wie Temperatur/Luftfeuchte Sensoren ja auch 2 Werte liefern)?


Bin für jede Idee dankbar.

Cheers
Markus

kct-networx

Hi zusammen,

eine kleine Anmerkung noch zum Thema:

Nach fast einem Jahr kann ich sagen, dass der Auslesevorgang in 90% der Fälle ohne Probleme funktioniert.
In den restlichen 10% wurden fehlerhafte Zeichen anstatt Zahlen über den seriellen Port eingelesen.
Diese Sonderzeichen verhageln einem natürlich die Möglichkeit einen gescheiten Plot zu erzeugen gewaltig.

Nach ein paar Experimenten mit RegEx konnte ich gute Ergebnisse mit der folgenden Modifikation erreichen:
efine ReadLevelJet at +*00:15:00 {my $leveljetreading = `socat - /dev/ttyUSB0,b19200,nonblock,raw,echo=0,readbytes=18 | egrep "[0-9]{2,4} , [0-9]{1,4} , [0-9]{1,4}"`;; fhem "set Oeltank $leveljetreading"}
Mit dieser Änderung wird geprüft ob das Format genau dem entspricht, wie es vom LevelJet gesendet wird. Nur dann wird die Variable "Oeltank" (dummy) hier im Beispiel gesetzt.
Sollten einzelne Ziffern bei der Übertragung "verloren" gehen, kann dies allerdings nicht helfen.

Cheers
Markus

Lars_

Hallo,

das ist genau das was ich suche, schon vorab mal ein Danke für dein Engagement.
Gibt es mittlerweile die Möglichkeit das auch über einen CUL-Stick (868) zu empfangen oder passiert das bei dir immer per Kabel?

Danke vorab
Lars
Fhem auf rpi 3   fhem auf rpi b+
1 x CULHM/jeelink v3c   1 x CULHM
7 x HM-CC-RT-DN   3 x HM-CC-RT-DN
5 x HM-Sec-RHS

DerPeter

#7
Hallo zusammen,

da dies mein erster Post im fhem-Forum ist, mal kurz vorneweg:
Ich beschäftige mich seit ca. 3Monaten aktiv mit fhem und bin total begeistert, was damit auf einem rpi möglich ist. Zum Beispiel ist die Heizung mittlerweile komplett mit ELV-MAX! bestückt und funktioniert TipTop. Wenn auch etwas Lebenszeit dafür draufgeht...
Wirklich ein großes Lob an die Entwickler und die Community!

Beim Anbinden eines LevelJET an fhem bin ich auf ähnliche Probleme, wie die anderen Schreiber in diesem Thread gestoßen. So richtig gut funktioniert es nicht.

Habe mich darum mal am Schreiben eines Moduls für die serielle Kommunikation des LevelJET versucht. Als Gerüst/Vorlage habe ich 66_ECMD.pm von Boris Neubert genommen - hoffe das geht in Ordnung. (Habe noch nie was in Perl gemacht und an die Struktur von fhem muss man sich ja auch erstmal rantasten.)

- Serielle Kommunikation am LevelJET auf <verbose> stellen.
- Das Modul im Anhang "98_LevelJet.pm" >>> ins fhem Modulverzeichnis kopieren und laden.
- Device anlegen, Beispiel: define LJet LevelJet serial /dev/ttyUSB1@19200
- Eine Doku befindet sich dann unter "Device specific help" bzw. etwas Zusatzkram im anderen Anhang "98_LevelJet Anmerkungen.pdf"

Für mich funktioniert es gut.

Gruß, Peter
rpi b+ / rpi2 b; cul868; jeelink; MAX! (ht, wt, fk, et); lacrosse;

kct-networx

Hi Peter,

das ist ja Klasse dass du ein Modul für den LevelJet gebaut hast.
Funktioniert echt super!
Bisher ohne Probleme.

Hast du schon versucht dieses Modul offiziell zu FHEM hinzufügen zu lassen?
Meiner Meinung nach ist es dazu würdig.

Vielleicht in einem zukünftigen Release noch die Funktionen "event-on-change-reading" und "event-on-update-reading" hinzufügen, um die Datenlast zu reduzieren?!?!??
Dann wäre das Modul absolut Top und definitiv produktiv einsetzbar.

Grüße
Markus

DerPeter

#9
Hi Markus,

schön, daß es jemand genützt hat. Ich selbst hatte dies schon so gut wie vergessen.
"Offiziell" möchte ich es eigentlich nicht machen.

Meine aktuelle Lösung sieht momentan so aus: LevelJetST >>> Arduino-Nano >>> Funkmodul_RFM12B >>> JeeLink(modifizierter Sketch) >>> fhem-Modul f. LevelJet
Hat den Vorteil, daß ich kein Kabel zum rpi verlegen mußte und man festlegen kann, wann und wie oft Daten übertragen werden sollen. Außerdem werden die Schaltausgänge mit ausgewertet. Der JeeLink kann die Daten für Lacrosse, den LevelJet und einen anderen Typ Eigenbausensor empfangen/auswerten. Es ist natürlich viel Bastelei und deutlich höherer Programmieraufwand - aber am Ende eine smarte Lösung.

Im Anhang mal ein Bild dazu ...

Wegen der Datenlast: Der Leveljet bläst natürlich viel zuviel Daten raus. Ich denke, Du meinst die hohe Datenmenge beim Loggen und resultierend die schlechte Performance beim Darstellen von Plots.
Probiers doch mal mit dem Attribut: "event-min-interval" - in etwa so:
attr LJet event-min-interval Volumen:300
oder auch in Kombination mit "event-on-change".

Gruß, Peter
rpi b+ / rpi2 b; cul868; jeelink; MAX! (ht, wt, fk, et); lacrosse;