2017-01-17 2 views
2

Ich schreibe einen Client für ein Netzwerkgerät mit pyserial, die für ein paar Sekunden nach dem Anmelden im Gerät und bevor eine Eingabeaufforderung auf dem Gerät erhalten bleibt. das Bytes über die Linie Tracing I die folgenden Escape-Sequenzen sehen ist die Ursache für die halten:Escape-Sequenzen Interrupt pyserial Client

0003a0 73 65 20 6c 65 76 65 6c 0d 0a 0d 1b 5b 39 39 39  |se level....[999| 
0003b0 39 42 0d 1b 5b 39 39 39 39 42 1b 5a 20 20 1b 5b  |9B..[9999B.Z .[| 
0003c0 36 6e 0d 0d 0d 0d 5b 61 64 6d 69 6e 40 73 77 69  |6n....[[email protected]| 
0003d0 74 63 68 5d 20 3e 20 20 20 20 20 20 20 20 20 20  |tch] >   | 

Wenn screen Verwendung mit dem Gerät zu verbinden, wird keine Verzögerung gesehen als screen wird in geeigneter Weise reagieren.

0003a0 73 65 20 6c 65 76 65 6c 0d 0a 0d 1b 5b 39 39 39  |se level....[999| 
0003b0 39 42 0d 1b 5b 39 39 39 39 42 1b 5a 20    |9B..[9999B.Z | 

           ---=== WRITE ===--- 
000000 1b 5b 3f 31 3b 32 63         |.[?1;2c   | 

           ---=== READ ===--- 
000000 20 1b 5b 36 6e           | .[6n   | 

           ---=== WRITE ===--- 
000000 1b 5b 35 37 3b 33 52         |.[57;3R   | 

           ---=== READ ===--- 
000000 1b 5b 34 6c 1b 5b 32 30 6c 1b 5b 3f 34 37 6c 1b  |.[4l.[20l.[?47l.| 
000010 5b 3f 37 68 1b 5b 3f 35 6c 1b 5b 3f 32 35 68 1b  |[?7h.[?5l.[?25h.| 
000020 5b 48 1b 5b 39 39 39 39 42 1b 5b 36 6e    |[H.[9999B.[6n | 

           ---=== WRITE ===--- 
000000 1b 5b 35 37 3b 31 52         |.[57;1R   | 

           ---=== READ ===--- 
000000 1b 5b 48 1b 5b 39 39 39 39 42 1b 44 1b 5b 39 39  |.[H.[9999B.D.[99| 
000010 39 39 41 1b 5b 36 6e         |99A.[6n   | 

           ---=== WRITE ===--- 
000000 1b 5b 31 3b 31 52          |.[1;1R   | 

           ---=== READ ===--- 
000000 1b 5b 48 1b 5b 39 39 39 39 43 1b 5b 36 6e    |.[H.[9999C.[6n | 

           ---=== WRITE ===--- 
000000 1b 5b 31 3b 31 34 31 52        |.[1;141R  | 

           ---=== READ ===--- 
000000 1b 5b 48 c4 9b 48 1b 5b 36 6e 0d 20 20 20    |.[H..H.[6n.  | 

           ---=== WRITE ===--- 
000000 1b 5b 31 3b 33 52          |.[1;3R   | 

           ---=== READ ===--- 
000000 1b 5b 48 1b 5b 39 39 39 39 43 1b 5b 36 6e 20 1b  |.[H.[9999C.[6n .| 

           ---=== WRITE ===--- 
000000 1b 5b 31 3b 31 34 31 52        |.[1;141R  | 

           ---=== READ ===--- 
000000 5b 36 6e 20 1b 5b 36 6e        |[6n .[6n  | 

           ---=== WRITE ===--- 
000000 1b 5b 31 3b 31 34 32 52 1b 5b 32 3b 32 52    |.[1;142R.[2;2R | 

           ---=== READ ===--- 
000000 1b 5b 33 3b 35 72 1b 5b 48 1b 5b 36 6e 0a 0a   |.[3;5r.[H.[6n.. | 
           ---=== WRITE ===--- 
000000 1b 5b 31 3b 31 52          |.[1;1R   | 

           ---=== READ ===--- 
000000 0a 0a 0a 0a 0a 1b 5b 36 6e 1b 5b      |......[6n.[  | 

           ---=== WRITE ===--- 
000000 1b 5b 35 3b 31 52          |.[5;1R   | 

           ---=== READ ===--- 
000000 39 39 39 39 42 1b 5b 36 6e 1b 5b 72     |9999B.[6n.[r | 

           ---=== WRITE ===--- 
000000 1b 5b 35 3b 31 52          |.[5;1R   | 

           ---=== READ ===--- 
000000 1b 5b 31 3b 39 39 39 39 72 0d 0d 0d 1b 5b 39 39  |.[1;9999r....[99| 
000010 39 39 42 5b 61 64 6d 69 6e 40 73 77 69 74 63 68  |99B[[email protected]| 
000020 5d 20 3e 20           |] >    | 

Was genau macht diese Serie von Escape-Sequenzen und was ist der beste Weg, dies in meinem Client zu behandeln?

from asyncio import Protocol, get_event_loop 
from serial.aio import create_serial_connection 

class Serial(Protocol): 

    def connection_made(self, transport): 
     self.transport = transport 

    def data_received(self, data): 
     self.buffer += data.decode("utf-8") 
     self.handle() 

    def send(self, line): 
     self.transport.write("{}\r\n".format(line).encode()) 

loop = get_event_loop() 
coro = create_serial_connection(loop, Serial, "/dev/ttyUSB0") 
loop.run_until_complete(coro) 
loop.run_forever() 
+0

Es kann Es lohnt sich, zu versuchen, dem Gerät auf der anderen Seite mitzuteilen, dass der lokale Client diese Escape-Sequenzen nicht versteht, sodass das Gerät sie nicht sendet. Vielleicht gibt es eine Möglichkeit, den Terminaltyp oder die Umgebungsvariable TERM zu konfigurieren? Die andere Seite erwartet höchstwahrscheinlich ein _xterm_ oder _vt100_ oder ähnliches Terminal. – blubberdiblub

+0

Ja, es ist möglich, dem Gerät zu sagen, dass es die Sequenzen nicht senden soll, aber ich wollte mehr über den Prozess erfahren. –

+0

Nun, wenn Sie die Escape-Sequenz irgendwie erkennen und eine passende Antwort senden können, würde das wahrscheinlich auch funktionieren und würde wahrscheinlich das Pausierungsproblem lösen. Der relevante Standard ist [ECMA-48] (https://www.ecma-international.org/publications/standards/Ecma-048.htm). – blubberdiblub

Antwort

4

Das Chunk mit [6n (und der Escape-Zeichen vorangeht) fragt das Terminal es zu sagen, wo sich der Cursor befindet, als Teil der Bildschirmgröße zu bestimmen. Anscheinend pyserial versteht das nicht, und Sie müssen eine Weile auf das Programm warten, das die Bitte aufgibt und fortfährt.

In XTerm Control Sequences:

CSI Ps n Device Status Report (DSR). 
... 
      Ps = 6 -> Report Cursor Position (CPR) [row;column]. 

wo CSI die Sequenz Initiatorsteuerung entkommen [.

Wenn Sie screen laufen, es interprets diese Kontrollsequenz (dh es liest, versteht und Antworten angemessen):

 
     case 'n': 
      if (a1 == 5) /* Report terminal status */ 
       Report(win, "\033[0n", 0, 0); 
      else if (a1 == 6) /* Report cursor position */ 
       Report(win, "\033[%d;%dR", win->w_y + 1, win->w_x + 1); 

Der Statusbericht Kontrollsequenz von einigen Programmen verwendet wird, wie resize, um die Größe des Bildschirms Ihres Terminals zu bestimmen. Es funktioniert, indem man den Cursor in eine unglaublich weit unten rechts stehende Ecke bewegt und dann (weil die Terminals Grenzen haben) fragt, wie weit es gekommen ist. Dieses spezielle Beispiel verwendet nicht resize, das 999 für jede Koordinate sendet (aber es ist fraglich, ob es ein reales Szenario gibt, in dem vier Ziffern benötigt werden).

Die Anwendung, die die Gerätestatus Steuersequenz bewegt den Cursor sendet unten mit der Flucht[9999B und verwendet offenbar, dass später beim Scrollen Rand mit endet mit der Sequenz Einrichtung r. Dies ist eine häufig verwendete Funktion VT100 nicht in ECMA-48 (die r bezeichnet eine privaten Gebrauch Sequenz, das heißt, nicht genormt).

Wenn Sie einen falschen Wert für die Cursorposition angeben, erhalten Sie möglicherweise schlechte Ergebnisse.

er auch mit zwei verschiedenen Kontrollsequenzen versucht, den Cursor auf die Startseite (oben links) in dieser Reihenfolge von der screen lesen zu bewegen/schreibt:

1b 5b 48 c4 9b 48 

(0x9b ist die 8-bit Äquivalent 0x1b, 0x5b oder escape[).

So Ihre Entscheidungen sind einige Beispiele:

  • beseitigen die (möglicherweise unnötige) Abfrage für Bildschirm-Größe oder
  • ändern Ihre pyserial Skript der Gerätestatus Steuersequenz zu handhaben