one a separate flag to check if the device is active

This commit is contained in:
Daniel Pavel 2013-06-21 15:17:14 +02:00
parent c04851f64e
commit fd35f23af7
9 changed files with 212 additions and 146 deletions

View File

@ -105,8 +105,8 @@ def get_register(device, name, default_number=-1):
if reply:
return reply
if not known_register and device.ping():
_log.warn("%s: failed to read '%s' from default register 0x%02X, blacklisting",
if not known_register and device.kind is not None and device.online:
_log.warn("%s: failed to read register '%s' (0x%02X), blacklisting",
device, name, default_number)
device.registers[name] = -default_number

View File

@ -147,7 +147,7 @@ class FeaturesArray(object):
if self.features is not None:
return True
if hasattr(self.device, 'status') and not bool(self.device.status):
if not self.device.online:
# device is not connected right now, will have to try later
return False

View File

@ -26,11 +26,12 @@ MAX_PAIRED_DEVICES = 6
class PairedDevice(object):
def __init__(self, receiver, number):
def __init__(self, receiver, number, link_notification=None):
assert receiver
self.receiver = _proxy(receiver)
assert number > 0 and number <= receiver.max_devices
self.number = number
self.online = None
self.wpid = None
self.polling_rate = 0
@ -38,56 +39,61 @@ class PairedDevice(object):
self._kind = None
self._codename = None
self._name = None
self._protocol = None
self._serial = None
unifying = self.receiver.unifying_supported
if unifying:
# force a reading of the codename
if self.codename is None:
raise _base.NoSuchDevice(nuber=number, receiver=receiver, error="read codename")
if link_notification is None:
if unifying:
# force a reading of the codename
pair_info = receiver.read_register(0x2B5, 0x20 + number - 1)
if pair_info is None:
raise _base.NoSuchDevice(nuber=number, receiver=receiver, error="read pair info")
pair_info = receiver.request(0x83B5, 0x20 + number - 1)
if pair_info is None:
raise _base.NoSuchDevice(nuber=number, receiver=receiver, error="read pair info")
self.wpid = _strhex(pair_info[3:5])
kind = ord(pair_info[7:8]) & 0x0F
self._kind = _hidpp10.DEVICE_KIND[kind]
self.polling_rate = ord(pair_info[2:3])
else:
# guesswork...
descriptor = _descriptors.DEVICES.get(self.receiver.product_id)
if descriptor is None:
self._codename = self.receiver.product_id
# actually there IS a device, just that we can't identify it
# raise _base.NoSuchDevice(nuber=number, receiver=receiver, product_id=receiver.product_id, failed="no descriptor")
self._name = 'Unknown device ' + self._codename
self.wpid = _strhex(pair_info[3:5])
kind = ord(pair_info[7:8]) & 0x0F
self._kind = _hidpp10.DEVICE_KIND[kind]
self.polling_rate = ord(pair_info[2:3])
else:
self._codename = descriptor.codename
self._name = descriptor.name
# guesswork... look for the product id in the descriptors
descriptor = _descriptors.DEVICES.get(self.receiver.product_id)
if descriptor is None:
self._codename = self.receiver.product_id
# actually there IS a device, just that we can't identify it
# raise _base.NoSuchDevice(nuber=number, receiver=receiver, product_id=receiver.product_id, failed="no descriptor")
self._name = 'Unknown device ' + self._codename
else:
self._codename = descriptor.codename
self._name = descriptor.name
device_info = self.receiver.request(0x83B5, 0x04)
assert device_info, "failed to read Nano device info"
self.wpid = _strhex(device_info[3:5])
# self._kind = descriptor.kind
self.polling_rate = 0
device_info = self.receiver.read_register(0x2B5, 0x04)
if device_info is None:
raise _base.NoSuchDevice(nuber=number, receiver=receiver, error="read Nano wpid")
self.wpid = _strhex(device_info[3:5])
# self._kind = descriptor.kind
self.serial = self.receiver.serial
else:
self.wpid = _strhex(link_notification.data[2:3] + link_notification.data[1:2])
assert link_notification.address == (0x04 if unifying else 0x03)
kind = ord(link_notification.data[1:2]) & 0x0F
self._kind = _hidpp10.DEVICE_KIND[kind]
self.online = bool(ord(link_notification.data[0:1]) & 0x40)
# the wpid is necessary to properly identify wireless link on/off notifications
# also it gets set to None when the device is unpaired
assert self.wpid is not None, "failed to read wpid: device %d of %s" % (number, receiver)
# the codename is necessary to guess all other info
assert self._codename is not None, "failed to read codename: device %d of %s" % (number, receiver)
# knowing the protocol as soon as possible helps reading all other info
# and avoids an unecessary ping
descriptor = _descriptors.DEVICES.get(self.codename)
if descriptor is None:
_log.warn("device without descriptor found: %s (%d of %s)", self.codename, number, receiver)
self._protocol = None if unifying else 1.0
else:
self._protocol = descriptor.protocol if unifying else 1.0 # may be None
if self._codename is not None:
descriptor = _descriptors.DEVICES.get(self._codename)
if descriptor is None:
_log.warn("device without descriptor found: %s (%d of %s)", self._codename, number, receiver)
self._protocol = None if unifying else 1.0
else:
self._protocol = descriptor.protocol if unifying else 1.0 # may be None
self._power_switch = None if unifying else '(unknown)'
self.serial = _hidpp10.get_serial(self) if unifying else self.receiver.serial
self._firmware = None
self._keys = None
@ -106,10 +112,22 @@ class PairedDevice(object):
def protocol(self):
if self._protocol is None:
self._protocol = _base.ping(self.receiver.handle, self.number)
# if the ping failed, the peripheral is (almost) certainly offline
self.online = self._protocol is not None
# use the descriptor only as a fallback, because it may not be 100% correct
descriptor = _descriptors.DEVICES.get(self.codename)
if self._protocol is None:
descriptor = _descriptors.DEVICES.get(self.codename)
if descriptor and descriptor.protocol is not None:
self._protocol = descriptor.protocol
else:
if descriptor:
if descriptor.protocol is None:
_log.info("%s: descriptor has no protocol, should be %0.1f", self, self._protocol)
elif descriptor.protocol != self._protocol:
_log.error("%s: descriptor has wrong protocol %0.1f, should be %0.1f",
self, descriptor.protocol, self._protocol)
# _log.debug("device %d protocol %s", self.number, self._protocol)
return self._protocol or 0
@ -131,12 +149,12 @@ class PairedDevice(object):
if codename:
self._codename = codename[2:].rstrip(b'\x00').decode('utf-8')
# _log.debug("device %d codename %s", self.number, self._codename)
return self._codename
return self._codename or '?'
@property
def name(self):
if self._name is None:
if self.protocol >= 2.0:
if self.protocol >= 2.0 and self.online:
self._name = _hidpp20.get_name(self)
if self._name is None:
descriptor = _descriptors.DEVICES.get(self.codename)
@ -155,7 +173,7 @@ class PairedDevice(object):
# self._kind = _hidpp10.DEVICE_KIND[kind]
# if self.wpid is None:
# self.wpid = _strhex(pair_info[3:5])
if self.protocol >= 2.0:
if self.protocol >= 2.0 and self.online:
self._kind = _hidpp20.get_kind(self)
if self._kind is None:
descriptor = _descriptors.DEVICES.get(self.codename)
@ -165,26 +183,25 @@ class PairedDevice(object):
@property
def firmware(self):
if self._firmware is None:
if self._firmware is None and self.online:
if self.protocol < 2.0:
self._firmware = _hidpp10.get_firmware(self)
else:
self._firmware = _hidpp20.get_firmware(self)
return self._firmware or ()
# @property
# def serial(self):
# if self._serial is None:
# if self.receiver.unifying_supported:
# self._serial = _hidpp10.get_serial(self)
# else:
# self._serial = self.receiver.serial
# return self._serial or '?'
@property
def serial(self):
if self._serial is None:
assert self.receiver.unifying_supported
# otherwise it should have been set in the constructor
self._serial = _hidpp10.get_serial(self)
return self._serial or '?'
@property
def keys(self):
if self._keys is None:
if self.protocol >= 2.0:
if self.protocol >= 2.0 and self.online:
self._keys = _hidpp20.get_keys(self) or ()
return self._keys
@ -207,14 +224,14 @@ class PairedDevice(object):
else:
self._settings = [s(self) for s in descriptor.settings]
if self.features:
if self.online and self.features:
_descriptors.check_features(self, self._settings)
return self._settings
def enable_notifications(self, enable=True):
"""Enable or disable device (dis)connection notifications on this
receiver."""
if not self.receiver or not self.receiver.handle or self.protocol >= 2.0:
if not bool(self.receiver) or self.protocol >= 2.0:
return False
if enable:
@ -245,7 +262,10 @@ class PairedDevice(object):
return _hidpp20.feature_request(self, feature, function, *params)
def ping(self):
return _base.ping(self.receiver.handle, self.number) is not None
"""Checks if the device is online, returns True of False"""
protocol = _base.ping(self.receiver.handle, self.number)
self.online = protocol is not None
return self.online
def __index__(self):
return self.number
@ -260,6 +280,8 @@ class PairedDevice(object):
def __hash__(self):
return self.serial.__hash__()
__bool__ = __nonzero__ = lambda self: self.wpid is not None and self.number in self.receiver
def __str__(self):
return '<PairedDevice(%d,%s,%s)>' % (self.number, self.wpid, self.codename or '?')
__unicode__ = __repr__ = __str__
@ -349,12 +371,15 @@ class Receiver(object):
if not self.write_register(0x02, 0x02):
_log.warn("%s: failed to trigger device link notifications", self)
def register_new_device(self, number):
def register_new_device(self, number, notification=None):
if self._devices.get(number) is not None:
raise IndexError("%s: device number %d already registered" % (self, number))
assert notification is None or notification.devnumber == number
assert notification is None or notification.sub_id == 0x41
try:
dev = PairedDevice(self, number)
dev = PairedDevice(self, number, notification)
assert dev.wpid
_log.info("%s: found new device %d (%s)", self, number, dev.wpid)
self._devices[number] = dev
@ -420,6 +445,7 @@ class Receiver(object):
if reply:
# invalidate the device
dev.wpid = None
dev.online = False
del self._devices[key]
_log.warn("%s unpaired device %s", self, dev)
else:

View File

@ -190,8 +190,10 @@ class DeviceStatus(dict):
self._changed(alert=alert, reason=reason, timestamp=timestamp)
def read_battery(self, timestamp=None):
d = self._device
if d and self._active:
if self._active:
d = self._device
assert d
if d.protocol < 2.0:
battery = _hidpp10.get_battery(d)
else:
@ -213,29 +215,32 @@ class DeviceStatus(dict):
self[KEYS.BATTERY_CHARGING] = None
self._changed()
def _changed(self, active=True, alert=ALERT.NONE, reason=None, timestamp=None):
def _changed(self, active=None, alert=ALERT.NONE, reason=None, timestamp=None):
assert self._changed_callback
assert self._device
d = self._device
was_active, self._active = self._active, active
if active:
if not was_active:
# Make sure to set notification flags on the device, they
# get cleared when the device is turned off (but not when the device
# goes idle, and we can't tell the difference right now).
self[KEYS.NOTIFICATION_FLAGS] = d.enable_notifications()
if self.configuration:
self.configuration.attach_to(d)
else:
if was_active:
battery = self.get(KEYS.BATTERY_LEVEL)
self.clear()
# If we had a known battery level before, assume it's not going
# to change much while the device is offline.
if battery is not None:
self[KEYS.BATTERY_LEVEL] = battery
assert d
if self.updated == 0 and active:
if active is not None:
d.online = active
was_active, self._active = self._active, active
if active:
if not was_active:
# Make sure to set notification flags on the device, they
# get cleared when the device is turned off (but not when the device
# goes idle, and we can't tell the difference right now).
self[KEYS.NOTIFICATION_FLAGS] = d.enable_notifications()
if self.configuration:
self.configuration.attach_to(d)
else:
if was_active:
battery = self.get(KEYS.BATTERY_LEVEL)
self.clear()
# If we had a known battery level before, assume it's not going
# to change much while the device is offline.
if battery is not None:
self[KEYS.BATTERY_LEVEL] = battery
if self.updated == 0 and active == True:
# if the device is active on the very first status notification,
# (meaning just when the program started or a new receiver was just
# detected), pop-up a notification about it
@ -330,8 +335,10 @@ class DeviceStatus(dict):
if n.address == 0x02:
# device un-paired
self.clear()
self._device.status = None
self._changed(False, ALERT.ALL, 'unpaired')
dev = self._device
dev.wpid = None
dev.status = None
self._changed(active=False, alert=ALERT.ALL, reason='unpaired')
else:
_log.warn("%s: disconnection with unknown type %02X: %s", self._device, n.address, n)
return True
@ -342,6 +349,10 @@ class DeviceStatus(dict):
else 'eQuad' if n.address == 0x03
else None)
if protocol_name:
if _log.isEnabledFor(_DEBUG):
wpid = _strhex(n.data[2:3] + n.data[1:2])
assert wpid == self._device.wpid, "%s wpid mismatch, got %s" % (self._device, wpid)
flags = ord(n.data[:1]) & 0xF0
link_encrypyed = bool(flags & 0x20)
link_established = not (flags & 0x40)
@ -351,21 +362,21 @@ class DeviceStatus(dict):
_log.debug("%s: %s connection notification: software=%s, encrypted=%s, link=%s, payload=%s",
self._device, protocol_name, sw_present, link_encrypyed, link_established, has_payload)
self[KEYS.LINK_ENCRYPTED] = link_encrypyed
self._changed(link_established)
self._changed(active=link_established)
if protocol_name == 'eQuad':
# some Nano devices might not have been initialized fully
if self._device._kind is None:
kind = ord(n.data[:1]) & 0x0F
self._device._kind = _hidpp10.DEVICE_KIND[kind]
assert self._device.wpid == _strhex(n.data[2:3] + n.data[1:2])
# if protocol_name == 'eQuad':
# # some Nano devices might not have been initialized fully
# if self._device._kind is None:
# kind = ord(n.data[:1]) & 0x0F
# self._device._kind = _hidpp10.DEVICE_KIND[kind]
# assert self._device.wpid == _strhex(n.data[2:3] + n.data[1:2])
# if the device just came online, read the battery charge
if self._active and KEYS.BATTERY_LEVEL not in self:
self.read_battery()
else:
_log.warn("%s: connection notification with unknown protocol %02X: %s", self._device.number, n.address, n)
# if the device just came online, read the battery charge
if self._active and KEYS.BATTERY_LEVEL not in self:
self.read_battery()
return True
if n.sub_id == 0x49:
@ -380,7 +391,7 @@ class DeviceStatus(dict):
if _log.isEnabledFor(_DEBUG):
_log.debug("%s: device powered on", self._device)
reason = str(self) or 'powered on'
self._changed(alert=ALERT.NOTIFICATION, reason=reason)
self._changed(active=True, alert=ALERT.NOTIFICATION, reason=reason)
else:
_log.info("%s: unknown %s", self._device, n)
return True
@ -410,7 +421,7 @@ class DeviceStatus(dict):
if _log.isEnabledFor(_DEBUG):
_log.debug("wireless status: %s", n)
if n.data[0:3] == b'\x01\x01\x01':
self._changed(alert=ALERT.NOTIFICATION, reason='powered on')
self._changed(active=True, alert=ALERT.NOTIFICATION, reason='powered on')
else:
_log.info("%s: unknown WIRELESS %s", self._device, n)
else:
@ -426,11 +437,11 @@ class DeviceStatus(dict):
if n.address == 0x00:
self[KEYS.LIGHT_LEVEL] = None
self[KEYS.BATTERY_CHARGING] = None
self._changed()
self._changed(active=True)
elif n.address == 0x10:
self[KEYS.LIGHT_LEVEL] = lux
self[KEYS.BATTERY_CHARGING] = lux > 200
self._changed()
self._changed(active=True)
elif n.address == 0x20:
_log.debug("%s: Light Check button pressed", self._device)
self._changed(alert=ALERT.SHOW_WINDOW)

View File

@ -18,7 +18,7 @@ from logitech.unifying_receiver import (Receiver,
#
from collections import namedtuple
_GHOST_DEVICE = namedtuple('_GHOST_DEVICE', ['receiver', 'number', 'name', 'kind', 'serial', 'status'])
_GHOST_DEVICE = namedtuple('_GHOST_DEVICE', ['receiver', 'number', 'name', 'kind', 'serial', 'status', 'online'])
_GHOST_DEVICE.__bool__ = lambda self: False
_GHOST_DEVICE.__nonzero__ = _GHOST_DEVICE.__bool__
del namedtuple
@ -30,7 +30,8 @@ def _ghost(device):
name=device.name,
kind=device.kind,
serial=device.serial,
status=None)
status=None,
online=False)
#
#
@ -109,8 +110,7 @@ class ReceiverListener(_listener.EventsListener):
for number in range(1, 6):
if number in self.receiver:
dev = self.receiver[number]
assert dev
if dev.status is not None:
if dev and dev.status is not None:
dev.status.poll(timestamp)
except Exception as e:
_log.exception("polling", e)
@ -118,9 +118,15 @@ class ReceiverListener(_listener.EventsListener):
def _status_changed(self, device, alert=_status.ALERT.NONE, reason=None):
assert device is not None
if _log.isEnabledFor(_DEBUG):
_log.debug("%s: status_changed %s: %s, %s (%X) %s", self.receiver, device,
'active' if device.status else 'inactive',
device.status, alert, reason or '')
if device.kind is None:
_log.debug("status_changed %s: %s, %s (%X) %s", device,
'present' if bool(device) else 'removed',
device.status, alert, reason or '')
else:
_log.debug("status_changed %s: %s %s, %s (%X) %s", device,
'paired' if bool(device) else 'unpaired',
'online' if device.online else 'offline',
device.status, alert, reason or '')
if device.kind is None:
assert device == self.receiver
@ -129,16 +135,15 @@ class ReceiverListener(_listener.EventsListener):
return
assert device.receiver == self.receiver
if device.status is None:
if not device:
# device was unpaired, and since the object is weakref'ed
# it won't be valid for much longer
_log.info("device %s was unpaired, ghosting", device)
_log.warn("device %s was unpaired, ghosting", device)
device = _ghost(device)
self.status_changed_callback(device, alert, reason)
if device.status is None:
if not device:
# the device was just unpaired, need to update the
# status of the receiver as well
self.status_changed_callback(self.receiver)
@ -155,28 +160,33 @@ class ReceiverListener(_listener.EventsListener):
# a device notification
assert n.devnumber > 0 and n.devnumber <= self.receiver.max_devices
already_known = n.devnumber in self.receiver
dev = self.receiver[n.devnumber]
if not already_known and n.sub_id == 0x41:
dev = self.receiver.register_new_device(n.devnumber, n)
else:
dev = self.receiver[n.devnumber]
if not dev:
_log.warn("%s: received %s for invalid device %d: %r", self.receiver, n, n.devnumber, dev)
return
if not already_known:
# read these as soon as possible, they will be used everywhere
dev.protocol, dev.codename
# _log.info("%s triggered new device %s", n, dev)
dev.status = _status.DeviceStatus(dev, self._status_changed)
dev.status.configuration = configuration
# the receiver changed status as well
self._status_changed(self.receiver)
# status may be None if the device has just been unpaired
if dev.status is not None:
dev.status.process_notification(n)
if self.receiver.status.lock_open and not already_known:
# this should be the first notification after a device was paired
assert n.sub_id == 0x41 and n.address == 0x04
_log.info("%s: pairing detected new device", self.receiver)
self.receiver.status.new_device = dev
assert dev
assert dev.status is not None
dev.status.process_notification(n)
if self.receiver.status.lock_open and not already_known:
# this should be the first notification after a device was paired
assert n.sub_id == 0x41 and n.address == 0x04
_log.info("%s: pairing detected new device", self.receiver)
self.receiver.status.new_device = dev
else:
if dev.online is None:
dev.ping()
def __str__(self):
return '<ReceiverListener(%s,%s)>' % (self.receiver.path, self.receiver.handle)

View File

@ -63,7 +63,7 @@ def destroy():
from logitech.unifying_receiver.status import ALERT
def _status_changed(device, alert, reason):
assert device is not None
_log.info("status changed: %s, %s, %s", device, alert, reason)
_log.info("status changed: %s (%s) %s", device, alert, reason)
tray.update(device)
if alert & ALERT.ATTENTION:

View File

@ -127,7 +127,7 @@ def _create_sbox(s):
return sbox
def _update_setting_item(sbox, value, is_active=True):
def _update_setting_item(sbox, value, is_online=True):
_, failed, spinner, control = sbox.get_children()
spinner.set_visible(False)
spinner.stop()
@ -135,7 +135,7 @@ def _update_setting_item(sbox, value, is_active=True):
# print ("update", control, "with new value", value)
if value is None:
control.set_sensitive(False)
failed.set_visible(is_active)
failed.set_visible(is_online)
return
failed.set_visible(False)

View File

@ -391,16 +391,19 @@ def _remove_receiver(receiver):
index += 1
def _update_menu_item(index, device_status):
def _update_menu_item(index, device):
assert device
assert device.status is not None
menu_items = _menu.get_children()
menu_item = menu_items[index]
level = device_status.get(_K.BATTERY_LEVEL)
charging = device_status.get(_K.BATTERY_CHARGING)
level = device.status.get(_K.BATTERY_LEVEL)
charging = device.status.get(_K.BATTERY_CHARGING)
icon_name = _icons.battery(level, charging)
image_widget = menu_item.get_image()
image_widget.set_sensitive(bool(device_status))
image_widget.set_sensitive(bool(device.online))
_update_menu_icon(image_widget, icon_name)
#
@ -455,17 +458,17 @@ def update(device=None):
else:
# peripheral
is_alive = device.status is not None
is_paired = bool(device)
receiver_path = device.receiver.path
index = None
for idx, (path, serial, name, _, _) in enumerate(_devices_info):
if path == receiver_path and serial == device.serial:
index = idx
if is_alive:
if is_paired:
if index is None:
index = _add_device(device)
_update_menu_item(index, device.status)
_update_menu_item(index, device)
else:
# was just unpaired
if index:

View File

@ -431,6 +431,7 @@ def _update_details(button):
assert button
visible = button.get_active()
device = _find_selected_device()
assert device
if visible:
_details._text.set_markup('<small>reading...</small>')
@ -465,6 +466,8 @@ def _update_details(button):
def _update_receiver_panel(receiver, panel, buttons, full=False):
assert receiver
devices_count = len(receiver)
if receiver.max_devices > 1:
if devices_count == 0:
@ -498,8 +501,9 @@ def _update_receiver_panel(receiver, panel, buttons, full=False):
def _update_device_panel(device, panel, buttons, full=False):
is_active = bool(device.status)
panel.set_sensitive(is_active)
assert device
is_online = bool(device.online)
panel.set_sensitive(is_online)
battery_level = device.status.get(_K.BATTERY_LEVEL)
if battery_level is None:
@ -515,15 +519,15 @@ def _update_device_panel(device, panel, buttons, full=False):
panel._battery._icon.set_sensitive(True)
text = '%d%%' % battery_level
if is_active:
if is_online:
if charging:
text += ' <small>(charging)</small>'
else:
text += ' <small>(last known)</small>'
panel._battery._text.set_sensitive(is_active)
panel._battery._text.set_sensitive(is_online)
panel._battery._text.set_markup(text)
if is_active:
if is_online:
not_secure = device.status.get(_K.LINK_ENCRYPTED) == False
if not_secure:
panel._secure._text.set_text('not encrypted')
@ -539,7 +543,7 @@ def _update_device_panel(device, panel, buttons, full=False):
panel._secure._icon.set_visible(False)
panel._secure.set_tooltip_text('')
if is_active:
if is_online:
light_level = device.status.get(_K.LIGHT_LEVEL)
if light_level is None:
panel._lux.set_visible(False)
@ -557,7 +561,7 @@ def _update_device_panel(device, panel, buttons, full=False):
panel.set_visible(True)
if full:
_config_panel.update(panel._config, device, is_active)
_config_panel.update(device, is_online)
def _update_info_panel(device, full=False):
@ -567,19 +571,24 @@ def _update_info_panel(device, full=False):
_empty.set_visible(True)
return
is_active = bool(device.status)
# a receiver must be valid
# a device must be paired
assert device
_info._title.set_markup('<b>%s</b>' % device.name)
_info._title.set_sensitive(is_active)
icon_name = _icons.device_icon_name(device.name, device.kind)
_info._icon.set_from_icon_name(icon_name, _DEVICE_ICON_SIZE)
_info._icon.set_sensitive(is_active)
if device.kind is None:
_info._device.set_visible(False)
_info._icon.set_sensitive(True)
_info._title.set_sensitive(True)
_update_receiver_panel(device, _info._receiver, _info._buttons, full)
else:
_info._receiver.set_visible(False)
is_online = bool(device.online)
_info._icon.set_sensitive(is_online)
_info._title.set_sensitive(is_online)
_update_device_panel(device, _info._device, _info._buttons, full)
_empty.set_visible(False)
@ -664,10 +673,16 @@ def update(device, need_popup=False):
else:
# peripheral
is_alive = device.status is not None
item = _device_row(device.receiver.path, device.serial, device if is_alive else None)
if is_alive and item:
_model.set_value(item, _COLUMN.ACTIVE, bool(device.status))
is_paired = bool(device)
assert device.receiver
assert device.serial
item = _device_row(device.receiver.path, device.serial, device if is_paired else None)
if is_paired and item:
was_online = _model.get_value(item, _COLUMN.ACTIVE)
is_online = bool(device.online)
_model.set_value(item, _COLUMN.ACTIVE, is_online)
battery_level = device.status.get(_K.BATTERY_LEVEL)
if battery_level is None:
_model.set_value(item, _COLUMN.STATUS_ICON, '')
@ -679,7 +694,8 @@ def update(device, need_popup=False):
if selected_device_id is None:
select(device.receiver.path, device.serial)
elif selected_device_id == device.serial:
_update_info_panel(device, need_popup)
full_update = need_popup or was_online != is_online
_update_info_panel(device, full=full_update)
elif item:
_model.remove(item)