|
- from pyftdi.pyftdi.ftdi import *
- from pyftdi.pyftdi.usbtools import *
- import time
- import usb.core
- import usb.util
- from .event import event
- import threading
-
- class NoDeviceError(Exception):
- pass
-
- class AD2USB(object):
- on_test = event.Event('testing')
-
- on_open = event.Event('Called when the device has been opened')
- on_close = event.Event('Called when the device has been closed')
- on_read = event.Event('Called when a line has been read from the device')
- on_write = event.Event('Called when data has been written to the device')
-
- __devices = []
-
- @classmethod
- def find_all(cls):
- cls.__devices = Device.find_all()
-
- return cls.__devices
-
- def __init__(self):
- self._device = None
-
- AD2USB.find_all()
-
- def __del__(self):
- pass
-
- def open(self, device=None):
- if len(self.__devices) == 0:
- raise NoDeviceError('No AD2USB devices present.')
-
- if device is None:
- device = self.__devices[0]
-
- self._device = Device(serial=device[2], description=device[4])
-
- self._wire_events()
-
- self._device.open()
-
- def close(self):
- self._device.close()
- self._device = None
-
- def _wire_events(self):
- self._device.on_open += self.on_open
- self._device.on_close += self.on_close
- self._device.on_read += self.on_read
- self._device.on_write += self.on_write
-
-
- class Device(object):
- FTDI_VENDOR_ID = 0x0403
- FTDI_PRODUCT_ID = 0x6001
- BAUDRATE = 115200
-
- on_open = event.Event('Called when the device has been opened')
- on_close = event.Event('Called when the device has been closed')
- on_read = event.Event('Called when a line has been read from the device')
- on_write = event.Event('Called when data has been written to the device')
-
- @staticmethod
- def find_all():
- devices = []
-
- try:
- devices = Ftdi.find_all([(Device.FTDI_VENDOR_ID, Device.FTDI_PRODUCT_ID)], nocache=True)
- except usb.core.USBError, e:
- raise
-
- return devices
-
- def __init__(self, vid=FTDI_VENDOR_ID, pid=FTDI_PRODUCT_ID, serial=None, description=None):
- self._vendor_id = vid
- self._product_id = pid
- self._serial_number = serial
- self._description = description
- self._buffer = ''
- self._device = Ftdi()
- self._running = False
-
- self._read_thread = Device.ReadThread(self)
-
- def open(self, baudrate=BAUDRATE, interface=0, index=0):
- self._running = True
-
- try:
- self._device.open(self._vendor_id,
- self._product_id,
- interface,
- index,
- self._serial_number,
- self._description)
-
- self._device.set_baudrate(baudrate)
- except (usb.core.USBError, FtdiError):
- self.on_close()
- raise
- else:
- self._read_thread.start()
-
- self.on_open((self._serial_number, self._description))
-
- def close(self):
- try:
- self._running = False
- self._read_thread.stop()
-
- self._device.close()
- except (FtdiError, usb.core.USBError):
- pass
-
- self.on_close()
-
- def write(self, data):
- self._device.write_data(data)
-
- self.on_write(data)
-
- def read_line(self, timeout=0.0):
- start_time = time.time()
- got_line = False
- ret = None
-
- try:
- while self._running:
- buf = self._device.read_data(1)
- self._buffer += buf
-
- if buf == "\n":
- if len(self._buffer) > 1:
- if self._buffer[-2] == "\r":
- self._buffer = self._buffer[:-2]
-
- # ignore if we just got \r\n with nothing else in the buffer.
- if len(self._buffer) != 0:
- got_line = True
- break
- else:
- self._buffer = self._buffer[:-1]
-
- if timeout > 0 and time.time() - start_time > timeout:
- break
-
- time.sleep(0.01)
- except FtdiError, e:
- # TODO: I don't think we should be ignoring this
- raise
- else:
- if got_line:
- ret = self._buffer
- self._buffer = ''
-
- self.on_read(ret)
-
- return ret
-
- class ReadThread(threading.Thread):
- def __init__(self, device):
- threading.Thread.__init__(self)
- self._device = device
- self._running = False
-
- def stop(self):
- self._running = False
-
- def run(self):
- self._running = True
-
- while self._running:
- try:
- self._device.read_line()
- except (usb.core.USBError, FtdiError):
- self.stop()
- self._device.close()
-
- time.sleep(0.25)
|