Example #1
0
    def unpack_package(package_path, target_dir):
        """
        Unpacks a Nordic DFU package.

        :param str package_path: Path to the package
        :param str target_dir: Target directory to unpack the package to
        :return: Manifest Manifest: Returns a manifest back to the user. The manifest is a parse datamodel
        of the manifest found in the Nordic DFU package.
        """

        if not os.path.isfile(package_path):
            raise NordicSemiException("Package {0} not found.".format(package_path))

        target_dir = os.path.abspath(target_dir)
        target_base_path = os.path.dirname(target_dir)

        if not os.path.exists(target_base_path):
            raise NordicSemiException("Base path to target directory {0} does not exist.".format(target_base_path))

        if not os.path.isdir(target_base_path):
            raise NordicSemiException("Base path to target directory {0} is not a directory.".format(target_base_path))

        if os.path.exists(target_dir):
            raise NordicSemiException(
                "Target directory {0} exists, not able to unpack to that directory.",
                target_dir)

        with ZipFile(package_path, 'r') as pkg:
            pkg.extractall(target_dir)

            with open(os.path.join(target_dir, Package.MANIFEST_FILENAME), 'r') as f:
                _json = f.read()
                """:type :str """

                return Manifest.from_json(_json)
    def _wait_for_response(self, opcode):
        """
        Waits for self.response_opcode_received to be set to the expected opcode
        Will timeout after 10 seconds

        :param int opcode: The expected opcode
        :return:
        """
        timeout = 40
        start_time = datetime.now()

        while self.response_opcode_received != opcode:
            timed_out = datetime.now() - start_time > timedelta(0, timeout)
            if timed_out:
                log_message = "Timeout while waiting for response from device."
                self._send_event(DfuEvent.TIMEOUT_EVENT,
                                 log_message=log_message)
                raise NordicSemiException(log_message)

            if self.disconnected_event_received:
                log_message = "Disconnected from device."
                raise IllegalStateException(log_message)

            time.sleep(0.1)

        if self.last_error != DfuErrorCodeBle.SUCCESS:
            error_message = DfuErrorCodeBle.error_code_lookup(self.last_error)
            self._send_event(DfuEvent.ERROR_EVENT, log_message=error_message)
            raise NordicSemiException(error_message)

        self.response_opcode_received = None
Example #3
0
    def open(self):
        super(DfuTransportSerial, self).open()

        try:
            self.serial_port = Serial(port=self.com_port, baudrate=self.baud_rate, rtscts=self.flow_control, timeout=self.timeout)
        except Exception, e:
            raise NordicSemiException("Serial port could not be opened on {0}. Reason: {1}".format(self.com_port, e.message))
Example #4
0
    def open(self):
        super(DfuTransportSerial, self).open()

        # Touch is enabled, disconnect and reconnect
        if self.touch > 0:
            try:
                touch_port = Serial(port=self.com_port,
                                    baudrate=self.touch,
                                    rtscts=self.flow_control,
                                    timeout=self.timeout)
            except Exception as e:
                raise NordicSemiException(
                    "Serial port could not be opened on {0}. Reason: {1}".
                    format(self.com_port, e))

            # Wait for serial port stable
            time.sleep(DfuTransportSerial.SERIAL_PORT_OPEN_WAIT_TIME)

            touch_port.close()
            logger.info("Touched serial port %s", self.com_port)

            # Wait for device go into DFU mode and fully enumerated
            time.sleep(DfuTransportSerial.TOUCH_RESET_WAIT_TIME)

        try:
            self.serial_port = Serial(port=self.com_port,
                                      baudrate=self.baud_rate,
                                      rtscts=self.flow_control,
                                      timeout=self.timeout)
        except Exception as e:
            raise NordicSemiException(
                "Serial port could not be opened on {0}. Reason: {1}".format(
                    self.com_port, e))

        logger.info("Opened serial port %s", self.com_port)

        # Wait for serial port stable
        time.sleep(DfuTransportSerial.SERIAL_PORT_OPEN_WAIT_TIME)

        # Toggle DTR to reset the board and enter DFU mode (only if touch is not used)
        if self.touch == 0:
            self.serial_port.setDTR(False)
            time.sleep(0.05)
            self.serial_port.setDTR(True)

            # Delay to allow device to boot up
            time.sleep(DfuTransportSerial.DTR_RESET_WAIT_TIME)
    def _wait_for_condition(self,
                            condition_function,
                            expected_condition_value=True,
                            timeout=10,
                            waiting_for="condition"):
        """
        Waits for condition_function to be true
        Will timeout after 60 seconds

        :param function condition_function: The function we are waiting for to return true
        :param str timeout_message: Message that should be logged
        :return:
        """

        start_time = datetime.now()

        while condition_function() != expected_condition_value:
            timeout_message = "Timeout while waiting for {0}.".format(
                waiting_for)
            timed_out = datetime.now() - start_time > timedelta(0, timeout)
            if timed_out:
                self._send_event(DfuEvent.TIMEOUT_EVENT,
                                 log_message=timeout_message)
                raise NordicSemiException(timeout_message)

            if not self.is_open():
                log_message = "Disconnected from device while waiting for {0}.".format(
                    waiting_for)
                raise IllegalStateException(log_message)

            sleep(0.1)

        if self.get_last_error() != DfuErrorCodeBle.SUCCESS:
            error_message = "Error occoured while waiting for {0}. Error response {1}."
            error_code = DfuErrorCodeBle.error_code_lookup(
                self.get_last_error())
            error_message = error_message.format(waiting_for, error_code)
            self._send_event(DfuEvent.ERROR_EVENT, log_message=error_message)
            raise NordicSemiException(error_message)
    def open(self):
        super(DfuTransportSerial, self).open()

        try:
            self.serial_port = Serial(port=self.com_port, baudrate=self.baud_rate, rtscts=self.flow_control, timeout=self.timeout)
        except Exception as e:
            raise NordicSemiException("Serial port could not be opened on {0}. Reason: {1}".format(self.com_port, e))

        logger.info("Opened serial port %s", self.com_port)

        # Wait for the system to reset
        time.sleep(DfuTransportSerial.SERIAL_PORT_OPEN_WAIT_TIME)

        # Toggle DTR to reset the board and enter DFU mode
        self.serial_port.setDTR(False)
        time.sleep(0.05)
        self.serial_port.setDTR(True)

        # Delay to allow device to boot up
        time.sleep(DfuTransportSerial.NRF52_RESET_WAIT_TIME)
Example #7
0
    def get_ack_nr(self):
        def is_timeout(start_time, timeout_sec):
            return not (datetime.now() - start_time <= timedelta(
                0, timeout_sec))

        uart_buffer = []
        start = datetime.now()

        while uart_buffer.count(0xC0) < 2:
            # Disregard first of the two C0
            temp = [x for x in self.serial_port.read(6)]

            if temp:
                uart_buffer += temp

            if is_timeout(start, DfuTransportSerial.ACK_PACKET_TIMEOUT):
                # reset HciPacket numbering back to 0
                HciPacket.sequence_number = 0
                self._send_event(
                    DfuEvent.TIMEOUT_EVENT,
                    log_message=
                    "Timed out waiting for acknowledgement from device.")

                # quit loop
                break

                # read until you get a new C0
                # RESUME_WORK

        if len(uart_buffer) < 2:
            raise NordicSemiException(
                "No data received on serial port. Not able to proceed.")

        logger.debug("PC <- target: %s", [hex(i) for i in uart_buffer])
        data = self.decode_esc_chars(uart_buffer)

        # Remove 0xC0 at start and beginning
        data = data[1:-1]

        # Extract ACK number from header
        return (data[0] >> 3) & 0x07
        def sleep_until_ready_to_send():
            """
            Waits until a notification is received from peer device
            Will timeout after 10 seconds

            :return:
            """
            if NUM_OF_PACKETS_BETWEEN_NOTIF:
                timeout = 10
                start_time = datetime.now()

                while not self.ready_to_send:
                    timed_out = datetime.now() - start_time > timedelta(
                        0, timeout)
                    if timed_out:
                        log_message = "Timeout while waiting for notification from device."
                        self._send_event(DfuEvent.TIMEOUT_EVENT,
                                         log_message=log_message)
                        raise NordicSemiException(log_message)

                    time.sleep(0.1)
Example #9
0
def slip_decode_esc_chars(data):
    """Decode esc characters in a SLIP package.

    Replaces 0xDBDC with 0xCO and 0xDBDD with 0xDB.

    :return: str decoded data
    :type str data: data to decode
    """
    result = []
    while len(data):
        char = data.pop(0)
        if char == 0xDB:
            char2 = data.pop(0)
            if char2 == 0xDC:
                result.append(0xC0)
            elif char2 == 0xDD:
                result.append(0xDB)
            else:
                raise NordicSemiException('Char 0xDB NOT followed by 0xDC or 0xDD')
        else:
            result.append(char)
    return result