fixes to polling receiver/device status
This commit is contained in:
parent
2e351bfc78
commit
ed5ce48f65
|
|
@ -40,6 +40,7 @@ class _ThreadedHandle(object):
|
|||
self._listener = listener
|
||||
self.path = path
|
||||
self._local = _threading.local()
|
||||
# take over the current handle for the thread doing the replacement
|
||||
self._local.handle = handle
|
||||
self._handles = [handle]
|
||||
|
||||
|
|
@ -104,7 +105,8 @@ class _ThreadedHandle(object):
|
|||
_EVENT_READ_TIMEOUT = 500
|
||||
|
||||
# After this many reads that did not produce a packet, call the tick() method.
|
||||
_IDLE_READS = 4
|
||||
# This only happens if tick_period is enabled (>0) for the Listener instance.
|
||||
_IDLE_READS = 5
|
||||
|
||||
|
||||
class EventsListener(_threading.Thread):
|
||||
|
|
@ -113,7 +115,7 @@ class EventsListener(_threading.Thread):
|
|||
Incoming packets will be passed to the callback function in sequence.
|
||||
"""
|
||||
def __init__(self, receiver, notifications_callback):
|
||||
super(EventsListener, self).__init__(name=self.__class__.__name__)
|
||||
super(EventsListener, self).__init__(name=self.__class__.__name__ + ':' + receiver.path)
|
||||
|
||||
self.daemon = True
|
||||
self._active = False
|
||||
|
|
@ -128,14 +130,17 @@ class EventsListener(_threading.Thread):
|
|||
self._active = True
|
||||
|
||||
# replace the handle with a threaded one
|
||||
ihandle = int(self.receiver.handle)
|
||||
self.receiver.handle = _ThreadedHandle(self, self.receiver.path, self.receiver.handle)
|
||||
# get the right low-level handle for this thead
|
||||
ihandle = int(self.receiver.handle)
|
||||
_log.info("started with %s (%d)", self.receiver, ihandle)
|
||||
|
||||
self.has_started()
|
||||
|
||||
last_tick = 0
|
||||
idle_reads = _IDLE_READS * 10
|
||||
# the first idle read -- delay it a bit, and make sure to stagger
|
||||
# idle reads for multiple receivers
|
||||
idle_reads = _IDLE_READS + (ihandle % 3) * 2
|
||||
|
||||
while self._active:
|
||||
if self._queued_notifications.empty():
|
||||
|
|
|
|||
|
|
@ -79,6 +79,16 @@ class ReceiverStatus(dict):
|
|||
# self.updated = _timestamp()
|
||||
self._changed_callback(self._receiver, alert=alert, reason=reason)
|
||||
|
||||
def poll(self, timestamp):
|
||||
r = self._receiver
|
||||
assert r
|
||||
|
||||
if _log.isEnabledFor(_DEBUG):
|
||||
_log.debug("polling status of %s", r)
|
||||
|
||||
# make sure to read some stuff that may be read later by the UI
|
||||
r.serial, r.firmware, None
|
||||
|
||||
def process_notification(self, n):
|
||||
if n.sub_id == 0x4A:
|
||||
self.lock_open = bool(n.address & 0x01)
|
||||
|
|
@ -227,16 +237,16 @@ class DeviceStatus(dict):
|
|||
if _log.isEnabledFor(_DEBUG):
|
||||
_log.debug("polling status of %s", d)
|
||||
|
||||
# read these from the device in case they haven't been read already
|
||||
d.protocol, d.serial, d.firmware
|
||||
# read these from the device, the UI may need them later
|
||||
d.protocol, d.firmware, d.kind, d.name, d.settings, None
|
||||
|
||||
# make sure we know all the features of the device
|
||||
# if d.features:
|
||||
# d.features[:]
|
||||
|
||||
if BATTERY_LEVEL not in self:
|
||||
self.read_battery(timestamp)
|
||||
|
||||
# make sure we know all the features of the device
|
||||
if d.features:
|
||||
d.features[:]
|
||||
|
||||
elif len(self) > 0 and timestamp - self.updated > _STATUS_TIMEOUT:
|
||||
# if the device has been inactive for too long, clear out any known
|
||||
# properties, they are most likely obsolete anyway
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ def _ghost(device):
|
|||
|
||||
# how often to poll devices that haven't updated their statuses on their own
|
||||
# (through notifications)
|
||||
_POLL_TICK = 100 # seconds
|
||||
_POLL_TICK = 3 * 60 # seconds
|
||||
|
||||
|
||||
class ReceiverListener(_listener.EventsListener):
|
||||
|
|
@ -41,7 +41,7 @@ class ReceiverListener(_listener.EventsListener):
|
|||
def __init__(self, receiver, status_changed_callback):
|
||||
super(ReceiverListener, self).__init__(receiver, self._notifications_handler)
|
||||
# no reason to enable polling yet
|
||||
# self.tick_period = _POLL_TICK
|
||||
self.tick_period = _POLL_TICK
|
||||
self._last_tick = 0
|
||||
|
||||
assert status_changed_callback
|
||||
|
|
@ -58,7 +58,8 @@ class ReceiverListener(_listener.EventsListener):
|
|||
r, self.receiver = self.receiver, None
|
||||
assert r is not None
|
||||
_log.info("%s: notifications listener has stopped", r)
|
||||
r.status = 'The device was unplugged.'
|
||||
|
||||
r.status = 'The receiver was unplugged.'
|
||||
if r:
|
||||
try:
|
||||
pass
|
||||
|
|
@ -75,8 +76,12 @@ class ReceiverListener(_listener.EventsListener):
|
|||
# configuration.save()
|
||||
|
||||
def tick(self, timestamp):
|
||||
# if _log.isEnabledFor(_DEBUG):
|
||||
# _log.debug("%s: polling status: %s", self.receiver, list(iter(self.receiver)))
|
||||
if not self.tick_period:
|
||||
raise Exception("tick() should not be called without a tick_period: %s", self)
|
||||
|
||||
if not self.receiver:
|
||||
# just in case the receiver was just removed
|
||||
return
|
||||
|
||||
# not necessary anymore, we're now using udev monitor to watch for receiver status
|
||||
# if self._last_tick > 0 and timestamp - self._last_tick > _POLL_TICK * 2:
|
||||
|
|
@ -94,9 +99,20 @@ class ReceiverListener(_listener.EventsListener):
|
|||
# don't mess with stuff while pairing
|
||||
return
|
||||
|
||||
for dev in self.receiver:
|
||||
if dev.status is not None:
|
||||
dev.status.poll(timestamp)
|
||||
self.receiver.status.poll(timestamp)
|
||||
|
||||
# Iterating directly through the reciver would unnecessarily probe
|
||||
# all possible devices, even unpaired ones.
|
||||
# Checking for each device number in turn makes sure only already
|
||||
# known devices are polled.
|
||||
# This is okay because we should have already known about them all
|
||||
# long before the first poll() happents, through notifications.
|
||||
for number in range(1, 6):
|
||||
if number in self.receiver:
|
||||
dev = self.receiver[number]
|
||||
assert dev
|
||||
if dev.status is not None:
|
||||
dev.status.poll(timestamp)
|
||||
|
||||
def _status_changed(self, device, alert=_status.ALERT.NONE, reason=None):
|
||||
assert device is not None
|
||||
|
|
|
|||
Loading…
Reference in New Issue