Ejemplo n.º 1
0
 def sample_worker(self):
     rc_api = self._rc_api
     sample_event = self._sample_event
     
     Logger.info('DataBusPump: DataBus Sampler Starting')
     sample_event.clear()
     if sample_event.wait(SAMPLE_POLL_TEST_TIMEOUT) == True:
         Logger.info('DataBusPump: Async sampling detected')
     else:
         Logger.info('DataBusPump: Synchronous sampling mode enabled')
         while self._running.is_set():
             try:
                 #the timeout here is designed to be longer than the streaming rate of 
                 #RaceCapture. If we don't get an asynchronous sample, then we will timeout
                 #and request a sample anyway.
                 rc_api.sample()
                 sample_event.wait(SAMPLE_POLL_EVENT_TIMEOUT)
                 sample_event.clear()
                 sleep(SAMPLE_POLL_INTERVAL_TIMEOUT)
             except Exception as e:
                 sleep(SAMPLE_POLL_EXCEPTION_RECOVERY)
                 Logger.error('DataBusPump: Exception in sample_worker: ' + str(e))
             finally:
                 sample_event.clear()
             
     Logger.info('DataBusPump: DataBus Sampler Exiting')
     safe_thread_exit()
Ejemplo n.º 2
0
    def _connection_thread_message_reader(self, rx_queue, connection, should_run):
        """This method is designed to be run in a thread, it will loop infinitely as long as should_run.is_set()
        returns True. In its loop it will attempt to read data from the socket connection

        :param rx_queue Queue for pushing data read from the socket onto
        :param connection Socket connection to read data from
        :param should_run Event to check on each loop to determine if to continue reading
        :type rx_queue threading.Queue
        :type connection SocketConnection
        :type should_run threading.Event
        :return: None
        """
        Logger.debug('SocketComm: connection thread message reader started')

        while should_run.is_set():
            try:
                msg = connection.read_line(should_run)
                if msg:
                    rx_queue.put(msg)
            except:
                Logger.error('SocketComm: Exception in connection_process_message_reader')
                Logger.debug(traceback.format_exc())
                should_run.clear()
                sleep(0.5)
        Logger.debug('SocketComm: connection process message reader exited')
        safe_thread_exit()
Ejemplo n.º 3
0
    def _session_recorder_worker(self):
        Logger.info('SessionRecorder: session recorder worker starting')
        try:
            # reset our sample data dict
            sample_data = {}
            index = 0
            qsize = 0
            sample_queue = self._sample_queue
            # will drain the queue before exiting thread
            while self.recording or qsize > 0:
                try:
                    sample = sample_queue.get(
                        True, SessionRecorder.SAMPLE_QUEUE_GET_TIMEOUT)
                    # Merging previous sample with new data to desparsify the
                    # data
                    sample_data.update(sample)
                    self._datastore.insert_sample(sample_data,
                                                  self._current_session_id)
                    qsize = sample_queue.qsize()
                    if index % SessionRecorder.SAMPLE_QUEUE_BACKLOG_LOG_INTERVAL == 0 and qsize > 0:
                        Logger.info(
                            'SessionRecorder: queue backlog: {}'.format(qsize))
                    index += 1
                except Empty:
                    pass
        except Exception as e:
            Logger.error(
                'SessionRecorder: Exception in session recorder worker ' +
                str(e))
        finally:
            safe_thread_exit()

        Logger.info('SessionRecorder: session recorder worker ending')
Ejemplo n.º 4
0
    def _connection_message_thread(self, connection, address, rx_queue, tx_queue, command_queue):
        """
        'Manager' method that is run in a thread that starts up the read and write threads for the socket
         connection. Watches the command_queue to know when to stop

        :param connection: Socket connection
        :param address: IP address to connect to
        :param rx_queue: Receive queue
        :param tx_queue: Transmit queue
        :param command_queue: Command queue
        :return: None
        """
        Logger.info('SocketComm: connection process starting')

        try:
            connection.open(address)
            connection.flushInput()
            connection.flushOutput()

            reader_writer_should_run = threading.Event()
            reader_writer_should_run.set()

            reader_thread = threading.Thread(target=self._connection_thread_message_reader, args=(rx_queue, connection,
                                                                                            reader_writer_should_run))
            reader_thread.start()

            writer_thread = threading.Thread(target=self._connection_thread_message_writer, args=(tx_queue, connection,
                                                                                            reader_writer_should_run))
            writer_thread.start()

            while reader_writer_should_run.is_set():
                try:
                    command = command_queue.get(True, self.KEEP_ALIVE_TIMEOUT_S)
                    if command == self.COMMAND_CLOSE:
                        Logger.debug('SocketComm: connection thread: got close command')
                        reader_writer_should_run.clear()
                except Empty:
                    Logger.debug('SocketComm: keep alive timeout')
                    reader_writer_should_run.clear()
            Logger.debug('SocketComm: connection worker exiting')

            reader_thread.join()
            writer_thread.join()

            try:
                connection.close()
            except:
                Logger.error('SocketComm: Exception closing connection worker connection')
                Logger.error(traceback.format_exc())
        except socket.timeout as e:
            Logger.error("SocketComm: got timeout connecting to {}".format(address))
        except socket.error as e:
            Logger.error("SocketComm: got exception connecting to {}".format(address))
            Logger.error('SocketComm: socket error setting up connection thread: ' + str(type(e)) + str(e))
        except Exception as e:
            Logger.error('SocketComm: Exception setting up connection thread: ' + str(type(e)) + str(e))
            Logger.debug(traceback.format_exc())

        Logger.debug('SocketComm: connection worker exited')
        safe_thread_exit()
Ejemplo n.º 5
0
    def _connection_thread_message_reader(self, rx_queue, connection,
                                          should_run):
        """This method is designed to be run in a thread, it will loop infinitely as long as should_run.is_set()
        returns True. In its loop it will attempt to read data from the socket connection

        :param rx_queue Queue for pushing data read from the socket onto
        :param connection Socket connection to read data from
        :param should_run Event to check on each loop to determine if to continue reading
        :type rx_queue threading.Queue
        :type connection SocketConnection
        :type should_run threading.Event
        :return: None
        """
        Logger.debug('SocketComm: connection thread message reader started')

        while should_run.is_set():
            try:
                msg = connection.read_line(should_run)
                if msg:
                    rx_queue.put(msg)
            except:
                Logger.error(
                    'SocketComm: Exception in connection_process_message_reader'
                )
                Logger.debug(traceback.format_exc())
                should_run.clear()
                sleep(0.5)
        Logger.debug('SocketComm: connection process message reader exited')
        safe_thread_exit()
Ejemplo n.º 6
0
    def _connection_thread_message_writer(self, tx_queue, connection,
                                          should_run):
        """This method is designed to be run in a thread, it will loop infinitely as long as should_run.is_set()
        returns True. In its loop it will attempt to write pending data from the socket connection

        :param tx_queue Queue for pulling data to be written to the socket
        :param connection Socket connection to write data to
        :param should_run Event to check on each loop to determine if to continue writing
        :type tx_queue threading.Queue
        :type connection SocketConnection
        :type should_run threading.Event
        :return: None
        """
        Logger.info('SocketComm: connection thread message writer started')
        while should_run.is_set():
            try:
                message = tx_queue.get(True, 1.0)
                if message:
                    Logger.debug(
                        "SocketComm: writing message {}".format(message))
                    connection.write(message)
            except Empty:
                pass
            except Exception as e:
                Logger.error(
                    'SocketComm: Exception in connection_thread_message_writer '
                    + str(e))
                Logger.debug(traceback.format_exc())
                should_run.clear()
                sleep(0.5)
        Logger.debug('SocketComm: connection thread message writer exited')
        safe_thread_exit()
Ejemplo n.º 7
0
    def msg_rx_worker(self):
        Logger.info('RCPAPI: msg_rx_worker starting')
        comms = self.comms
        error_count = 0
        while self._running.is_set():
            msg = None
            try:
                msg = comms.read_message()
                if msg:
                    # clean incoming string, and drop illegal characters
                    msg = unicode(msg, errors='ignore')
                    msgJson = json.loads(msg, strict=False)

                    if 's' in msgJson:
                        Logger.trace('RCPAPI: Rx: ' + str(msg))
                    else:
                        Logger.debug('RCPAPI: Rx: ' + str(msg))
                    Clock.schedule_once(lambda dt: self.on_rx(True))
                    error_count = 0
                    for messageName in msgJson.keys():
                        Logger.trace('RCPAPI: processing message ' +
                                     messageName)
                        listeners = self.msgListeners.get(messageName, None)
                        if listeners:
                            for listener in listeners:
                                try:
                                    listener(msgJson)
                                except Exception as e:
                                    Logger.error(
                                        'RCPAPI: Message Listener Exception for'
                                    )
                                    Logger.debug(traceback.format_exc())
                            break
                    msg = ''
                else:
                    sleep(NO_DATA_AVAILABLE_DELAY)

            except PortNotOpenException:
                Logger.debug("RCPAPI: Port not open...")
                msg = ''
                sleep(1.0)
            except Exception as e:
                Logger.warn(
                    'RCPAPI: Message rx worker exception: {} | {}'.format(
                        repr(msg), str(e)))
                Logger.debug(traceback.format_exc())
                msg = ''
                error_count += 1
                if error_count > 5 and not self._auto_detect_event.is_set():
                    Logger.warn(
                        "RCPAPI: Too many Rx exceptions; re-opening connection"
                    )
                    self.recover_connection()
                    self.connected_version = None
                    sleep(5)
                else:
                    sleep(0.25)

        safe_thread_exit()
        Logger.info("RCPAPI: msg_rx_worker exiting")
Ejemplo n.º 8
0
    def _connection_thread_message_writer(self, tx_queue, connection, should_run):
        """This method is designed to be run in a thread, it will loop infinitely as long as should_run.is_set()
        returns True. In its loop it will attempt to write pending data from the socket connection

        :param tx_queue Queue for pulling data to be written to the socket
        :param connection Socket connection to write data to
        :param should_run Event to check on each loop to determine if to continue writing
        :type tx_queue threading.Queue
        :type connection SocketConnection
        :type should_run threading.Event
        :return: None
        """
        Logger.info('SocketComm: connection thread message writer started')
        while should_run.is_set():
            try:
                message = tx_queue.get(True, 1.0)
                if message:
                    Logger.debug("SocketComm: writing message {}".format(message))
                    connection.write(message)
            except Empty:
                pass
            except Exception as e:
                Logger.error('SocketComm: Exception in connection_thread_message_writer ' + str(e))
                Logger.debug(traceback.format_exc())
                should_run.clear()
                sleep(0.5)
        Logger.debug('SocketComm: connection thread message writer exited')
        safe_thread_exit()
Ejemplo n.º 9
0
    def _connection_message_thread(self, connection, address, rx_queue, tx_queue, command_queue):
        """
        'Manager' method that is run in a thread that starts up the read and write threads for the socket
         connection. Watches the command_queue to know when to stop

        :param connection: Socket connection
        :param address: IP address to connect to
        :param rx_queue: Receive queue
        :param tx_queue: Transmit queue
        :param command_queue: Command queue
        :return: None
        """
        Logger.info('SocketComm: connection process starting')

        try:
            connection.open(address)
            connection.flushInput()
            connection.flushOutput()

            reader_writer_should_run = threading.Event()
            reader_writer_should_run.set()

            reader_thread = threading.Thread(target=self._connection_thread_message_reader, args=(rx_queue, connection,
                                                                                            reader_writer_should_run))
            reader_thread.start()

            writer_thread = threading.Thread(target=self._connection_thread_message_writer, args=(tx_queue, connection,
                                                                                            reader_writer_should_run))
            writer_thread.start()

            while reader_writer_should_run.is_set():
                try:
                    command = command_queue.get(True, self.KEEP_ALIVE_TIMEOUT_S)
                    if command == self.COMMAND_CLOSE:
                        Logger.debug('SocketComm: connection thread: got close command')
                        reader_writer_should_run.clear()
                except Empty:
                    Logger.debug('SocketComm: keep alive timeout')
            Logger.debug('SocketComm: connection worker exiting')

            reader_thread.join()
            writer_thread.join()

            try:
                connection.close()
            except:
                Logger.error('SocketComm: Exception closing connection worker connection')
                Logger.error(traceback.format_exc())
        except socket.timeout as e:
            Logger.error("SocketComm: got timeout connecting to {}".format(address))
        except socket.error as e:
            Logger.error("SocketComm: got exception connecting to {}".format(address))
            Logger.error('SocketComm: socket error setting up connection thread: ' + str(type(e)) + str(e))
        except Exception as e:
            Logger.error('SocketComm: Exception setting up connection thread: ' + str(type(e)) + str(e))
            Logger.debug(traceback.format_exc())

        Logger.debug('SocketComm: connection worker exited')
        safe_thread_exit()
Ejemplo n.º 10
0
 def status_worker(self):
     Logger.info('StatusPump: status_worker starting')
     self._rc_api.addListener('status', self._on_status_updated)
     while self._running.is_set():
         self._rc_api.get_status()
         sleep(self.STATUS_QUERY_INTERVAL)
     Logger.info('StatusPump: status_worker exited')
     safe_thread_exit()
Ejemplo n.º 11
0
 def status_worker(self):
     Logger.info('StatusPump: status_worker starting')
     self._rc_api.addListener('status', self._on_status_updated)
     while self._running.is_set():
         self._rc_api.get_status()
         sleep(self.STATUS_QUERY_INTERVAL)
     Logger.info('StatusPump: status_worker exited')
     safe_thread_exit()
Ejemplo n.º 12
0
    def _session_recorder_worker(self):
        Logger.info('SessionRecorder: session recorder worker starting')
        try:
            # reset our sample data dict
            qsize = 0
            insert_counter = 0
            sample_queue = self._sample_queue
            index = 0
            # will drain the queue before exiting thread
            while self.recording or qsize > 0:
                try:
                    sample_data = sample_queue.get(
                        True, SessionRecorder.SAMPLE_QUEUE_GET_TIMEOUT)
                    self._datastore.insert_sample_nocommit(
                        sample_data, self._current_session_id)
                    insert_counter += 1
                    qsize = sample_queue.qsize()
                    # since the commit is slow, only do the commit once the queue empty to prevent overrunning the buffer.
                    if (qsize == 0) or (insert_counter >= SessionRecorder.
                                        SAMPLE_QUEUE_UNCOMMITTED_INSERT_LIMIT):
                        self._datastore.commit()
                        insert_counter = 0

                    if qsize > 0 and index % SessionRecorder.SAMPLE_QUEUE_BACKLOG_LOG_INTERVAL == 0:
                        Logger.info(
                            'SessionRecorder: queue backlog: {}, commit backlog: {}, sample send delay: {}ms'
                            .format(qsize, insert_counter,
                                    self._sample_send_delay))

                    if insert_counter > (
                            SessionRecorder.
                            SAMPLE_QUEUE_UNCOMMITTED_INSERT_LIMIT *
                            SessionRecorder.SAMPLE_QUEUE_BACKLOG_LOG_THRESHOLD
                    ):
                        Logger.debug(
                            'SessionRecorder: commit backlog: {}'.format(
                                insert_counter))

                    if qsize > (
                            SessionRecorder.SAMPLE_QUEUE_MAX_SIZE *
                            SessionRecorder.SAMPLE_QUEUE_BACKLOG_LOG_THRESHOLD
                    ):
                        Logger.debug(
                            'SessionRecorder: queue backlog: {}'.format(qsize))

                    index += 1
                except Empty:
                    pass
        except Exception as e:
            Logger.error(
                'SessionRecorder: Exception in session recorder worker ' +
                str(e))
        finally:
            safe_thread_exit()

        Logger.info('SessionRecorder: session recorder worker ending')
Ejemplo n.º 13
0
    def status_worker(self):
        Logger.info('StatusPump: status_worker starting')
        self._rc_api.addListener('status', self._on_status_updated)
        while self._running.is_set():
            self._rc_api.get_status()
            sleep(StatusPump.STATUS_QUERY_INTERVAL_SEC)
            if not self._ready.wait(StatusPump.READY_WAIT_TIMEOUT_SEC):
                Logger.warn('StatusPump: timed out waiting for status response')

        Logger.info('StatusPump: status_worker exited')
        safe_thread_exit()
Ejemplo n.º 14
0
    def status_worker(self):
        Logger.info('StatusPump: status_worker starting')
        self._rc_api.addListener('status', self._on_status_updated)
        while self._running.is_set():
            self._rc_api.get_status()
            sleep(StatusPump.STATUS_QUERY_INTERVAL_SEC)
            if not self._ready.wait(StatusPump.READY_WAIT_TIMEOUT_SEC):
                Logger.warn('StatusPump: timed out waiting for status response')

        Logger.info('StatusPump: status_worker exited')
        safe_thread_exit()
Ejemplo n.º 15
0
    def msg_rx_worker(self):
        Logger.info('RCPAPI: msg_rx_worker starting')
        comms = self.comms
        error_count = 0
        while self._running.is_set():
            msg = None
            try:
                msg = comms.read_message()
                if msg:
                    # clean incoming string, and drop illegal characters
                    msg = unicode(msg, errors='ignore')
                    msgJson = json.loads(msg, strict=False)

                    if 's' in msgJson:
                         Logger.trace('RCPAPI: Rx: ' + str(msg))
                    else:
                         Logger.debug('RCPAPI: Rx: ' + str(msg))
                    Clock.schedule_once(lambda dt: self.on_rx(True))
                    error_count = 0
                    for messageName in msgJson.keys():
                        Logger.trace('RCPAPI: processing message ' + messageName)
                        listeners = self.msgListeners.get(messageName, None)
                        if listeners:
                            for listener in listeners:
                                try:
                                    listener(msgJson)
                                except Exception as e:
                                    Logger.error('RCPAPI: Message Listener Exception for')
                                    Logger.debug(traceback.format_exc())
                            break
                    msg = ''
                else:
                    sleep(NO_DATA_AVAILABLE_DELAY)

            except PortNotOpenException:
                Logger.debug("RCPAPI: Port not open...")
                msg = ''
                sleep(1.0)
            except Exception as e:
                Logger.warn('RCPAPI: Message rx worker exception: {} | {}'.format(repr(msg), str(e)))
                Logger.debug(traceback.format_exc())
                msg = ''
                error_count += 1
                if error_count > 5 and not self._auto_detect_event.is_set():
                    Logger.warn("RCPAPI: Too many Rx exceptions; re-opening connection")
                    self.recover_connection()
                    self.connected_version = None
                    sleep(5)
                else:
                    sleep(0.25)

        safe_thread_exit()
        Logger.info("RCPAPI: msg_rx_worker exiting")
Ejemplo n.º 16
0
    def sample_worker(self):
        rc_api = self._rc_api
        Logger.info('DataBusPump: sample_worker starting')
        while self._running.is_set():
            try:
                rc_api.sample()
                sleep(SAMPLE_POLL_INTERVAL_TIMEOUT)
            except Exception as e:
                Logger.error('DataBusPump: Exception in sample_worker: ' + str(e))
                sleep(SAMPLE_POLL_EXCEPTION_RECOVERY)

        Logger.info('DataBusPump: sample_worker exiting')
        safe_thread_exit()
Ejemplo n.º 17
0
    def sample_worker(self):
        rc_api = self._rc_api
        Logger.info('DataBusPump: sample_worker polling starting')
        while self._poll.is_set():
            try:
                rc_api.sample()
                sleep(1.0 / self.current_sample_rate)
            except Exception as e:
                Logger.error('DataBusPump: Exception in sample_worker: ' + str(e))
                sleep(DataBusPump.SAMPLE_POLL_EXCEPTION_RECOVERY)

        Logger.info('DataBusPump: sample_worker exiting')
        safe_thread_exit()
Ejemplo n.º 18
0
    def sample_worker(self):
        rc_api = self._rc_api
        Logger.info('DataBusPump: sample_worker polling starting')
        while self._poll.is_set():
            try:
                rc_api.sample()
                sleep(1.0 / self.current_sample_rate)
            except Exception as e:
                Logger.error('DataBusPump: Exception in sample_worker: ' + str(e))
                sleep(DataBusPump.SAMPLE_POLL_EXCEPTION_RECOVERY)

        Logger.info('DataBusPump: sample_worker exiting')
        safe_thread_exit()
Ejemplo n.º 19
0
    def sample_worker(self):
        rc_api = self._rc_api
        Logger.info('DataBusPump: sample_worker starting')
        while self._running.is_set():
            try:
                rc_api.sample()
                sleep(SAMPLE_POLL_INTERVAL_TIMEOUT)
            except Exception as e:
                Logger.error('DataBusPump: Exception in sample_worker: ' +
                             str(e))
                sleep(SAMPLE_POLL_EXCEPTION_RECOVERY)

        Logger.info('DataBusPump: sample_worker exiting')
        safe_thread_exit()
Ejemplo n.º 20
0
    def auto_detect_worker(self):
        Logger.info('RCPAPI: auto_detect_worker starting')

        class VersionResult(object):
            version_json = None

        def on_ver_win(value, source):
            version_result.version_json = value
            version_result_event.set()

        while self._running.is_set():
            self._auto_detect_event.wait()
            self._auto_detect_event.clear()
            self._enable_autodetect.wait()
            # check again if we're shutting down
            # to prevent a needless re-detection attempt
            if not self._running.is_set():
                break
            try:
                Logger.debug("RCPAPI: Starting auto-detect")
                self._auto_detect_busy.set()
                self.sendCommandLock.acquire()
                self.addListener("ver", on_ver_win)

                comms = self.comms
                if comms and comms.isOpen():
                    comms.close()

                version_result = VersionResult()
                version_result_event = Event()
                version_result_event.clear()

                if comms.device:
                    devices = [comms.device]
                else:
                    devices = comms.get_available_devices()
                    last_known_device = self._settings.userPrefs.get_pref(
                        'preferences', 'last_known_device')
                    # if there was a last known device try it repeatedly while trying the other devices.
                    if last_known_device:
                        Logger.info(
                            'RCPAPI: trying last known device before each other device: {}'
                            .format(last_known_device))
                        # ensure we remove it from the existing list
                        try:
                            devices.remove(last_known_device)
                        except ValueError:
                            pass

                        # rebuild the list, with last_known_device as every second entry
                        temp_list = devices
                        devices = [last_known_device]
                        for device in temp_list:
                            devices = devices + [device, last_known_device]

                    Logger.debug('RCPAPI: Searching for device')

                testVer = VersionConfig()
                for device in devices:
                    try:
                        if not self._running.is_set():
                            break
                        Logger.debug('RCPAPI: Trying ' + str(device))
                        if self.detect_activity_callback:
                            self.detect_activity_callback(str(device))
                        comms.device = device
                        comms.open()
                        self.sendGetVersion()
                        version_result_event.wait(2)
                        version_result_event.clear()
                        if version_result.version_json != None:
                            testVer.fromJson(
                                version_result.version_json.get('ver', None))
                            if testVer.is_valid:
                                break  # we found something!
                        else:
                            try:
                                Logger.debug('RCPAPI: Giving up on ' +
                                             str(device))
                                comms.close()
                            finally:
                                pass

                    except Exception as detail:
                        Logger.error('RCPAPI: Not found on ' + str(device) +
                                     " " + str(detail))
                        Logger.error(traceback.format_exc())
                        try:
                            comms.close()
                        finally:
                            pass

                if testVer.is_valid:
                    Logger.debug("RCPAPI: Found device version " +
                                 str(testVer) + " on port: " +
                                 str(comms.device))
                    self.detect_win(testVer)
                    self._auto_detect_event.clear()
                    self._settings.userPrefs.set_pref('preferences',
                                                      'last_known_device',
                                                      comms.device)
                else:
                    Logger.debug('RCPAPI: Did not find device')
                    comms.close()
                    comms.device = None
                    if self.detect_fail_callback: self.detect_fail_callback()
            except Exception as e:
                Logger.error('RCPAPI: Error running auto detect: ' + str(e))
                Logger.error(traceback.format_exc())
                if self.detect_fail_callback: self.detect_fail_callback()
            finally:
                Logger.debug("RCPAPI: auto detect finished. port=" +
                             str(comms.device))
                self._auto_detect_busy.clear()
                self.removeListener("ver", on_ver_win)
                self.sendCommandLock.release()
                comms.device = None
                sleep(AUTODETECT_COOLOFF_TIME)

        safe_thread_exit()
        Logger.debug('RCPAPI: auto_detect_worker exiting')
Ejemplo n.º 21
0
    def cmd_sequence_worker(self):
        Logger.info('RCPAPI: cmd_sequence_worker starting')
        while self._running.is_set():
            try:
                # Block for 1 second for messages
                command = self._command_queue.get(
                    True, RcpApi.COMMAND_SEQUENCE_TIMEOUT)

                command_list = command.command_list
                rootName = command.rootName
                winCallback = command.winCallback
                failCallback = command.failCallback
                comms = self.comms

                Logger.debug('RCPAPI: Execute Sequence begin')

                if not comms.isOpen(): self.run_auto_detect()

                q = self.cmdSequenceQueue

                responseResults = {}
                cmdCount = 0
                cmdLength = len(command_list)
                self.notifyProgress(cmdCount, cmdLength)
                try:
                    for rcpCmd in command_list:
                        payload = rcpCmd.payload
                        index = rcpCmd.index
                        option = rcpCmd.option
                        last = rcpCmd.last

                        level2Retry = 0
                        name = rcpCmd.name
                        result = None

                        self.addListener(name, self.rcpCmdComplete)
                        while not result and level2Retry <= self.level_2_retries:
                            args = []
                            if payload is not None:
                                args.append(payload)
                            if index is not None:
                                args.append(index)
                            if option is not None:
                                args.append(option)
                            if last is not None:
                                args.append(last)
                            rcpCmd.cmd(*args)
                            retry = 0
                            while not result and retry < DEFAULT_READ_RETRIES:
                                try:
                                    result = q.get(True, self.msg_rx_timeout)
                                    msgName = result.keys()[0]
                                    if not msgName == name:
                                        Logger.warn(
                                            'RCPAPI: rx message did not match expected name '
                                            + str(name) + '; ' + str(msgName))
                                        result = None
                                except Exception as e:
                                    Logger.warn(
                                        'RCPAPI: Read message timeout waiting for {}'
                                        .format(name))
                                    self.recoverTimeout()
                                    retry += 1
                            if not result:
                                Logger.warn('RCPAPI: Level 2 retry for (' +
                                            str(level2Retry) + ') ' + name)
                                level2Retry += 1

                        if not result:
                            raise Exception('Timeout waiting for ' + name)

                        responseResults[name] = result[name]
                        self.removeListener(name, self.rcpCmdComplete)
                        cmdCount += 1
                        self.notifyProgress(cmdCount, cmdLength)

                    if rootName:
                        callback = self.callback_factory(
                            winCallback, {rootName: responseResults})
                    else:
                        callback = self.callback_factory(
                            winCallback, responseResults)

                    Clock.schedule_once(callback)

                except CommsErrorException:
                    self.recover_connection()
                    self.connected_version = None
                except Exception as detail:
                    Logger.error('RCPAPI: Command sequence exception: ' +
                                 str(detail))
                    Logger.error(traceback.format_exc())
                    callback = self.callback_factory(failCallback, detail)
                    Clock.schedule_once(callback)
                    self.connected_version = None
                    self.recover_connection()

                Logger.debug('RCPAPI: Execute Sequence complete')

            except Queue.Empty:
                pass

            except Exception as e:
                Logger.error('RCPAPI: Execute command exception ' + str(e))

        Logger.info('RCPAPI: cmd_sequence_worker exiting')
        safe_thread_exit()
Ejemplo n.º 22
0
    def cmd_sequence_worker(self):
        Logger.info('RCPAPI: cmd_sequence_worker starting')
        while self._running.is_set():
            try:
                # Block for 1 second for messages
                command = self._command_queue.get(True, RcpApi.COMMAND_SEQUENCE_TIMEOUT)

                command_list = command.command_list
                rootName = command.rootName
                winCallback = command.winCallback
                failCallback = command.failCallback
                comms = self.comms

                Logger.debug('RCPAPI: Execute Sequence begin')

                if not comms.isOpen(): self.run_auto_detect()

                q = self.cmdSequenceQueue

                responseResults = {}
                cmdCount = 0
                cmdLength = len(command_list)
                self.notifyProgress(cmdCount, cmdLength)
                try:
                    for rcpCmd in command_list:
                        payload = rcpCmd.payload
                        index = rcpCmd.index
                        option = rcpCmd.option
                        last = rcpCmd.last

                        level2Retry = 0
                        name = rcpCmd.name
                        result = None

                        self.addListener(name, self.rcpCmdComplete)
                        while not result and level2Retry <= self.level_2_retries:
                            args = []
                            if payload is not None:
                                args.append(payload)
                            if index is not None:
                                args.append(index)
                            if option is not None:
                                args.append(option)
                            if last is not None:
                                args.append(last)
                            rcpCmd.cmd(*args)
                            retry = 0
                            while not result and retry < DEFAULT_READ_RETRIES:
                                try:
                                    result = q.get(True, self.msg_rx_timeout)
                                    msgName = result.keys()[0]
                                    if not msgName == name:
                                        Logger.warn('RCPAPI: rx message did not match expected name ' + str(name) + '; ' + str(msgName))
                                        result = None
                                except Exception as e:
                                    Logger.warn('RCPAPI: Read message timeout waiting for {}'.format(name))
                                    self.recoverTimeout()
                                    retry += 1
                            if not result:
                                Logger.warn('RCPAPI: Level 2 retry for (' + str(level2Retry) + ') ' + name)
                                level2Retry += 1


                        if not result:
                            raise Exception('Timeout waiting for ' + name)


                        responseResults[name] = result[name]
                        self.removeListener(name, self.rcpCmdComplete)
                        cmdCount += 1
                        self.notifyProgress(cmdCount, cmdLength)

                    if rootName:
                        callback = self.callback_factory(winCallback, {rootName: responseResults})
                    else:
                        callback = self.callback_factory(winCallback, responseResults)

                    Clock.schedule_once(callback)

                except CommsErrorException:
                    self.recover_connection()
                    self.connected_version = None
                except Exception as detail:
                    Logger.error('RCPAPI: Command sequence exception: ' + str(detail))
                    Logger.error(traceback.format_exc())
                    callback = self.callback_factory(failCallback, detail)
                    Clock.schedule_once(callback)
                    self.connected_version = None
                    self.recover_connection()

                Logger.debug('RCPAPI: Execute Sequence complete')

            except Queue.Empty:
                pass

            except Exception as e:
                Logger.error('RCPAPI: Execute command exception ' + str(e))

        Logger.info('RCPAPI: cmd_sequence_worker exiting')
        safe_thread_exit()
Ejemplo n.º 23
0
    def auto_detect_worker(self):
        Logger.info('RCPAPI: auto_detect_worker starting')
        class VersionResult(object):
            version_json = None

        def on_ver_win(value, source):
            version_result.version_json = value
            version_result_event.set()

        while self._running.is_set():
            self._auto_detect_event.wait()
            self._auto_detect_event.clear()
            self._enable_autodetect.wait()
            # check again if we're shutting down
            # to prevent a needless re-detection attempt
            if not self._running.is_set():
                break
            try:
                Logger.debug("RCPAPI: Starting auto-detect")
                self._auto_detect_busy.set()
                self.sendCommandLock.acquire()
                self.addListener("ver", on_ver_win)

                comms = self.comms
                if comms and comms.isOpen():
                    comms.close()

                version_result = VersionResult()
                version_result_event = Event()
                version_result_event.clear()

                if comms.device:
                    devices = [comms.device]
                else:
                    devices = comms.get_available_devices()
                    last_known_device = self._settings.userPrefs.get_pref('preferences', 'last_known_device')
                    # if there was a last known device try it repeatedly while trying the other devices.
                    if last_known_device:
                        Logger.info('RCPAPI: trying last known device before each other device: {}'.format(last_known_device))
                        # ensure we remove it from the existing list
                        try:
                            devices.remove(last_known_device)
                        except ValueError:
                            pass

                        # rebuild the list, with last_known_device as every second entry
                        temp_list = devices
                        devices = [last_known_device]
                        for device in temp_list:
                            devices = devices + [device, last_known_device]

                    Logger.debug('RCPAPI: Searching for device')

                testVer = VersionConfig()
                for device in devices:
                    try:
                        if not self._running.is_set():
                            break
                        Logger.debug('RCPAPI: Trying ' + str(device))
                        if self.detect_activity_callback: self.detect_activity_callback(str(device))
                        comms.device = device
                        comms.open()
                        self.sendGetVersion()
                        version_result_event.wait(2)
                        version_result_event.clear()
                        if version_result.version_json != None:
                            testVer.fromJson(version_result.version_json.get('ver', None))
                            if testVer.is_valid:
                                break  # we found something!
                        else:
                            try:
                                Logger.debug('RCPAPI: Giving up on ' + str(device))
                                comms.close()
                            finally:
                                pass

                    except Exception as detail:
                        Logger.error('RCPAPI: Not found on ' + str(device) + " " + str(detail))
                        Logger.error(traceback.format_exc())
                        try:
                            comms.close()
                        finally:
                            pass

                if testVer.is_valid:
                    Logger.debug("RCPAPI: Found device version " + str(testVer) + " on port: " + str(comms.device))
                    self.detect_win(testVer)
                    self._auto_detect_event.clear()
                    self._settings.userPrefs.set_pref('preferences', 'last_known_device', comms.device)
                else:
                    Logger.debug('RCPAPI: Did not find device')
                    comms.close()
                    comms.device = None
                    if self.detect_fail_callback: self.detect_fail_callback()
            except Exception as e:
                Logger.error('RCPAPI: Error running auto detect: ' + str(e))
                Logger.error(traceback.format_exc())
                if self.detect_fail_callback: self.detect_fail_callback()
            finally:
                Logger.debug("RCPAPI: auto detect finished. port=" + str(comms.device))
                self._auto_detect_busy.clear()
                self.removeListener("ver", on_ver_win)
                self.sendCommandLock.release()
                comms.device = None
                sleep(AUTODETECT_COOLOFF_TIME)

        safe_thread_exit()
        Logger.debug('RCPAPI: auto_detect_worker exiting')