| 1 |
|
|---|
| 2 |
|
|---|
| 3 |
|
|---|
| 4 |
|
|---|
| 5 |
""" |
|---|
| 6 |
Serial port support for Windows. |
|---|
| 7 |
|
|---|
| 8 |
Requires PySerial and win32all, and needs to be used with win32event |
|---|
| 9 |
reactor. |
|---|
| 10 |
""" |
|---|
| 11 |
|
|---|
| 12 |
|
|---|
| 13 |
import os |
|---|
| 14 |
import serial |
|---|
| 15 |
from serial import PARITY_NONE, PARITY_EVEN, PARITY_ODD |
|---|
| 16 |
from serial import STOPBITS_ONE, STOPBITS_TWO |
|---|
| 17 |
from serial import FIVEBITS, SIXBITS, SEVENBITS, EIGHTBITS |
|---|
| 18 |
import win32file, win32event |
|---|
| 19 |
|
|---|
| 20 |
|
|---|
| 21 |
from twisted.protocols import basic |
|---|
| 22 |
from twisted.internet import abstract |
|---|
| 23 |
from twisted.python import log |
|---|
| 24 |
|
|---|
| 25 |
|
|---|
| 26 |
from serialport import BaseSerialPort |
|---|
| 27 |
|
|---|
| 28 |
|
|---|
| 29 |
class SerialPort(BaseSerialPort, abstract.FileDescriptor): |
|---|
| 30 |
"""A select()able serial device, acting as a transport.""" |
|---|
| 31 |
|
|---|
| 32 |
connected = 1 |
|---|
| 33 |
|
|---|
| 34 |
def __init__(self, protocol, deviceNameOrPortNumber, reactor, |
|---|
| 35 |
baudrate = 9600, bytesize = EIGHTBITS, parity = PARITY_NONE, |
|---|
| 36 |
stopbits = STOPBITS_ONE, xonxoff = 0, rtscts = 0): |
|---|
| 37 |
self._serial = serial.Serial(deviceNameOrPortNumber, baudrate=baudrate, |
|---|
| 38 |
bytesize=bytesize, parity=parity, |
|---|
| 39 |
stopbits=stopbits, timeout=None, |
|---|
| 40 |
xonxoff=xonxoff, rtscts=rtscts) |
|---|
| 41 |
self.flushInput() |
|---|
| 42 |
self.flushOutput() |
|---|
| 43 |
self.reactor = reactor |
|---|
| 44 |
self.protocol = protocol |
|---|
| 45 |
self.outQueue = [] |
|---|
| 46 |
self.closed = 0 |
|---|
| 47 |
self.closedNotifies = 0 |
|---|
| 48 |
self.writeInProgress = 0 |
|---|
| 49 |
|
|---|
| 50 |
self.protocol = protocol |
|---|
| 51 |
self._overlappedRead = win32file.OVERLAPPED() |
|---|
| 52 |
self._overlappedRead.hEvent = win32event.CreateEvent(None, 1, 0, None) |
|---|
| 53 |
self._overlappedWrite = win32file.OVERLAPPED() |
|---|
| 54 |
self._overlappedWrite.hEvent = win32event.CreateEvent(None, 0, 0, None) |
|---|
| 55 |
|
|---|
| 56 |
self.reactor.addEvent(self._overlappedRead.hEvent, self, 'serialReadEvent') |
|---|
| 57 |
self.reactor.addEvent(self._overlappedWrite.hEvent, self, 'serialWriteEvent') |
|---|
| 58 |
|
|---|
| 59 |
self.protocol.makeConnection(self) |
|---|
| 60 |
|
|---|
| 61 |
flags, comstat = win32file.ClearCommError(self._serial.hComPort) |
|---|
| 62 |
rc, self.read_buf = win32file.ReadFile(self._serial.hComPort, |
|---|
| 63 |
win32file.AllocateReadBuffer(1), |
|---|
| 64 |
self._overlappedRead) |
|---|
| 65 |
|
|---|
| 66 |
def serialReadEvent(self): |
|---|
| 67 |
|
|---|
| 68 |
n = win32file.GetOverlappedResult(self._serial.hComPort, self._overlappedRead, 0) |
|---|
| 69 |
if n: |
|---|
| 70 |
first = str(self.read_buf[:n]) |
|---|
| 71 |
|
|---|
| 72 |
flags, comstat = win32file.ClearCommError(self._serial.hComPort) |
|---|
| 73 |
if comstat.cbInQue: |
|---|
| 74 |
win32event.ResetEvent(self._overlappedRead.hEvent) |
|---|
| 75 |
rc, buf = win32file.ReadFile(self._serial.hComPort, |
|---|
| 76 |
win32file.AllocateReadBuffer(comstat.cbInQue), |
|---|
| 77 |
self._overlappedRead) |
|---|
| 78 |
n = win32file.GetOverlappedResult(self._serial.hComPort, self._overlappedRead, 1) |
|---|
| 79 |
|
|---|
| 80 |
self.protocol.dataReceived(first + str(buf[:n])) |
|---|
| 81 |
else: |
|---|
| 82 |
|
|---|
| 83 |
self.protocol.dataReceived(first) |
|---|
| 84 |
|
|---|
| 85 |
|
|---|
| 86 |
win32event.ResetEvent(self._overlappedRead.hEvent) |
|---|
| 87 |
rc, self.read_buf = win32file.ReadFile(self._serial.hComPort, |
|---|
| 88 |
win32file.AllocateReadBuffer(1), |
|---|
| 89 |
self._overlappedRead) |
|---|
| 90 |
|
|---|
| 91 |
def write(self, data): |
|---|
| 92 |
if data: |
|---|
| 93 |
if self.writeInProgress: |
|---|
| 94 |
self.outQueue.append(data) |
|---|
| 95 |
else: |
|---|
| 96 |
self.writeInProgress = 1 |
|---|
| 97 |
win32file.WriteFile(self._serial.hComPort, data, self._overlappedWrite) |
|---|
| 98 |
|
|---|
| 99 |
def serialWriteEvent(self): |
|---|
| 100 |
try: |
|---|
| 101 |
dataToWrite = self.outQueue.pop(0) |
|---|
| 102 |
except IndexError: |
|---|
| 103 |
self.writeInProgress = 0 |
|---|
| 104 |
return |
|---|
| 105 |
else: |
|---|
| 106 |
win32file.WriteFile(self._serial.hComPort, dataToWrite, self._overlappedWrite) |
|---|
| 107 |
|
|---|
| 108 |
def connectionLost(self, reason): |
|---|
| 109 |
self.reactor.removeEvent(self._overlappedRead.hEvent) |
|---|
| 110 |
self.reactor.removeEvent(self._overlappedWrite.hEvent) |
|---|
| 111 |
abstract.FileDescriptor.connectionLost(self, reason) |
|---|
| 112 |
self._serial.close() |
|---|