-
Notifications
You must be signed in to change notification settings - Fork 96
Description
Hi there,
I've been using this library to create a coordinated radio network of xbee devices. One device acts as a coordinator and the rest as nodes. I record statistics for the time to transmit/receive messages to each node.
I noticed that my receive times were curiously always in a multiple of 100ms- which is odd. None of my configuration settings on the XBee itself would have caused this, so I began digging through the code in this repository, which is where I traced the execution path to this function, in https://github.com/digidotcom/xbee-python/blob/master/digi/xbee/reader.py#L2021:
def get_by_remote(self, remote, timeout=None):
"""
Returns the first element of the queue that had been sent by
`remote`, if there is some in the specified timeout.
If timeout is `None`, this method is non-blocking. In this case, if
there is not any packet sent by `remote` in the queue, it returns
`None`, otherwise it returns an :class:`.XBeeAPIPacket`.
Args:
remote (:class:`.RemoteXBeeDevice`): Remote XBee to get its first
element from queue.
timeout (Integer, optional, default=`None`): Timeout in seconds.
Returns:
:class:`.XBeeAPIPacket`: If there is any packet available before
the timeout expires. If timeout is `None`, the returned value
may be `None`.
Raises:
TimeoutException: If timeout is not `None` and there is not any
packet available that was sent by `remote` before the timeout
expires.
"""
if timeout is None:
with self.mutex:
for packet in self.queue:
if self.__remote_device_match(packet, remote):
self.queue.remove(packet)
return packet
return None
packet = self.get_by_remote(remote)
dead_line = time.time() + timeout
while packet is None and dead_line > time.time():
time.sleep(0.1)
packet = self.get_by_remote(remote)
if packet is None:
raise TimeoutException()
return packet
time.sleep(0.1) in a loop... Who thought this was a good idea?! I have sidestepped the issue by calling the read_data_remote function without a timeout and using my own timeout loop with an increment smaller than 100ms.
This problem could be avoided entirely by instantiating a separate data queue for each remote device and thus being able to use the builtin queue.get with the appropriate timeout, like in the get() method just above the offending function.
But if you don't want to do all that, just make the increment smaller than 100ms (I chose 10ms) to make it more tolerable.