| @@ -13,6 +13,7 @@ class Overseer(object): | |||||
| Factory for creation of AD2USB devices as well as provide4s attach/detach events." | Factory for creation of AD2USB devices as well as provide4s attach/detach events." | ||||
| """ | """ | ||||
| # Factory events | |||||
| on_attached = event.Event('Called when an AD2USB device has been detected.') | on_attached = event.Event('Called when an AD2USB device has been detected.') | ||||
| on_detached = event.Event('Called when an AD2USB device has been removed.') | on_detached = event.Event('Called when an AD2USB device has been removed.') | ||||
| @@ -152,13 +153,15 @@ class AD2USB(object): | |||||
| High-level wrapper around AD2USB/AD2SERIAL devices. | High-level wrapper around AD2USB/AD2SERIAL devices. | ||||
| """ | """ | ||||
| # High-level Events | |||||
| on_open = event.Event('Called when the device has been opened') | on_open = event.Event('Called when the device has been opened') | ||||
| on_close = event.Event('Called when the device has been closed') | on_close = event.Event('Called when the device has been closed') | ||||
| on_message = event.Event('Called when a message has been received from the device.') | |||||
| # Low-level Events | |||||
| on_read = event.Event('Called when a line has been read from the device') | 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') | on_write = event.Event('Called when data has been written to the device') | ||||
| on_message = event.Event('Called when a message has been received from the device.') | |||||
| def __init__(self, device): | def __init__(self, device): | ||||
| """ | """ | ||||
| Constructor | Constructor | ||||
| @@ -198,7 +201,7 @@ class AD2USB(object): | |||||
| """ | """ | ||||
| Parses messages from the panel. | Parses messages from the panel. | ||||
| """ | """ | ||||
| if data[0] == '!': | |||||
| if data[0] == '!': # TEMP: Remove this. | |||||
| return None | return None | ||||
| msg = Message() | msg = Message() | ||||
| @@ -19,6 +19,7 @@ class Device(object): | |||||
| Generic parent device to all AD2USB products. | Generic parent device to all AD2USB products. | ||||
| """ | """ | ||||
| # Generic device events | |||||
| on_open = event.Event('Called when the device has been opened') | on_open = event.Event('Called when the device has been opened') | ||||
| on_close = event.Event('Called when the device has been closed') | 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_read = event.Event('Called when a line has been read from the device') | ||||
| @@ -59,7 +60,7 @@ class Device(object): | |||||
| try: | try: | ||||
| self._device.read_line(timeout=10) | self._device.read_line(timeout=10) | ||||
| except util.CommError, err: | except util.CommError, err: | ||||
| traceback.print_exc(err) | |||||
| traceback.print_exc(err) # TEMP | |||||
| except util.TimeoutError, err: | except util.TimeoutError, err: | ||||
| pass | pass | ||||
| @@ -70,6 +71,7 @@ class USBDevice(Device): | |||||
| AD2USB device exposed with PyFTDI's interface. | AD2USB device exposed with PyFTDI's interface. | ||||
| """ | """ | ||||
| # Constants | |||||
| FTDI_VENDOR_ID = 0x0403 | FTDI_VENDOR_ID = 0x0403 | ||||
| FTDI_PRODUCT_ID = 0x6001 | FTDI_PRODUCT_ID = 0x6001 | ||||
| BAUDRATE = 115200 | BAUDRATE = 115200 | ||||
| @@ -113,6 +115,7 @@ class USBDevice(Device): | |||||
| """ | """ | ||||
| self._running = True | self._running = True | ||||
| # Set up defaults | |||||
| if baudrate is None: | if baudrate is None: | ||||
| baudrate = USBDevice.BAUDRATE | baudrate = USBDevice.BAUDRATE | ||||
| @@ -125,6 +128,7 @@ class USBDevice(Device): | |||||
| if index is None: | if index is None: | ||||
| index = 0 | index = 0 | ||||
| # Open the device and start up the thread. | |||||
| try: | try: | ||||
| self._device.open(self._vendor_id, | self._device.open(self._vendor_id, | ||||
| self._product_id, | self._product_id, | ||||
| @@ -226,6 +230,8 @@ class SerialDevice(Device): | |||||
| """ | """ | ||||
| AD2USB or AD2SERIAL device exposed with the pyserial interface. | AD2USB or AD2SERIAL device exposed with the pyserial interface. | ||||
| """ | """ | ||||
| # Constants | |||||
| BAUDRATE = 19200 | BAUDRATE = 19200 | ||||
| @staticmethod | @staticmethod | ||||
| @@ -264,6 +270,8 @@ class SerialDevice(Device): | |||||
| """ | """ | ||||
| Opens the device. | Opens the device. | ||||
| """ | """ | ||||
| # Set up the defaults | |||||
| if baudrate is None: | if baudrate is None: | ||||
| baudrate = SerialDevice.BAUDRATE | baudrate = SerialDevice.BAUDRATE | ||||
| @@ -276,6 +284,7 @@ class SerialDevice(Device): | |||||
| self._device.baudrate = baudrate | self._device.baudrate = baudrate | ||||
| self._device.port = self._interface | self._device.port = self._interface | ||||
| # Open the device and start up the reader thread. | |||||
| try: | try: | ||||
| self._device.open() | self._device.open() | ||||
| @@ -338,7 +347,7 @@ class SerialDevice(Device): | |||||
| while self._running: | while self._running: | ||||
| buf = self._device.read(1) | buf = self._device.read(1) | ||||
| if buf != '' and buf != "\xff": # WTF is this \xff and why is it in my buffer?! | |||||
| if buf != '' and buf != "\xff": # AD2SERIAL specifically apparently sends down \xFF on boot. | |||||
| self._buffer += buf | self._buffer += buf | ||||
| if buf == "\n": | if buf == "\n": | ||||
| @@ -29,6 +29,7 @@ class Firmware(object): | |||||
| Represents firmware for the AD2USB/AD2SERIAL devices. | Represents firmware for the AD2USB/AD2SERIAL devices. | ||||
| """ | """ | ||||
| # Constants | |||||
| STAGE_START = 0 | STAGE_START = 0 | ||||
| STAGE_WAITING = 1 | STAGE_WAITING = 1 | ||||
| STAGE_BOOT = 2 | STAGE_BOOT = 2 | ||||
| @@ -53,7 +54,12 @@ class Firmware(object): | |||||
| """ | """ | ||||
| Uploads firmware to an AD2USB/AD2SERIAL device. | Uploads firmware to an AD2USB/AD2SERIAL device. | ||||
| """ | """ | ||||
| def do_upload(): | def do_upload(): | ||||
| """ | |||||
| Perform the actual firmware upload to the device. | |||||
| """ | |||||
| with open(filename) as f: | with open(filename) as f: | ||||
| for line in f: | for line in f: | ||||
| line = line.rstrip() | line = line.rstrip() | ||||
| @@ -68,6 +74,9 @@ class Firmware(object): | |||||
| time.sleep(0.05) | time.sleep(0.05) | ||||
| def read_until(pattern, timeout=0.0): | def read_until(pattern, timeout=0.0): | ||||
| """ | |||||
| Read characters until a specific pattern is found or the timeout is hit. | |||||
| """ | |||||
| start_time = time.time() | start_time = time.time() | ||||
| buf = '' | buf = '' | ||||
| position = 0 | position = 0 | ||||
| @@ -96,6 +105,8 @@ class Firmware(object): | |||||
| if progress_callback is not None: | if progress_callback is not None: | ||||
| progress_callback(Firmware.STAGE_START) | progress_callback(Firmware.STAGE_START) | ||||
| # Close the reader thread and wait for it to die, otherwise | |||||
| # it interferes with our reading. | |||||
| dev.close_reader() | dev.close_reader() | ||||
| while dev._read_thread.is_alive(): | while dev._read_thread.is_alive(): | ||||
| if progress_callback is not None: | if progress_callback is not None: | ||||
| @@ -107,19 +118,23 @@ class Firmware(object): | |||||
| if progress_callback is not None: | if progress_callback is not None: | ||||
| progress_callback(Firmware.STAGE_BOOT) | progress_callback(Firmware.STAGE_BOOT) | ||||
| # Reboot the device and wait for the boot loader. | |||||
| dev.write("=") | dev.write("=") | ||||
| read_until('!boot', timeout=10.0) | read_until('!boot', timeout=10.0) | ||||
| if progress_callback is not None: | if progress_callback is not None: | ||||
| progress_callback(Firmware.STAGE_LOAD) | progress_callback(Firmware.STAGE_LOAD) | ||||
| # Get ourselves into the boot loader and wait for indication | |||||
| # that it's ready for the firmware upload. | |||||
| dev.write("=") | dev.write("=") | ||||
| read_until('!load', timeout=10.0) | read_until('!load', timeout=10.0) | ||||
| # And finally do the upload. | |||||
| do_upload() | do_upload() | ||||
| if progress_callback is not None: | if progress_callback is not None: | ||||
| progress_callback(Firmware.STAGE_DONE) | progress_callback(Firmware.STAGE_DONE) | ||||
| except TimeoutError, err: | except TimeoutError, err: | ||||
| print traceback.print_exc(err) | |||||
| print traceback.print_exc(err) # TEMP | |||||
| pass | pass | ||||