device: clean up pinging code
This commit is contained in:
parent
5657c1ac99
commit
0905ed5f43
|
@ -499,40 +499,29 @@ def request(handle, devnumber, request_id, *params, no_reply=False, return_error
|
||||||
|
|
||||||
def ping(handle, devnumber, long_message=False):
|
def ping(handle, devnumber, long_message=False):
|
||||||
"""Check if a device is connected to the receiver.
|
"""Check if a device is connected to the receiver.
|
||||||
|
|
||||||
:returns: The HID protocol supported by the device, as a floating point number, if the device is active.
|
:returns: The HID protocol supported by the device, as a floating point number, if the device is active.
|
||||||
"""
|
"""
|
||||||
if _log.isEnabledFor(_DEBUG):
|
if _log.isEnabledFor(_DEBUG):
|
||||||
_log.debug('(%s) pinging device %d', handle, devnumber)
|
_log.debug('(%s) pinging device %d', handle, devnumber)
|
||||||
|
|
||||||
# import inspect as _inspect
|
|
||||||
# print ('\n '.join(str(s) for s in _inspect.stack()))
|
|
||||||
|
|
||||||
with acquire_timeout(handle_lock(handle), handle, 10.):
|
with acquire_timeout(handle_lock(handle), handle, 10.):
|
||||||
|
notifications_hook = getattr(handle, 'notifications_hook', None)
|
||||||
|
try:
|
||||||
|
_skip_incoming(handle, int(handle), notifications_hook)
|
||||||
|
except NoReceiver:
|
||||||
|
_log.warn('device or receiver disconnected')
|
||||||
|
return
|
||||||
|
|
||||||
# randomize the SoftwareId and mark byte to be able to identify the ping
|
# randomize the SoftwareId and mark byte to be able to identify the ping
|
||||||
# reply, and set most significant (0x8) bit in SoftwareId so that the reply
|
# reply, and set most significant (0x8) bit in SoftwareId so that the reply
|
||||||
# is always distinguishable from notifications
|
# is always distinguishable from notifications
|
||||||
request_id = 0x0018 | _random_bits(3)
|
request_id = 0x0018 | _random_bits(3)
|
||||||
request_data = _pack('!HBBB', request_id, 0, 0, _random_bits(8))
|
request_data = _pack('!HBBB', request_id, 0, 0, _random_bits(8))
|
||||||
|
write(int(handle), devnumber, request_data, long_message)
|
||||||
|
|
||||||
ihandle = int(handle)
|
request_started = _timestamp() # we consider timeout from this point
|
||||||
notifications_hook = getattr(handle, 'notifications_hook', None)
|
|
||||||
try:
|
|
||||||
_skip_incoming(handle, ihandle, notifications_hook)
|
|
||||||
except NoReceiver:
|
|
||||||
_log.warn('device or receiver disconnected')
|
|
||||||
return
|
|
||||||
|
|
||||||
write(ihandle, devnumber, request_data, long_message)
|
|
||||||
|
|
||||||
# we consider timeout from this point
|
|
||||||
request_started = _timestamp()
|
|
||||||
delta = 0
|
delta = 0
|
||||||
|
|
||||||
while delta < _PING_TIMEOUT:
|
while delta < _PING_TIMEOUT:
|
||||||
reply = _read(handle, _PING_TIMEOUT)
|
reply = _read(handle, _PING_TIMEOUT)
|
||||||
|
|
||||||
if reply:
|
if reply:
|
||||||
report_id, reply_devnumber, reply_data = reply
|
report_id, reply_devnumber, reply_data = reply
|
||||||
if reply_devnumber == devnumber:
|
if reply_devnumber == devnumber:
|
||||||
|
@ -540,17 +529,14 @@ def ping(handle, devnumber, long_message=False):
|
||||||
# HID++ 2.0+ device, currently connected
|
# HID++ 2.0+ device, currently connected
|
||||||
return ord(reply_data[2:3]) + ord(reply_data[3:4]) / 10.0
|
return ord(reply_data[2:3]) + ord(reply_data[3:4]) / 10.0
|
||||||
|
|
||||||
if report_id == HIDPP_SHORT_MESSAGE_ID and reply_data[:1] == b'\x8F' and reply_data[1:3] == request_data[:2
|
if report_id == HIDPP_SHORT_MESSAGE_ID and reply_data[:1] == b'\x8F' and \
|
||||||
]:
|
reply_data[1:3] == request_data[:2]: # error response
|
||||||
assert reply_data[-1:] == b'\x00'
|
assert reply_data[-1:] == b'\x00'
|
||||||
error = ord(reply_data[3:4])
|
error = ord(reply_data[3:4])
|
||||||
|
|
||||||
if error == _hidpp10.ERROR.invalid_SubID__command: # a valid reply from a HID++ 1.0 device
|
if error == _hidpp10.ERROR.invalid_SubID__command: # a valid reply from a HID++ 1.0 device
|
||||||
return 1.0
|
return 1.0
|
||||||
|
|
||||||
if error == _hidpp10.ERROR.resource_error: # device unreachable
|
if error == _hidpp10.ERROR.resource_error: # device unreachable
|
||||||
return
|
return
|
||||||
|
|
||||||
if error == _hidpp10.ERROR.unknown_device: # no paired device with that number
|
if error == _hidpp10.ERROR.unknown_device: # no paired device with that number
|
||||||
_log.error('(%s) device %d error on ping request: unknown device', handle, devnumber)
|
_log.error('(%s) device %d error on ping request: unknown device', handle, devnumber)
|
||||||
raise NoSuchDevice(number=devnumber, request=request_id)
|
raise NoSuchDevice(number=devnumber, request=request_id)
|
||||||
|
@ -565,4 +551,3 @@ def ping(handle, devnumber, long_message=False):
|
||||||
delta = _timestamp() - request_started
|
delta = _timestamp() - request_started
|
||||||
|
|
||||||
_log.warn('(%s) timeout (%0.2f/%0.2f) on device %d ping', handle, delta, _PING_TIMEOUT, devnumber)
|
_log.warn('(%s) timeout (%0.2f/%0.2f) on device %d ping', handle, delta, _PING_TIMEOUT, devnumber)
|
||||||
# raise DeviceUnreachable(number=devnumber, request=request_id)
|
|
||||||
|
|
|
@ -141,33 +141,20 @@ class EventsListener(_threading.Thread):
|
||||||
|
|
||||||
def __init__(self, receiver, notifications_callback):
|
def __init__(self, receiver, notifications_callback):
|
||||||
super().__init__(name=self.__class__.__name__ + ':' + receiver.path.split('/')[2])
|
super().__init__(name=self.__class__.__name__ + ':' + receiver.path.split('/')[2])
|
||||||
|
|
||||||
self.daemon = True
|
self.daemon = True
|
||||||
self._active = False
|
self._active = False
|
||||||
|
|
||||||
self.receiver = receiver
|
self.receiver = receiver
|
||||||
self._queued_notifications = _Queue(16)
|
self._queued_notifications = _Queue(16)
|
||||||
self._notifications_callback = notifications_callback
|
self._notifications_callback = notifications_callback
|
||||||
|
|
||||||
# self.tick_period = 0
|
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
self._active = True
|
self._active = True
|
||||||
|
|
||||||
# replace the handle with a threaded one
|
# replace the handle with a threaded one
|
||||||
self.receiver.handle = _ThreadedHandle(self, self.receiver.path, self.receiver.handle)
|
self.receiver.handle = _ThreadedHandle(self, self.receiver.path, self.receiver.handle)
|
||||||
# get the right low-level handle for this thread
|
|
||||||
ihandle = int(self.receiver.handle)
|
|
||||||
if _log.isEnabledFor(_INFO):
|
if _log.isEnabledFor(_INFO):
|
||||||
_log.info('started with %s (%d)', self.receiver, ihandle)
|
_log.info('started with %s (%d)', self.receiver, int(self.receiver.handle))
|
||||||
|
|
||||||
self.has_started()
|
self.has_started()
|
||||||
|
|
||||||
# last_tick = 0
|
|
||||||
# the first idle read -- delay it a bit, and make sure to stagger
|
|
||||||
# idle reads for multiple receivers
|
|
||||||
# idle_reads = _IDLE_READS + (ihandle % 5) * 2
|
|
||||||
|
|
||||||
if self.receiver.isDevice: # ping (wired or BT) devices to see if they are really online
|
if self.receiver.isDevice: # ping (wired or BT) devices to see if they are really online
|
||||||
if self.receiver.ping():
|
if self.receiver.ping():
|
||||||
self.receiver.status.changed(True, reason='initialization')
|
self.receiver.status.changed(True, reason='initialization')
|
||||||
|
@ -175,36 +162,21 @@ class EventsListener(_threading.Thread):
|
||||||
while self._active:
|
while self._active:
|
||||||
if self._queued_notifications.empty():
|
if self._queued_notifications.empty():
|
||||||
try:
|
try:
|
||||||
# _log.debug("read next notification")
|
|
||||||
n = _base.read(self.receiver.handle, _EVENT_READ_TIMEOUT)
|
n = _base.read(self.receiver.handle, _EVENT_READ_TIMEOUT)
|
||||||
except _base.NoReceiver:
|
except _base.NoReceiver:
|
||||||
_log.warning('%s disconnected', self.receiver.name)
|
_log.warning('%s disconnected', self.receiver.name)
|
||||||
self.receiver.close()
|
self.receiver.close()
|
||||||
break
|
break
|
||||||
|
|
||||||
if n:
|
if n:
|
||||||
n = _base.make_notification(*n)
|
n = _base.make_notification(*n)
|
||||||
else:
|
else:
|
||||||
# deliver any queued notifications
|
n = self._queued_notifications.get() # deliver any queued notifications
|
||||||
n = self._queued_notifications.get()
|
|
||||||
|
|
||||||
if n:
|
if n:
|
||||||
# if _log.isEnabledFor(_DEBUG):
|
|
||||||
# _log.debug("%s: processing %s", self.receiver, n)
|
|
||||||
try:
|
try:
|
||||||
self._notifications_callback(n)
|
self._notifications_callback(n)
|
||||||
except Exception:
|
except Exception:
|
||||||
_log.exception('processing %s', n)
|
_log.exception('processing %s', n)
|
||||||
|
|
||||||
# elif self.tick_period:
|
|
||||||
# idle_reads -= 1
|
|
||||||
# if idle_reads <= 0:
|
|
||||||
# idle_reads = _IDLE_READS
|
|
||||||
# now = _timestamp()
|
|
||||||
# if now - last_tick >= self.tick_period:
|
|
||||||
# last_tick = now
|
|
||||||
# self.tick(now)
|
|
||||||
|
|
||||||
del self._queued_notifications
|
del self._queued_notifications
|
||||||
self.has_stopped()
|
self.has_stopped()
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue