PySerial — различия между версиями

Материал из roboforum.ru Wiki
Перейти к: навигация, поиск
 
м
 
(не показано 15 промежуточных версий 3 участников)
Строка 1: Строка 1:
 +
[[Категория:Коммуникации]]
 +
[[Категория:HOWTO]]
 +
[[Категория:Python]]
 +
 +
 +
{{elec-stub}}
 +
 +
 
Опишу что потребуется для создания гипертерминала на питоне
 
Опишу что потребуется для создания гипертерминала на питоне
  
 
== Что потребуется? ==
 
== Что потребуется? ==
*python 2.3 (или старше)
+
*[http://ru.wikipedia.org/wiki/Python Python 2.3]
*pygtk + gtk (если будем использовать GUI)
+
*[http://ru.wikipedia.org/wiki/PyGTK PyGTK + GTK]
*pyserial (библиотека для работы с комом)
+
*[http://pyserial.sourceforge.net/ PySerial]
 +
 
 +
PyGTK это обертка над GTK поэтому нужны обе библиотеки
 +
они реализуют [http://ru.wikipedia.org/wiki/GUI GUI]
 +
 
 +
PySerial - библиотека работы с ком портом, работает как под Windows так и под [http://ru.wikipedia.org/wiki/POSIX POSIX] системами
 +
 
 +
== PySerial - examples ==
 +
 
 +
Во всех примерах линии RxD и TxD соединены.
 +
 
 +
=== miniterm.py ===
 +
код:
 +
<source lang="python">
 +
#!/usr/bin/env python
 +
# -*- coding: utf-8 -*-
 +
# Very simple serial terminal
 +
# (C)2002-2004 Chris Liechti <cliecht@gmx.net>
 +
 
 +
# Input characters are sent directly (only LF -> CR/LF/CRLF translation is
 +
# done), received characters are displayed as is (or as trough pythons
 +
# repr, useful for debug purposes)
 +
# Baudrate and echo configuartion is done through globals
 +
 
 +
 +
import sys, os, serial, threading, getopt
 +
 +
EXITCHARCTER = '\x04'  #ctrl+D
 +
 +
#first choose a platform dependant way to read single characters from the console
 +
if os.name == 'nt':
 +
    import msvcrt
 +
    def getkey():
 +
        while 1:
 +
            if echo:
 +
                z = msvcrt.getche()
 +
            else:
 +
                z = msvcrt.getch()
 +
            if z == '\0' or z == '\xe0':    #functions keys
 +
                msvcrt.getch()
 +
            else:
 +
                if z == '\r':
 +
                    return '\n'
 +
                return z
 +
 
 +
elif os.name == 'posix':
 +
    import termios, sys, os, atexit
 +
    fd = sys.stdin.fileno()
 +
    old = termios.tcgetattr(fd)
 +
    new = termios.tcgetattr(fd)
 +
    new[3] = new[3] & ~termios.ICANON & ~termios.ECHO
 +
    new[6][termios.VMIN] = 1
 +
    new[6][termios.VTIME] = 0
 +
    termios.tcsetattr(fd, termios.TCSANOW, new)
 +
    s = ''    # We'll save the characters typed and add them to the pool.
 +
    def getkey():
 +
        c = os.read(fd, 1)
 +
        #~ c = sys.stdin.read(1)
 +
        if echo: sys.stdout.write(c); sys.stdout.flush()
 +
        return c
 +
    def clenaup_console():
 +
        termios.tcsetattr(fd, termios.TCSAFLUSH, old)
 +
    atexit.register(clenaup_console)      #terminal modes have to be restored on exit...
 +
 
 +
else:
 +
    raise "Sorry no implementation for your platform (%s) available." % sys.platform
 +
 
 +
CONVERT_CRLF = 2
 +
CONVERT_CR  = 1
 +
CONVERT_LF  = 0
 +
 
 +
def reader():
 +
    """loop forever and copy serial->console"""
 +
    while 1:
 +
        data = s.read()
 +
        if repr_mode:
 +
            sys.stdout.write(repr(data)[1:-1])
 +
        else:
 +
            sys.stdout.write(data)
 +
        sys.stdout.flush()
 +
 
 +
def writer():
 +
    """loop and copy console->serial until EOF character is found"""
 +
    while 1:
 +
        c = getkey()
 +
        if c == EXITCHARCTER:
 +
            break                      #exit app
 +
        elif c == '\n':
 +
            if convert_outgoing == CONVERT_CRLF:
 +
                s.write('\r\n')        #make it a CR+LF
 +
            elif convert_outgoing == CONVERT_CR:
 +
                s.write('\r')          #make it a CR
 +
            elif convert_outgoing == CONVERT_LF:
 +
                s.write('\n')          #make it a LF
 +
        else:
 +
            s.write(c)                  #send character
 +
 
 +
 
 +
print a short help message
 +
def usage():
 +
    sys.stderr.write("""USAGE: %s [options]
 +
    Miniterm - A simple terminal program for the serial port.
 +
 
 +
    options:
 +
    -p, --port=PORT: port, a number, default = 0 or a device name
 +
    -b, --baud=BAUD: baudrate, default 9600
 +
    -r, --rtscts:    enable RTS/CTS flow control (default off)
 +
    -x, --xonxoff:  enable software flow control (default off)
 +
    -e, --echo:      enable local echo (default off)
 +
    -c, --cr:        do not send CR+LF, send CR only
 +
    -n, --newline:  do not send CR+LF, send LF only
 +
    -D, --debug:    debug received data (escape nonprintable chars)
 +
 
 +
""" % sys.argv[0])
 +
 
 +
if __name__ == '__main__':
 +
    #initialize with defaults
 +
    port  = 0
 +
    baudrate = 9600
 +
    echo = 0
 +
    convert_outgoing = CONVERT_CRLF
 +
    rtscts = 0
 +
    xonxoff = 0
 +
    repr_mode = 0
 +
   
 +
    #parse command line options
 +
    try:
 +
        opts, args = getopt.getopt(sys.argv[1:],
 +
            "hp:b:rxecnD",
 +
            ["help", "port=", "baud=", "rtscts", "xonxoff", "echo",
 +
            "cr", "newline", "debug"]
 +
        )
 +
    except getopt.GetoptError:
 +
        # print help information and exit:
 +
        usage()
 +
        sys.exit(2)
 +
   
 +
    for o, a in opts:
 +
        if o in ("-h", "--help"):      #help text
 +
            usage()
 +
            sys.exit()
 +
        elif o in ("-p", "--port"):    #specified port
 +
            try:
 +
                port = int(a)
 +
            except ValueError:
 +
                port = a
 +
        elif o in ("-b", "--baud"):    #specified baudrate
 +
            try:
 +
                baudrate = int(a)
 +
            except ValueError:
 +
                raise ValueError, "Baudrate must be a integer number, not %r" % a
 +
        elif o in ("-r", "--rtscts"):
 +
            rtscts = 1
 +
        elif o in ("-x", "--xonxoff"):
 +
            xonxoff = 1
 +
        elif o in ("-e", "--echo"):
 +
            echo = 1
 +
        elif o in ("-c", "--cr"):
 +
            convert_outgoing = CONVERT_CR
 +
        elif o in ("-n", "--newline"):
 +
            convert_outgoing = CONVERT_LF
 +
        elif o in ("-D", "--debug"):
 +
            repr_mode = 1
 +
 
 +
    #open the port
 +
    try:
 +
        s = serial.Serial(port, baudrate, rtscts=rtscts, xonxoff=xonxoff)
 +
    except:
 +
        sys.stderr.write("Could not open port\n")
 +
        sys.exit(1)
 +
    sys.stderr.write("--- Miniterm --- type Ctrl-D to quit\n")
 +
    #start serial->console thread
 +
    r = threading.Thread(target=reader)
 +
    r.setDaemon(1)
 +
    r.start()
 +
    #and enter console->serial loop
 +
    writer()
 +
 
 +
    sys.stderr.write("\n--- exit ---\n")
 +
</source>
 +
Результат работы:
 +
<source lang="text">
 +
vovan@ubuntu-vooon:~/scripts/python/com-wake/pyserial-2.2/examples$ python ./miniterm.py -Den -p 0 -b 115200
 +
--- Miniterm --- type Ctrl-D to quit
 +
hheelllloo  wwoorrlldd!!
 +
\n
 +
--- exit ---
 +
</source>
 +
 
 +
=== wxTerminal.py ===
 +
Пример терминала с графическим интерфейсом
 +
требует библиотеки xWdigets и wxPython
 +
 
 +
<gallery>
 +
Изображение:wxTerminalSettings.png|меню настройки порта
 +
Изображение:wxTerminal.png|главное окно
 +
</gallery>

Текущая версия на 07:32, 3 декабря 2009




Опишу что потребуется для создания гипертерминала на питоне

Что потребуется?

PyGTK это обертка над GTK поэтому нужны обе библиотеки они реализуют GUI

PySerial - библиотека работы с ком портом, работает как под Windows так и под POSIX системами

PySerial - examples

Во всех примерах линии RxD и TxD соединены.

miniterm.py

код: <source lang="python">

  1. !/usr/bin/env python
  2. -*- coding: utf-8 -*-
  3. Very simple serial terminal
  4. (C)2002-2004 Chris Liechti <cliecht@gmx.net>
  1. Input characters are sent directly (only LF -> CR/LF/CRLF translation is
  2. done), received characters are displayed as is (or as trough pythons
  3. repr, useful for debug purposes)
  4. Baudrate and echo configuartion is done through globals


import sys, os, serial, threading, getopt

EXITCHARCTER = '\x04' #ctrl+D

  1. first choose a platform dependant way to read single characters from the console

if os.name == 'nt':

   import msvcrt
   def getkey():
       while 1:
           if echo:
               z = msvcrt.getche()
           else:
               z = msvcrt.getch()
           if z == '\0' or z == '\xe0':    #functions keys
               msvcrt.getch()
           else:
               if z == '\r':
                   return '\n'
               return z

elif os.name == 'posix':

   import termios, sys, os, atexit
   fd = sys.stdin.fileno()
   old = termios.tcgetattr(fd)
   new = termios.tcgetattr(fd)
   new[3] = new[3] & ~termios.ICANON & ~termios.ECHO
   new[6][termios.VMIN] = 1
   new[6][termios.VTIME] = 0
   termios.tcsetattr(fd, termios.TCSANOW, new)
   s =     # We'll save the characters typed and add them to the pool.
   def getkey():
       c = os.read(fd, 1)
       #~ c = sys.stdin.read(1)
       if echo: sys.stdout.write(c); sys.stdout.flush()
       return c
   def clenaup_console():
       termios.tcsetattr(fd, termios.TCSAFLUSH, old)
   atexit.register(clenaup_console)      #terminal modes have to be restored on exit...

else:

   raise "Sorry no implementation for your platform (%s) available." % sys.platform

CONVERT_CRLF = 2 CONVERT_CR = 1 CONVERT_LF = 0

def reader():

   """loop forever and copy serial->console"""
   while 1:
       data = s.read()
       if repr_mode:
           sys.stdout.write(repr(data)[1:-1])
       else:
           sys.stdout.write(data)
       sys.stdout.flush()

def writer():

   """loop and copy console->serial until EOF character is found"""
   while 1:
       c = getkey()
       if c == EXITCHARCTER: 
           break                       #exit app
       elif c == '\n':
           if convert_outgoing == CONVERT_CRLF:
               s.write('\r\n')         #make it a CR+LF
           elif convert_outgoing == CONVERT_CR:
               s.write('\r')           #make it a CR
           elif convert_outgoing == CONVERT_LF:
               s.write('\n')           #make it a LF
       else:
           s.write(c)                  #send character


print a short help message def usage():

   sys.stderr.write("""USAGE: %s [options]
   Miniterm - A simple terminal program for the serial port.
   options:
   -p, --port=PORT: port, a number, default = 0 or a device name
   -b, --baud=BAUD: baudrate, default 9600
   -r, --rtscts:    enable RTS/CTS flow control (default off)
   -x, --xonxoff:   enable software flow control (default off)
   -e, --echo:      enable local echo (default off)
   -c, --cr:        do not send CR+LF, send CR only
   -n, --newline:   do not send CR+LF, send LF only
   -D, --debug:     debug received data (escape nonprintable chars)
""" % sys.argv[0])

if __name__ == '__main__':

   #initialize with defaults
   port  = 0
   baudrate = 9600
   echo = 0
   convert_outgoing = CONVERT_CRLF
   rtscts = 0
   xonxoff = 0
   repr_mode = 0
   
   #parse command line options
   try:
       opts, args = getopt.getopt(sys.argv[1:],
           "hp:b:rxecnD",
           ["help", "port=", "baud=", "rtscts", "xonxoff", "echo",
           "cr", "newline", "debug"]
       )
   except getopt.GetoptError:
       # print help information and exit:
       usage()
       sys.exit(2)
   
   for o, a in opts:
       if o in ("-h", "--help"):       #help text
           usage()
           sys.exit()
       elif o in ("-p", "--port"):     #specified port
           try:
               port = int(a)
           except ValueError:
               port = a
       elif o in ("-b", "--baud"):     #specified baudrate
           try:
               baudrate = int(a)
           except ValueError:
               raise ValueError, "Baudrate must be a integer number, not %r" % a
       elif o in ("-r", "--rtscts"):
           rtscts = 1
       elif o in ("-x", "--xonxoff"):
           xonxoff = 1
       elif o in ("-e", "--echo"):
           echo = 1
       elif o in ("-c", "--cr"):
           convert_outgoing = CONVERT_CR
       elif o in ("-n", "--newline"):
           convert_outgoing = CONVERT_LF
       elif o in ("-D", "--debug"):
           repr_mode = 1
   #open the port
   try:
       s = serial.Serial(port, baudrate, rtscts=rtscts, xonxoff=xonxoff)
   except:
       sys.stderr.write("Could not open port\n")
       sys.exit(1)
   sys.stderr.write("--- Miniterm --- type Ctrl-D to quit\n")
   #start serial->console thread
   r = threading.Thread(target=reader)
   r.setDaemon(1)
   r.start()
   #and enter console->serial loop
   writer()
   sys.stderr.write("\n--- exit ---\n")

</source> Результат работы: <source lang="text"> vovan@ubuntu-vooon:~/scripts/python/com-wake/pyserial-2.2/examples$ python ./miniterm.py -Den -p 0 -b 115200 --- Miniterm --- type Ctrl-D to quit hheelllloo wwoorrlldd!! \n --- exit --- </source>

wxTerminal.py

Пример терминала с графическим интерфейсом требует библиотеки xWdigets и wxPython