def _try_baudrate(self, recovery_baudrate): # Here we are in recovery mode _log.debug("Reconfiguring the serial port to recovery baudrate of %d", recovery_baudrate) self._xbee_serial_port.apply_settings({_BAUDRATE_KEY: recovery_baudrate}) # Set the desired configuration permanently. _log.debug("Forcing the current setup to %s", self._desired_cfg) bauds = FirmwareBaudrate.get_by_baudrate(self._desired_cfg[_BAUDRATE_KEY]) if bauds: bauds = format(bauds.index, 'x') else: bauds = format(self._desired_cfg[_BAUDRATE_KEY], 'x') parity = FirmwareParity.get_by_parity(self._desired_cfg[_PARITY_KEY]) if not parity: parity = FirmwareParity.NONE parity = format(parity.index, 'x') stop_bits = FirmwareStopbits.get_by_stopbits(self._desired_cfg[_STOPBITS_KEY]) if not stop_bits: stop_bits = FirmwareStopbits.SB_1 stop_bits = format(stop_bits.index, 'x') cts = -1 rts = -1 if self._desired_cfg[_FLOW_CTRL_KEY] == FlowControl.HARDWARE_RTS_CTS: cts = 1 rts = 1 elif self._desired_cfg[_FLOW_CTRL_KEY] == FlowControl.NONE: # In fact, this should be any value but 1 in any of them # For that, we should read the value and change to 0 only if it is 1 cts = 0 rts = 0 _log.debug("In command mode: %s", enter_at_command_mode(self._xbee_serial_port)) for command in ( "%s%s\r" % (_AT_COMMANDS[_BAUDRATE_KEY], bauds), "%s%s\r" % (_AT_COMMANDS[_PARITY_KEY], parity), "%s%s\r" % (_AT_COMMANDS[_STOPBITS_KEY], stop_bits), "%s%s\r" % (_AT_COMMANDS[_CTS_KEY], cts), "%s%s\r" % (_AT_COMMANDS[_RTS_KEY], rts), "%s%s\r" % (_AT_COMMANDS[_API_ENABLE_KEY], self._desired_cfg[_API_ENABLE_KEY]), "%s%s\r" % (_AT_COMMANDS[_CMD_SEQ_CHAR_KEY], self._desired_cfg[_CMD_SEQ_CHAR_KEY]), "%s%s\r" % (_AT_COMMANDS[_GUARD_TIME_KEY], self._desired_cfg[_GUARD_TIME_KEY]), _AT_COMMANDS[_APPLY_CHANGES_KEY], _AT_COMMANDS[_WRITE_REGISTER_KEY], _AT_COMMANDS[_EXIT_MODE_KEY]): self._xbee_serial_port.write(str.encode(command, encoding="utf8")) if command == _AT_COMMANDS[_EXIT_MODE_KEY]: time.sleep(_DEFAULT_GUARD_TIME) timeout = time.time() + 2 while self._xbee_serial_port.inWaiting() == 0 and time.time() < timeout: time.sleep(0.1) read = self._xbee_serial_port.read(self._xbee_serial_port.inWaiting()) _log.debug("command %s = %s", command[:-1], read) if AT_OK_RESPONSE not in read: return "Command {!r} failed, non OK returned value of {!r}".format(command, read) # self._do_exception( # "Command {!r} failed, non OK returned value of {!r}".format(command, read)) if command == _AT_COMMANDS[_APPLY_CHANGES_KEY]: self._xbee_serial_port.apply_settings(self._desired_cfg) self._restore_target_connection() return None
def _refresh_serial_params(self, node, parameter, value, apply=True): """ Refreshes the proper cached parameter depending on `parameter` value. If `parameter` is not a cached parameter, this method does nothing. Args: node (:class:`.AbstractXBeeDevice`): The XBee to refresh. parameter (String): the parameter to refresh its value. value (Bytearray): the new value of the parameter. apply (Boolean, optional, default=`True`): `True` to apply immediately, `False` otherwise. Returns: Boolean: `True` if a network event must be sent, `False` otherwise. """ node_fut_apply = self._future_apply.get(str(node.get_64bit_addr()), {}) if parameter == ATStringCommand.AP.command: new_op_mode = OperatingMode.get(utils.bytes_to_int(value)) changed = bool(new_op_mode != node.operating_mode and new_op_mode in (OperatingMode.API_MODE, OperatingMode.ESCAPED_API_MODE)) if changed and apply: node._operating_mode = new_op_mode node_fut_apply.pop(parameter, None) elif changed: node_fut_apply.update({parameter: value}) return changed and apply if not node.serial_port or parameter not in ( ATStringCommand.BD.command, ATStringCommand.NB.command, ATStringCommand.SB.command): return False if parameter == ATStringCommand.BD.command: from digi.xbee.profile import FirmwareBaudrate new_bd = utils.bytes_to_int(value) baudrate = FirmwareBaudrate.get(new_bd) new_bd = baudrate.baudrate if baudrate else new_bd changed = new_bd != node.serial_port.baudrate parameter = "baudrate" if changed and apply else parameter value = new_bd if changed and apply else value elif parameter == ATStringCommand.NB.command: from digi.xbee.profile import FirmwareParity new_parity = FirmwareParity.get(utils.bytes_to_int(value)) new_parity = new_parity.parity if new_parity else None changed = new_parity != node.serial_port.parity parameter = "parity" if changed and apply else parameter value = new_parity if changed and apply else value else: from digi.xbee.profile import FirmwareStopbits new_sbits = FirmwareStopbits.get(utils.bytes_to_int(value)) new_sbits = new_sbits.stop_bits if new_sbits else None changed = new_sbits != node.serial_port.stopbits parameter = "stopbits" if changed and apply else parameter value = new_sbits if changed and apply else value if changed and apply: node.serial_port.apply_settings({parameter: value}) node_fut_apply.pop(parameter, None) elif changed: node_fut_apply.update({parameter: value}) return False
def autorecover_device(self): """ Recovers the XBee from an unknown state. Raises: RecoveryException: If there is any error performing the recovery action. """ if self._xbee_device and self._xbee_device.is_open: self._xbee_device.close() self._xbee_serial_port.open() self._xbee_serial_port.purge_port() _log.debug("Autorecovering the device by entering in recovery mode") recovery_baudrate = self._get_recovery_baudrate( _RECOVERY_DETECTION_TRIES) # If we couldn't enter in recovery mode, assume we are in bootloader # and retry if recovery_baudrate is None: _log.error("Could not determine the baudrate in recovery mode, " "assuming device is in bootloader mode and retrying") # Only for XBee 3 modules self._xbee_serial_port.apply_settings( {_BAUDRATE_KEY: _BOOTLOADER_BAUDRATE}) self._xbee_serial_port.write(str.encode(_BOOTLOADER_CONTINUE_KEY)) _log.debug("Retrying to determine the baudrate in recovery mode") recovery_baudrate = self._get_recovery_baudrate( _RECOVERY_DETECTION_TRIES) if recovery_baudrate is None: self._do_exception( "Could not determine the baudrate in recovery mode") # Here we are in recovery mode _log.debug("Reconfiguring the serial port to recovery baudrate of %d", recovery_baudrate) self._xbee_serial_port.apply_settings( {_BAUDRATE_KEY: recovery_baudrate}) # Set the desired configuration permanently. _log.debug("Forcing the current setup to %s", self._desired_cfg) bauds = FirmwareBaudrate.get_by_baudrate( self._desired_cfg[_BAUDRATE_KEY]) if bauds: bauds = format(bauds.index, 'x') else: bauds = format(self._desired_cfg[_BAUDRATE_KEY], 'x') parity = FirmwareParity.get_by_parity(self._desired_cfg[_PARITY_KEY]) if not parity: parity = FirmwareParity.NONE parity = format(parity.index, 'x') stop_bits = FirmwareStopbits.get_by_stopbits( self._desired_cfg[_STOPBITS_KEY]) if not stop_bits: stop_bits = FirmwareStopbits.NONE stop_bits = format(stop_bits.index, 'x') cts = -1 rts = -1 if self._desired_cfg[_FLOW_CTRL_KEY] == FlowControl.HARDWARE_RTS_CTS: cts = 1 rts = 1 elif self._desired_cfg[_FLOW_CTRL_KEY] == FlowControl.NONE: # In fact, this should be any value but 1 in any of them # For that, we should read the value and change to 0 only if it is 1 cts = 0 rts = 0 for command in ("%s%s\r" % (_AT_COMMANDS[_BAUDRATE_KEY], bauds), "%s%s\r" % (_AT_COMMANDS[_PARITY_KEY], parity), "%s%s\r" % (_AT_COMMANDS[_STOPBITS_KEY], stop_bits), "%s%s\r" % (_AT_COMMANDS[_CTS_KEY], cts), "%s%s\r" % (_AT_COMMANDS[_RTS_KEY], rts), "%s%s\r" % (_AT_COMMANDS[_API_ENABLE_KEY], self._desired_cfg[_API_ENABLE_KEY]), "%s%s\r" % (_AT_COMMANDS[_CMD_SEQ_CHAR_KEY], self._desired_cfg[_CMD_SEQ_CHAR_KEY]), "%s%s\r" % (_AT_COMMANDS[_GUARD_TIME_KEY], self._desired_cfg[_GUARD_TIME_KEY]), _AT_COMMANDS[_APPLY_CHANGES_KEY], _AT_COMMANDS[_WRITE_REGISTER_KEY], _AT_COMMANDS[_EXIT_MODE_KEY]): self._xbee_serial_port.write(str.encode(command)) if command == _AT_COMMANDS[_EXIT_MODE_KEY]: time.sleep(_DEFAULT_GUARD_TIME) timeout = time.time() + 2 while self._xbee_serial_port.inWaiting( ) == 0 and time.time() < timeout: time.sleep(0.1) read = self._xbee_serial_port.read( self._xbee_serial_port.inWaiting()) _log.debug("command %s = %s", command[:-1], read) if AT_OK_RESPONSE not in read: self._do_exception( "Command {!r} failed, non OK returned value of {!r}". format(command, read)) if command == _AT_COMMANDS[_APPLY_CHANGES_KEY]: self._xbee_serial_port.apply_settings(self._desired_cfg) self._restore_target_connection()