Description
TLDR: during apply_profile when re-opening the serial connection, we reset the operating mode to API_MODE and if the module is running in ESCAPED_API_MODE, any packets which happen to get escaped will cause a failure.
I'm attempting to apply a profile to a local XBee device. Of note I'm using ESCAPED_API_MODE on the module.
Below is the example I'm trying:
def main():
device = XBeeDevice(PORT, BAUD_RATE)
try:
device.open()
print("Updating profile '%s'...\n" % PROFILE_PATH)
device.apply_profile(PROFILE_PATH, progress_callback=progress_callback)
print("\nProfile updated successfully!")
except Exception as e:
print(str(e))
exit(1)
finally:
if device.is_open():
device.close()
I receive the following error:
Error re-configuring XBee device serial port: Response not received in the configured timeout.
I tracked this down to an issue during the re-opening of the device after applying the serial settings (in _ProfileUpdater._check_port_settings_changed()). During the re-open, the operating_mode in the python code is reset to API_MODE while the module is still running in ESCAPED_API_MODE. It appears that the behavior is specific to the exact settings of the profile, in that I would hit frame id 0x13 after the re-open, which escapes the id, causing the packet to be ignored since it has the extra escape character.
This function mimics the behavior of profile._check_port_settings_changed() that leads to the Exception. It can be seen that there are two failures, one where the failing frame_id (note, not the starting_frame id) is 0x11 and one for 0x13, both of which get escaped.
def replicateBug():
device = XBeeDevice(PORT, BAUD_RATE)
for starting_frame in range(0x0d, 0x14):
# Set the frame id to check by incrementing to it
while device.get_current_frame_id() != starting_frame:
device._get_next_frame_id()
# print("Testing current FrameID: 0x{0:02x}".format(device.get_current_frame_id()))
try:
device.close() # This is necessary to stop the frames read thread.
device.open()
except Exception as e:
print(e)
print("Frame ID 0x{0:02x} Failed".format(starting_frame))
else:
print("Frame ID 0x{0:02x} Succeeded".format(starting_frame))