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

Материал из roboforum.ru Wiki
Перейти к: навигация, поиск
 
Строка 2: Строка 2:
  
 
== Что потребуется? ==
 
== Что потребуется? ==
*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 ==
 +
Для примера используем '''miniterm.py''' из папки '''examples'''
 +
 
 +
ниже приведен его код:
 +
 
 +
#!/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
 +
    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)
 +
    sys.exitfunc = 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")

Версия 01:27, 1 июля 2007

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

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

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

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

PySerial - examples

Для примера используем miniterm.py из папки examples

ниже приведен его код:

#!/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
   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)
   sys.exitfunc = 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")