diff --git a/alarmdecoder/util.py b/alarmdecoder/util.py deleted file mode 100644 index afd7ebc..0000000 --- a/alarmdecoder/util.py +++ /dev/null @@ -1,204 +0,0 @@ -""" -Provides utility classes for the `AlarmDecoder`_ (AD2) devices. - -.. _AlarmDecoder: http://www.alarmdecoder.com - -.. moduleauthor:: Scott Petersen -""" - -import time -import threading - - -class NoDeviceError(Exception): - """ - No devices found. - """ - pass - - -class CommError(Exception): - """ - There was an error communicating with the device. - """ - pass - - -class TimeoutError(Exception): - """ - There was a timeout while trying to communicate with the device. - """ - pass - - -class InvalidMessageError(Exception): - """ - The format of the panel message was invalid. - """ - pass - - -class UploadError(Exception): - """ - Generic firmware upload error. - """ - pass - - -class UploadChecksumError(UploadError): - """ - The firmware upload failed due to a checksum error. - """ - pass - - -class Firmware(object): - """ - Represents firmware for the `AlarmDecoder`_ devices. - """ - - # Constants - STAGE_START = 0 - STAGE_WAITING = 1 - STAGE_BOOT = 2 - STAGE_LOAD = 3 - STAGE_UPLOADING = 4 - STAGE_DONE = 5 - STAGE_ERROR = 98 - STAGE_DEBUG = 99 - - # FIXME: Rewrite this monstrosity. - @staticmethod - def upload(dev, filename, progress_callback=None, debug=False): - """ - Uploads firmware to an `AlarmDecoder`_ device. - - :param filename: firmware filename - :type filename: string - :param progress_callback: callback function used to report progress - :type progress_callback: function - - :raises: :py:class:`~alarmdecoder.util.NoDeviceError`, :py:class:`~alarmdecoder.util.TimeoutError` - """ - - def do_upload(): - """ - Perform the actual firmware upload to the device. - """ - with open(filename) as upload_file: - line_cnt = 0 - for line in upload_file: - line_cnt += 1 - line = line.rstrip() - - if line[0] == ':': - dev.write(line + "\r") - response = dev.read_line(timeout=5.0, purge_buffer=True) - if debug: - stage_callback(Firmware.STAGE_DEBUG, data="line={0} - line={1} response={2}".format(line_cnt, line, response)); - - if '!ce' in response: - raise UploadChecksumError("Checksum error on line " + str(line_cnt) + " of " + filename); - - elif '!no' in response: - raise UploadError("Incorrect data sent to bootloader.") - - elif '!ok' in response: - break - - else: - if progress_callback is not None: - progress_callback(Firmware.STAGE_UPLOADING) - - time.sleep(0.0) - - def read_until(pattern, timeout=0.0): - """ - Read characters until a specific pattern is found or the timeout is - hit. - """ - def timeout_event(): - """Handles the read timeout event.""" - timeout_event.reading = False - - timeout_event.reading = True - - timer = None - if timeout > 0: - timer = threading.Timer(timeout, timeout_event) - timer.start() - - position = 0 - - dev.purge() - - while timeout_event.reading: - try: - char = dev.read() - - if char is not None and char != '': - if char == pattern[position]: - position = position + 1 - if position == len(pattern): - break - else: - position = 0 - - except Exception, err: - pass - - if timer: - if timer.is_alive(): - timer.cancel() - else: - raise TimeoutError('Timeout while waiting for line terminator.') - - def stage_callback(stage, **kwargs): - """Callback to update progress for the specified stage.""" - if progress_callback is not None: - progress_callback(stage, **kwargs) - - if dev is None: - raise NoDeviceError('No device specified for firmware upload.') - - stage_callback(Firmware.STAGE_START) - - if dev.is_reader_alive(): - # Close the reader thread and wait for it to die, otherwise - # it interferes with our reading. - dev.stop_reader() - while dev._read_thread.is_alive(): - stage_callback(Firmware.STAGE_WAITING) - time.sleep(0.5) - - # Reboot the device and wait for the boot loader. - retry = 3 - found_loader = False - while retry > 0: - try: - stage_callback(Firmware.STAGE_BOOT) - dev.write("=") - read_until('!boot', timeout=15.0) - - # Get ourselves into the boot loader and wait for indication - # that it's ready for the firmware upload. - stage_callback(Firmware.STAGE_LOAD) - dev.write("=") - read_until('!load', timeout=15.0) - - except TimeoutError, err: - retry -= 1 - else: - retry = 0 - found_loader = True - - # And finally do the upload. - if found_loader: - try: - do_upload() - except UploadError, err: - stage_callback(Firmware.STAGE_ERROR, error=str(err)) - else: - stage_callback(Firmware.STAGE_DONE) - else: - stage_callback(Firmware.STAGE_ERROR, error="Error entering bootloader.")