FHEM Forum

FHEM - Hausautomations-Systeme => Sonstige Systeme => Thema gestartet von: Freibeuter am 04 Juni 2014, 11:08:08

Titel: ECMD teilt String (willkürlich) auf
Beitrag von: Freibeuter am 04 Juni 2014, 11:08:08
Hallo,
leider komme ich mit dem neuen ECMD nicht mehr an die Daten von meiner Almemo Messwererfassung ran.
Da ich zu wenig Perl kann, habe ich mir bisher den gesamten AntwortString in ein Reading schreiben lassen und dieses dann in FHEM ausgewertet:
Dafür sende ich ein "S1" + CHR(13) an das Almemound bekam dann folgenden String:
"18:59:02 00: +0022.6 �C 01: -0080.1 �C 02: +0006.8 �C 03: +0022.7 �C 05: +0000.2  % 16:  - - -  �C"

Nun sieht die Antwort so aus:
2014.06.04 10:32:44 3: RS232: write "S1\n"
2014.06.04 10:32:44 3: RS232: read "S1\r\n"
2014.06.04 10:32:44 3: RS232: read "\01718:59:02"
2014.06.04 10:32:45 3: RS232: read " 00: +0022.6 �C 01: -0080.1 �C 02: +0006.8 �C 03: +0022.7 �C 05: +0000.2  % 16:  - - -  �C.\r\n\022\003"

und manchmal ist der "Zeilenumbruch" auch noch mitten in einem Wert:
2014.06.04 10:32:29 3: RS232: write "S1\n"
2014.06.04 10:32:29 3: RS232: read "S1\r\n"
2014.06.04 10:32:29 3: RS232: read "\01718:58:"
2014.06.04 10:32:30 3: RS232: read "47 00: +0022.6 �C 01: -0080.1 �C 02: +0006.8 �C 03: +0022.7 �C 05: +0000.2  % 16:  - - -  �C.\r\n\022\003"

Wie kann ich ECMD dazu bringen erst nach einem CR den String auszugeben?
Vielen Dank!

Classdef sieht so aus :
get Temp cmd {"S1\n"}
reading TempS match ".*"


und in FHEM:
serial /dev/ttyUSB0@9600

Titel: Antw:ECMD teilt String (willkürlich) auf
Beitrag von: Dr. Boris Neubert am 04 Juni 2014, 12:03:39
Hallo,

Du brauchst eine maßgeschneiderte Regexp im match.

Viele Grüße
Boris
Titel: Antw:ECMD teilt String (willkürlich) auf
Beitrag von: Freibeuter am 04 Juni 2014, 12:39:21
Hallo Boris,
vielen Dank für die schnelle Antwort.

So weit bin ich schon:
get Temp cmd {"S1\n"}
get Temp expect "S1\r\n017\d+:\d+:\d%20\d:.*C.\r\n\022\003"
Oder besser so :
get Temp cmd {"S1\n"}
get Temp expect "S1\r\n017\d+:\d+:\d 00: \d.\d �C 01: \d.\d �C 02: \d.\d �C 03: \d.\d �C 05: \d.\d % 16:  - - -  �C.\r\n\022\003"

Aber wie verarbeite ich das �C was wohl ein °C sein soll, kann ich auch Leerzeichen eingeben oder %20 dafür einsetzen ?
Gruß Peter F.
Titel: Antw:ECMD teilt String (willkürlich) auf
Beitrag von: Freibeuter am 04 Juni 2014, 14:07:36
Wieder wird nicht der ganze String ausgelesen, was mache ich falsch ?
RS232: unexpected answer "S1\r\n" received (wrote "S1\n", expected S1\r\n017\d+:\d+:\d 00: \d.\d �C 01: \d.\d �C 02: \d.\d �C 03: \d.\d �C 05: \d.\d % 16:  - - -  �C.\r\n\022\003)

Meine Commandref:
get Temp cmd {"S1\n"}
get Temp expect "S1\r\n017\d+:\d+:\d 00: \d.\d �C 01: \d.\d �C 02: \d.\d �C 03: \d.\d �C 05: \d.\d % 16:  - - -  �C.\r\n\022\003"

Titel: Antw:ECMD teilt String (willkürlich) auf
Beitrag von: Icinger am 04 Juni 2014, 20:35:29
HI, ich habe das selbe Problem, das die Antworten von meinem Smartmeter von ECMD willkürlich gesplittet werden (siehe http://forum.fhem.de/index.php/topic,24194.0.html (http://forum.fhem.de/index.php/topic,24194.0.html)

Ich habe das jetzt so gelöst, dass ich ein Reading auf .* mache und mir in der 99_myutils den String immer weiter zusammensetze.
Bei jedem Aufruf der Sub wird dann einfach der String bei CRs aufgesplittet und weiterverarbeitet.

lg, ici
Titel: Antw:ECMD teilt String (willkürlich) auf
Beitrag von: Dr. Boris Neubert am 04 Juni 2014, 20:37:25
Hallo Peter,

Soforthilfe:  ein Punkt match jedes Zeichen.

Am besten schaust Du Dir einmal http://perldoc.perl.org/perlre.html (http://perldoc.perl.org/perlre.html) an oder ein anderes der unzähligen Tutorials zu Perl Regular Expressions.

Viele Grüße
Boris
Titel: Antw:ECMD teilt String (willkürlich) auf
Beitrag von: Dr. Boris Neubert am 04 Juni 2014, 20:51:00
Hallo,

wenn ich nochmal darüber nachdenke: der match hilft nicht.

Die Ursache ist in der commandref beschrieben:
ZitatData received from the physical device is processed as it comes in chunks. If for some reason a datagram from the device is split in transit, pattern matching and processing will most likely fail.

DevIO.pm liefert die Teile, wie sie vom Device kommen, an das Modul weiter. Das gibt es auch mit anderen Modulen. Dort gibt es ein PARTIAL-Internal, das die Einzelteile einsammelt, bis das Datagramm komplett ist. Im Prinzip wäre die ganze Sache auch bei ECMD über ein PARTIAL-Internal zu lösen.

Bei ECMD ist das aber nicht so einfach, weil die Datagramme ja alles Mögliche sein können.

Ich hatte mir bereits folgende Lösung dazu ausgedacht: wenn es eine match-Direktive zu einem Kommando gibt, werden Fragmente solange gesammelt, bis es einen Match gibt. Das führt bei unerwarteten Antworten zwangsläufig zu einer endlosen Warterei, so daß noch eine geeignete Abbruchbedingung benötigt wird. Dabei ist es bisher geblieben.

Du kannst mit etwas mehr Perl-Kenntnissen das Verhalten aber replizieren: baue Dir einen Postprozessor, welcher die empfangenen Fragmente in einem Partial-Reading sammelt. Nach jedem Sammeln wird geprüft, ob es einen Match gibt. Falls ja, wird das Reading in die Bestandteile zerlegt und in andere Readings eingetütet und das Partial-Reading geleert.

ici macht das Ganze wohl auch mit einer Hilfsfunktion in 99_myutils.pm. Das wird vermutlich die einfachste Lösung sein.

Viele Grüße
Boris



Titel: Antw:ECMD teilt String (willkürlich) auf
Beitrag von: Icinger am 04 Juni 2014, 22:35:53
Hallo Boris,

als Abbruch-Bedingung, wenn ein Device was anderes sendet als im Expect erwartet, wäre mMn

1) Wenn empfangene Zeichenkette länger als erwartet und/oder
2) Timeout nach x (Mili)sekunden, falls Device gar nichts sendet

denkenswert.

lg, Ici
Titel: Antw:ECMD teilt String (willkürlich) auf
Beitrag von: tbnobody am 10 August 2014, 12:03:40
Hallo,

ich stehe aktuell vor einem ähnlichen Problem. Habe einen Mikrocontroller mit dem Eventgesteuert mehrere Taster abgefragt werden. Der Status (pressed / released) wird via ECMD an FHEM gemeldet.

In der fhem.cfg sieht das folgendermaßen aus:

define I2Cgate ECMD serial /dev/ttyUSB0@9600
attr I2Cgate classdefs SWITCH=/opt/fhem/switch.classdef
define WZ_SwitchDown ECMDDevice SWITCH 4
attr WZ_SwitchDown IODev I2Cgate
define WZ_SwitchUp ECMDDevice SWITCH 3
attr WZ_SwitchUp IODev I2Cgate
define WZ_SwitchSel1 ECMDDevice SWITCH 1
attr WZ_SwitchSel1 IODev I2Cgate
define WZ_SwitchSel2 ECMDDevice SWITCH 2
attr WZ_SwitchSel2 IODev I2Cgate


Die switch.classdef Datei hat folgenden Inhalt:

params switchID

reading pressed match "p%switchID"
reading released match "r%switchID"


Laut Logfile werden die Daten zerstückelt empfangen.


2014.08.10 04:55:19 5: I2Cgate: Spontaneously received "p"
2014.08.10 04:55:19 5: I2Cgate dispatch p
2014.08.10 04:55:19 5: Triggering global (1 changes)
2014.08.10 04:55:19 5: Notify loop for global UNDEFINED ECMDDevice message p
2014.08.10 04:55:19 2: autocreate: define ECMDDevice message p
2014.08.10 04:55:19 1: ERROR: Unknown module message
2014.08.10 04:55:19 5: I2Cgate: Spontaneously received "2\r\n"
2014.08.10 04:55:19 5: I2Cgate dispatch 2


Das Ganze mit .* zu matchen und in einer Eigenen Routine zusammenzustückeln wurde ja oben beschrieben. Ich bin mir nur nicht sicher ob das auch für meinen Einsatzzweck funktioniert da die Empfangenen Daten ja verschiedene Schalter Objekte steuern.
Titel: Antw:ECMD teilt String (willkürlich) auf
Beitrag von: hajo23 am 13 August 2014, 20:46:39
ein Ansatz wäre:

reading firstpart match ".*(?!\n$)"
reading firstpart postproc {s/.*\n(.*)(?!\n$)/$1/s; $_}
reading lastpart match "(.*)\n"
reading lastpart postproc {s/(.*)\n/$1/; $_}


wenn "\n" das letzte Zeichen einer Message wäre, wobei lastpart immer greift. Man müsste also die Zeitstempel vergleichen, die Teile ggf. zusammenführen, auswerten und firstpart leeren.
Titel: Antw:ECMD teilt String (willkürlich) auf
Beitrag von: Dr. Boris Neubert am 06 September 2014, 22:58:40
Schaut bitte hier: http://forum.fhem.de/index.php/topic,21515.msg197863.html#msg197863 (http://forum.fhem.de/index.php/topic,21515.msg197863.html#msg197863)

Grüße
Boris
Titel: Antw:ECMD teilt String (willkürlich) auf
Beitrag von: Icinger am 07 September 2014, 08:07:18
Boris for president!  ;D

Danke, klingt vielversprechend. Wird ich heute gleich mal ausprobieren.
Titel: Antw:ECMD teilt String (willkürlich) auf
Beitrag von: Freibeuter am 26 Oktober 2014, 11:11:05
Ich beiße noch immer auf Granit :-(

Ausgangssituation:
eine Ccontrol II sendet fogenden String:
A23B123C123D(chr13)
und diesen möchte ich jetzt in 3 Readings A B C auslesen:

meine Classdef dazu ist:

get temp cmd {"get-temp".chr(0x0D)}

reading temp expect "A\dB\dC\dD\r"

ich nutze partial 2
und bekomme folgendes Log:
2014.10.26 10:44:02 0: RS232: write "get-temp\r"
2014.10.26 10:44:03 0: RS232: read "A6"
2014.10.26 10:44:03 0: RS232: read "10B530C595D"

Bin für jede Hilfe dankbar, und ja es liegt an meinen noch zu schlechten Perl Kenntnissen :-(
Schönen Sonntag Euch
Peter F.

Titel: Antw:ECMD teilt String (willkürlich) auf
Beitrag von: Dr. Boris Neubert am 26 Oktober 2014, 15:48:50
Du musst eine auf die Antwort passende Perl Regular Expression hinter expect verwenden. Am besten schlaust Du Dich zu Regex erst einmal auf.

Grüße
Boris