📄 serial.py
字号:
# serial.py
"""Win32 serial port interface.
Serial Communications DLLs (Wsc32.dll) by
MarshallSoft Computing, Inc.
POB 4543 Huntsville AL 35815. 205-881-4630.
Email: mike@marshallsoft.com
This module wraps the shared library Sio.pyd which
provides access to the Wsc32.dll.
This module exports classes:
PortDict - manages port parameters, looks like a dictionary
Port - wrap access to the Sio functions
And will raise SioError exceptions.
These constants are exported:
RSP_NONE, RSP_TERMINATED, RSP_FIXEDLEN, RSP_BEST_EFFORT,
COM1, ..., COM9,
Baud110, Baud300, Baud1200, Baud2400, Baud4800, Baud9600, Baud19200,
Baud38400, Baud57600, Baud115200,
NoParity, OddParity, EvenParity, MarkParity, SpaceParity,
OneStopBit, TwoStopBits
WordLength5, WordLength6, WordLength7, WordLength8
"""
import sys
import regex
import string
from types import IntType, StringType
from mstimer import MsTimer
from crilib import *
from sio import *
[RSP_NONE, RSP_TERMINATED, RSP_FIXEDLEN, RSP_BEST_EFFORT] = range(0, 4)
PORT_CLOSED = -1
class PortDict:
"""A dictionary used to parameterize a Port object.
Usage: import serial
d = serial.PortDict()
d['port'] = serial.COM2
...
fd = serial.Port()
fd.open(d)
Entries (keys are all strings):
debug: Boolean, turn on/off debug/tracing
port: Port param COM1 ... Com9
baud: Port param, Baud110|Baud300|Baud1200|Baud2400|Baud4800
|Baud9600|Baud19200|Baud38400|Baud57600|Baud115200
parity: Port param, NoParity|OddParity|EvenParity|MarkParity
|SpaceParity
stopBits: Port param, OneStopBit|TwoStopBits
dataBits: Port param, WordLength5|WordLength6|WordLength7
|WordLength8
rxBufSize: Maximum size of a rsp
rxBufSize: Maximum size of a cmd
timeoutMs: Milliseconds to wait for expected responses
cmdsEchoed: Boolean, whether hdw echoes characters or not
cmdTerm: String expected to terminate RSP_TERMINATED command
responses
rspTerm: String appended to cmd's
rspType: Used by cmd methods, RSP_NONE|RSP_TERMINATED|RSP_FIXEDLEN
|RSP_BEST_EFFORT
rspFixedLen: Length of expected rsp, if rspType == RSP_FIXEDLEN
rtsSignal RTS signal setting (S set or C clear)
dtrSignal DTR signal setting (S set or C clear)
"""
portKw = {
COM1: 'COM1',
COM2: 'COM2',
COM3: 'COM3',
COM4: 'COM4',
COM5: 'COM5',
COM6: 'COM6',
COM7: 'COM7',
COM8: 'COM8',
COM9: 'COM9'
}
baudKw = {
Baud110: 'Baud110',
Baud300: 'Baud300',
Baud1200: 'Baud1200',
Baud2400: 'Baud2400',
Baud4800: 'Baud4800',
Baud9600: 'Baud9600',
Baud19200: 'Baud19200',
Baud38400: 'Baud38400',
Baud57600: 'Baud57600',
Baud115200: 'Baud115200'
}
parityKw = {
NoParity: 'NoParity',
OddParity: 'OddParity',
EvenParity: 'EvenParity',
MarkParity: 'MarkParity',
SpaceParity: 'SpaceParity'
}
stopBitsKw = {
OneStopBit: 'OneStopBit',
TwoStopBits: 'TwoStopBits'
}
dataBitsKw = {
WordLength5: 'WordLength5',
WordLength6: 'WordLength6',
WordLength7: 'WordLength7',
WordLength8: 'WordLength8'
}
rspTypeKw = {
RSP_NONE: 'RSP_NONE',
RSP_TERMINATED: 'RSP_TERMINATED',
RSP_FIXEDLEN: 'RSP_FIXEDLEN',
RSP_BEST_EFFORT: 'RSP_BEST_EFFORT'
}
paramKws = {
'port': portKw,
'baud': baudKw,
'parity': parityKw,
'stopBits': stopBitsKw,
'dataBits': dataBitsKw,
'rspType': rspTypeKw
}
portVals = tuple(portKw.keys())
baudVals = tuple(baudKw.keys())
parityVals = tuple(parityKw.keys())
stopBitVals = tuple(stopBitsKw.keys())
dataBitVals = tuple(dataBitsKw.keys())
rspTypeVals = tuple(rspTypeKw.keys())
def __init__(self):
"""Create a serial port configuration dictionary that can be modified
before passing to the Port.open method.
"""
self._dict = {}
self._dict['debug'] = FALSE
self._dict['port'] = COM2
self._dict['baud'] = Baud9600
self._dict['parity'] = NoParity
self._dict['stopBits'] = OneStopBit
self._dict['dataBits'] = WordLength8
self._dict['rxBufSize'] = 1024
self._dict['txBufSize'] = 1024
self._dict['timeOutMs'] = 500
self._dict['cmdsEchoed'] = FALSE
self._dict['cmdTerm'] = ''
self._dict['rspTerm'] = ''
self._dict['rspTermPat'] = None
self._dict['rspType'] = RSP_BEST_EFFORT
self._dict['rspFixedLen'] = 0
self._dict['rtsSignal'] = 'S'
self._dict['dtrSignal'] = 'S'
def __getitem__(self, key):
"""Normal dictionary behavior."""
return self._dict[key]
def __setitem__(self, key, value):
"""Only allow existing items to be changed. Validate entries"""
if self._dict.has_key(key):
if key == 'port':
if not value in PortDict.portVals:
raise AttributeError, 'Illegal port value'
elif key == 'baud':
if not value in PortDict.baudVals:
raise AttributeError, 'Illegal baud value'
elif key == 'parity':
if not value in PortDict.parityVals:
raise AttributeError, 'Illegal parity value'
elif key == 'stopBits':
if not value in PortDict.stopBitVals:
raise AttributeError, 'Illegal stopBits value'
elif key == 'dataBits':
if not value in PortDict.dataBitVals:
raise AttributeError, 'Illegal dataBits value'
elif key == 'rspType':
if not value in PortDict.rspTypeVals:
raise AttributeError, 'Illegal rspType value'
elif key == 'rxBufSize' or key == 'txBufSize':
if value <= 0:
raise AttributeError, 'buffer size must be > 0'
elif key == 'timeOutMs':
if value <= 0 or value > 60000:
raise AttributeError, '0 < timeOutMs <= 60000'
elif key == 'cmdTerm' or key == 'rspTerm':
if type(value) != StringType:
raise AttributeError, 'terminators must be strings'
elif key == 'rspTermPat':
raise AttributeError, 'cannot set rspTermPat directly,'\
'store rspTerm instead'
elif key == 'rspFixedLen':
if value <= 0 or value > self._dict['rxBufSize']:
raise AttributeError, \
'0 < rspFixedLen <= %d' % self._dict['rxBufSize']
elif key == 'debug' or key == 'cmdsEchoed':
if type(value) != IntType:
raise AttributeError, 'must be a boolean value'
elif key == 'rtsSignal':
if not value[:1] in 'CS':
raise AttributeError, 'Illegal rtsSignal value'
elif key == 'dtrSignal':
if not value[:1] in 'CS':
raise AttributeError, 'Illegal dtrSignal value'
self._dict[key] = value
if key == 'rspTerm':
self._dict['rspTermPat'] = regex.compile('^.*%s$' % value)
else:
raise KeyError, 'No such key %s in a PortDict' % key
def has_key(self, key):
"""Normal dictionary behavior."""
return self._dict.has_key(key)
def keys(self):
"""Normal dictionary behavior."""
return self._dict.keys()
def __repr__(self):
"""Format a listing of current options."""
str = '<serial Config:'
keys = self._dict.keys()
keys.sort()
for k in keys:
if PortDict.paramKws.has_key(k):
d = PortDict.paramKws[k]
str = str + '\n %s = %s' % (k, d[self._dict[k]])
else:
str = str + '\n %s = %s' % (k, `self._dict[k]`)
str = str + '\n>\n'
return str
class Port:
"""Encapsulate methods for accessing the Win32 serial ports.
Public methods:
open(cfg) -- Open port specified by PortDict instance cfg.
flush() -- Empty receive and transmit buffers.
getLastFlush() -- Return the last string that was flushed.
getLastRsp() -- Return the last response.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -