group all status keys into one object

This commit is contained in:
Daniel Pavel 2013-06-19 19:45:39 +02:00
parent 2fee88e54b
commit a806f2672d
3 changed files with 56 additions and 64 deletions

View File

@ -30,14 +30,15 @@ from . import hidpp20 as _hidpp20
ALERT = _NamedInts(NONE=0x00, NOTIFICATION=0x01, SHOW_WINDOW=0x02, ATTENTION=0x04, ALL=0xFF) ALERT = _NamedInts(NONE=0x00, NOTIFICATION=0x01, SHOW_WINDOW=0x02, ATTENTION=0x04, ALL=0xFF)
# device properties that may be reported KEYS = _NamedInts(
ENCRYPTED='encrypted' BATTERY_LEVEL=1,
BATTERY_LEVEL='battery-level' BATTERY_CHARGING=2,
BATTERY_STATUS='battery-status' BATTERY_STATUS=3,
BATTERY_CHARGING='battery-charging' LIGHT_LEVEL=4,
LIGHT_LEVEL='light-level' LINK_ENCRYPTED=5,
ERROR='error' NOTIFICATION_FLAGS=6,
NOTIFICATIONS='notifications' ERROR=7,
)
# If the battery charge is under this percentage, trigger an attention event # If the battery charge is under this percentage, trigger an attention event
# (blink systray icon/notification/whatever). # (blink systray icon/notification/whatever).
@ -67,8 +68,8 @@ class ReceiverStatus(dict):
self.lock_open = False self.lock_open = False
self.new_device = None self.new_device = None
self[ERROR] = None
self[NOTIFICATIONS] = _hidpp10.get_notification_flags(receiver) self[NOTIFICATIONS] = _hidpp10.get_notification_flags(receiver)
self[KEYS.ERROR] = None
def __str__(self): def __str__(self):
count = len(self._receiver) count = len(self._receiver)
@ -92,7 +93,7 @@ class ReceiverStatus(dict):
r.serial, r.firmware, None r.serial, r.firmware, None
# r.enable_notifications() # r.enable_notifications()
self[NOTIFICATIONS] = _hidpp10.get_notification_flags(r) self[KEYS.NOTIFICATION_FLAGS] = _hidpp10.get_notification_flags(r)
def process_notification(self, n): def process_notification(self, n):
if n.sub_id == 0x4A: if n.sub_id == 0x4A:
@ -100,15 +101,15 @@ class ReceiverStatus(dict):
reason = 'pairing lock is ' + ('open' if self.lock_open else 'closed') reason = 'pairing lock is ' + ('open' if self.lock_open else 'closed')
_log.info("%s: %s", self._receiver, reason) _log.info("%s: %s", self._receiver, reason)
self[ERROR] = None self[KEYS.ERROR] = None
if self.lock_open: if self.lock_open:
self.new_device = None self.new_device = None
pair_error = ord(n.data[:1]) pair_error = ord(n.data[:1])
if pair_error: if pair_error:
self[ERROR] = _hidpp10.PAIRING_ERRORS[pair_error] self[KEYS.ERROR] = error_string = _hidpp10.PAIRING_ERRORS[pair_error]
self.new_device = None self.new_device = None
_log.warn("pairing error %d: %s", pair_error, self[ERROR]) _log.warn("pairing error %d: %s", pair_error, error_string)
self._changed(reason=reason) self._changed(reason=reason)
return True return True
@ -145,14 +146,14 @@ class DeviceStatus(dict):
return format % value return format % value
def _items(): def _items():
battery_level = _item(BATTERY_LEVEL, 'Battery: %d%%') battery_level = _item(KEYS.BATTERY_LEVEL, 'Battery: %d%%')
if battery_level: if battery_level:
yield battery_level yield battery_level
battery_status = _item(BATTERY_STATUS, ' (%s)') battery_status = _item(KEYS.BATTERY_STATUS, ' (%s)')
if battery_status: if battery_status:
yield battery_status yield battery_status
light_level = _item(LIGHT_LEVEL, 'Light: %d lux') light_level = _item(KEYS.LIGHT_LEVEL, 'Light: %d lux')
if light_level: if light_level:
if battery_level: if battery_level:
yield ', ' yield ', '
@ -171,11 +172,11 @@ class DeviceStatus(dict):
_log.debug("%s: battery %d%%, %s", self._device, level, status) _log.debug("%s: battery %d%%, %s", self._device, level, status)
# TODO: this is also executed when pressing Fn+F7 on K800. # TODO: this is also executed when pressing Fn+F7 on K800.
old_level, self[BATTERY_LEVEL] = self.get(BATTERY_LEVEL), level old_level, self[KEYS.BATTERY_LEVEL] = self.get(KEYS.BATTERY_LEVEL), level
old_status, self[BATTERY_STATUS] = self.get(BATTERY_STATUS), status old_status, self[KEYS.BATTERY_STATUS] = self.get(KEYS.BATTERY_STATUS), status
charging = status in ('charging', 'recharging', 'slow recharge') charging = status in ('charging', 'recharging', 'slow recharge')
old_charging, self[BATTERY_CHARGING] = self.get(BATTERY_CHARGING), charging old_charging, self[KEYS.BATTERY_CHARGING] = self.get(KEYS.BATTERY_CHARGING), charging
changed = old_level != level or old_status != status or old_charging != charging changed = old_level != level or old_status != status or old_charging != charging
alert, reason = ALERT.NONE, None alert, reason = ALERT.NONE, None
@ -207,9 +208,9 @@ class DeviceStatus(dict):
if battery: if battery:
level, status = battery level, status = battery
self.set_battery_info(level, status, timestamp=timestamp) self.set_battery_info(level, status, timestamp=timestamp)
elif BATTERY_STATUS in self: elif KEYS.BATTERY_STATUS in self:
self[BATTERY_STATUS] = None self[KEYS.BATTERY_STATUS] = None
self[BATTERY_CHARGING] = None self[KEYS.BATTERY_CHARGING] = None
self._changed() self._changed()
def _changed(self, active=True, alert=ALERT.NONE, reason=None, timestamp=None): def _changed(self, active=True, alert=ALERT.NONE, reason=None, timestamp=None):
@ -222,18 +223,17 @@ class DeviceStatus(dict):
# Make sure to set notification flags on the device, they # Make sure to set notification flags on the device, they
# get cleared when the device is turned off (but not when the device # get cleared when the device is turned off (but not when the device
# goes idle, and we can't tell the difference right now). # goes idle, and we can't tell the difference right now).
self[NOTIFICATIONS] = d.enable_notifications() self[KEYS.NOTIFICATION_FLAGS] = d.enable_notifications()
if self.configuration: if self.configuration:
self.configuration.attach_to(d) self.configuration.attach_to(d)
else: else:
if was_active: if was_active:
battery = self.get(BATTERY_LEVEL) battery = self.get(KEYS.BATTERY_LEVEL)
self.clear() self.clear()
# If we had a known battery level before, assume it's not going # If we had a known battery level before, assume it's not going
# to change much while the device is offline. # to change much while the device is offline.
if battery is not None: if battery is not None:
self[BATTERY_LEVEL] = battery self[KEYS.BATTERY_LEVEL] = battery
if self.updated == 0 and active: if self.updated == 0 and active:
# if the device is active on the very first status notification, # if the device is active on the very first status notification,
@ -272,7 +272,7 @@ class DeviceStatus(dict):
self._changed(active=False, reason='out of range') self._changed(active=False, reason='out of range')
# if still active, make sure we know the battery level # if still active, make sure we know the battery level
if BATTERY_LEVEL not in self: if KEYS.BATTERY_LEVEL not in self:
self.read_battery(timestamp) self.read_battery(timestamp)
elif timestamp - self.updated > _STATUS_TIMEOUT: elif timestamp - self.updated > _STATUS_TIMEOUT:
@ -350,7 +350,7 @@ class DeviceStatus(dict):
has_payload = bool(flags & 0x80) has_payload = bool(flags & 0x80)
_log.debug("%s: %s connection notification: software=%s, encrypted=%s, link=%s, payload=%s", _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._device, protocol_name, sw_present, link_encrypyed, link_established, has_payload)
self[ENCRYPTED] = link_encrypyed self[KEYS.LINK_ENCRYPTED] = link_encrypyed
self._changed(link_established) self._changed(link_established)
if protocol_name == 'eQuad': if protocol_name == 'eQuad':
@ -363,7 +363,7 @@ class DeviceStatus(dict):
_log.warn("%s: connection notification with unknown protocol %02X: %s", self._device.number, n.address, n) _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 the device just came online, read the battery charge
if self._active and BATTERY_LEVEL not in self: if self._active and KEYS.BATTERY_LEVEL not in self:
self.read_battery() self.read_battery()
return True return True
@ -420,16 +420,16 @@ class DeviceStatus(dict):
if feature == _hidpp20.FEATURE.SOLAR_DASHBOARD: if feature == _hidpp20.FEATURE.SOLAR_DASHBOARD:
if n.data[5:9] == b'GOOD': if n.data[5:9] == b'GOOD':
charge, lux, adc = _unpack('!BHH', n.data[:5]) charge, lux, adc = _unpack('!BHH', n.data[:5])
self[BATTERY_LEVEL] = charge self[KEYS.BATTERY_LEVEL] = charge
# guesstimate the battery voltage, emphasis on 'guess' # guesstimate the battery voltage, emphasis on 'guess'
self[BATTERY_STATUS] = '%1.2fV' % (adc * 2.67793237653 / 0x0672) self[KEYS.BATTERY_STATUS] = '%1.2fV' % (adc * 2.67793237653 / 0x0672)
if n.address == 0x00: if n.address == 0x00:
self[LIGHT_LEVEL] = None self[KEYS.LIGHT_LEVEL] = None
self[BATTERY_CHARGING] = None self[KEYS.BATTERY_CHARGING] = None
self._changed() self._changed()
elif n.address == 0x10: elif n.address == 0x10:
self[LIGHT_LEVEL] = lux self[KEYS.LIGHT_LEVEL] = lux
self[BATTERY_CHARGING] = lux > 200 self[KEYS.BATTERY_CHARGING] = lux > 200
self._changed() self._changed()
elif n.address == 0x20: elif n.address == 0x20:
_log.debug("%s: Light Check button pressed", self._device) _log.debug("%s: Light Check button pressed", self._device)

View File

@ -14,15 +14,13 @@ from gi.repository import Gtk, GLib
from gi.repository.Gdk import ScrollDirection from gi.repository.Gdk import ScrollDirection
from solaar import NAME from solaar import NAME
from logitech.unifying_receiver.status import ( from logitech.unifying_receiver.status import KEYS as _K
BATTERY_LEVEL as _BATTERY_LEVEL,
BATTERY_CHARGING as _BATTERY_CHARGING,
)
from . import icons as _icons from . import icons as _icons
from .window import ( from .window import popup as _window_popup, toggle as _window_toggle
popup as _window_popup,
toggle as _window_toggle #
) # constants
#
_TRAY_ICON_SIZE = 32 # pixels _TRAY_ICON_SIZE = 32 # pixels
_MENU_ICON_SIZE = Gtk.IconSize.LARGE_TOOLBAR _MENU_ICON_SIZE = Gtk.IconSize.LARGE_TOOLBAR
@ -159,8 +157,8 @@ try:
def _update_tray_icon(): def _update_tray_icon():
if _picked_device: if _picked_device:
_, _, name, _, device_status = _picked_device _, _, name, _, device_status = _picked_device
battery_level = device_status.get(_BATTERY_LEVEL) battery_level = device_status.get(_K.BATTERY_LEVEL)
battery_charging = device_status.get(_BATTERY_CHARGING) battery_charging = device_status.get(_K.BATTERY_CHARGING)
tray_icon_name = _icons.battery(battery_level, battery_charging) tray_icon_name = _icons.battery(battery_level, battery_charging)
description = '%s: %s' % (name, device_status) description = '%s: %s' % (name, device_status)
@ -217,8 +215,8 @@ except ImportError:
if _picked_device: if _picked_device:
_, _, name, _, device_status = _picked_device _, _, name, _, device_status = _picked_device
battery_level = device_status.get(_BATTERY_LEVEL) battery_level = device_status.get(_K.BATTERY_LEVEL)
battery_charging = device_status.get(_BATTERY_CHARGING) battery_charging = device_status.get(_K.BATTERY_CHARGING)
tray_icon_name = _icons.battery(battery_level, battery_charging) tray_icon_name = _icons.battery(battery_level, battery_charging)
else: else:
# there may be a receiver, but no peripherals # there may be a receiver, but no peripherals
@ -290,7 +288,7 @@ def _pick_device_with_lowest_battery():
for info in _devices_info: for info in _devices_info:
if info[1] is None: # is receiver/separator if info[1] is None: # is receiver/separator
continue continue
level = info[-1].get(_BATTERY_LEVEL) level = info[-1].get(_K.BATTERY_LEVEL)
if not picked or (level is not None and picked_level > level): if not picked or (level is not None and picked_level > level):
picked = info picked = info
picked_level = level or 0 picked_level = level or 0
@ -399,8 +397,8 @@ def _update_menu_item(index, device_status):
menu_items = _menu.get_children() menu_items = _menu.get_children()
menu_item = menu_items[index] menu_item = menu_items[index]
level = device_status.get(_BATTERY_LEVEL) level = device_status.get(_K.BATTERY_LEVEL)
charging = device_status.get(_BATTERY_CHARGING) charging = device_status.get(_K.BATTERY_CHARGING)
icon_name = _icons.battery(level, charging) icon_name = _icons.battery(level, charging)
image_widget = menu_item.get_image() image_widget = menu_item.get_image()

View File

@ -15,13 +15,7 @@ from solaar import NAME
# from solaar import __version__ as VERSION # from solaar import __version__ as VERSION
from logitech.unifying_receiver import hidpp10 as _hidpp10 from logitech.unifying_receiver import hidpp10 as _hidpp10
from logitech.unifying_receiver.common import NamedInts as _NamedInts from logitech.unifying_receiver.common import NamedInts as _NamedInts
from logitech.unifying_receiver.status import ( from logitech.unifying_receiver.status import KEYS as _K
BATTERY_LEVEL as _BATTERY_LEVEL,
BATTERY_CHARGING as _BATTERY_CHARGING,
LIGHT_LEVEL as _LIGHT_LEVEL,
ENCRYPTED as _ENCRYPTED,
NOTIFICATIONS as _NOTFITICATIONS,
)
from . import config_panel as _config_panel from . import config_panel as _config_panel
from . import action as _action, icons as _icons from . import action as _action, icons as _icons
from .about import show_window as _show_about_window from .about import show_window as _show_about_window
@ -454,7 +448,7 @@ def _update_details(button):
for fw in list(device.firmware): for fw in list(device.firmware):
yield (fw.kind, (fw.name + ' ' + fw.version).strip()) yield (fw.kind, (fw.name + ' ' + fw.version).strip())
flag_bits = device.status.get(_NOTFITICATIONS) flag_bits = device.status.get(_K.NOTIFICATION_FLAGS)
if flag_bits is not None: if flag_bits is not None:
flag_names = ('(none)',) if flag_bits == 0 else _hidpp10.NOTIFICATION_FLAG.flag_names(flag_bits) flag_names = ('(none)',) if flag_bits == 0 else _hidpp10.NOTIFICATION_FLAG.flag_names(flag_bits)
yield ('Notifications', ('\n%16s' % ' ').join(flag_names)) yield ('Notifications', ('\n%16s' % ' ').join(flag_names))
@ -503,7 +497,7 @@ def _update_device_panel(device, panel, buttons, full=False):
is_active = bool(device.status) is_active = bool(device.status)
panel.set_sensitive(is_active) panel.set_sensitive(is_active)
battery_level = device.status.get(_BATTERY_LEVEL) battery_level = device.status.get(_K.BATTERY_LEVEL)
if battery_level is None: if battery_level is None:
icon_name = _icons.battery() icon_name = _icons.battery()
panel._battery._icon.set_sensitive(False) panel._battery._icon.set_sensitive(False)
@ -511,7 +505,7 @@ def _update_device_panel(device, panel, buttons, full=False):
panel._battery._text.set_sensitive(True) panel._battery._text.set_sensitive(True)
panel._battery._text.set_markup('<small>unknown</small>') panel._battery._text.set_markup('<small>unknown</small>')
else: else:
charging = device.status.get(_BATTERY_CHARGING) charging = device.status.get(_K.BATTERY_CHARGING)
icon_name = _icons.battery(battery_level, charging) icon_name = _icons.battery(battery_level, charging)
panel._battery._icon.set_from_icon_name(icon_name, _INFO_ICON_SIZE) panel._battery._icon.set_from_icon_name(icon_name, _INFO_ICON_SIZE)
panel._battery._icon.set_sensitive(True) panel._battery._icon.set_sensitive(True)
@ -526,7 +520,7 @@ def _update_device_panel(device, panel, buttons, full=False):
panel._battery._text.set_markup(text) panel._battery._text.set_markup(text)
if is_active: if is_active:
not_secure = device.status.get(_ENCRYPTED) == False not_secure = device.status.get(_K.LINK_ENCRYPTED) == False
if not_secure: if not_secure:
panel._secure._text.set_text('not encrypted') panel._secure._text.set_text('not encrypted')
panel._secure._icon.set_from_icon_name('security-low', _INFO_ICON_SIZE) panel._secure._icon.set_from_icon_name('security-low', _INFO_ICON_SIZE)
@ -542,7 +536,7 @@ def _update_device_panel(device, panel, buttons, full=False):
panel._secure.set_tooltip_text('') panel._secure.set_tooltip_text('')
if is_active: if is_active:
light_level = device.status.get(_LIGHT_LEVEL) light_level = device.status.get(_K.LIGHT_LEVEL)
if light_level is None: if light_level is None:
panel._lux.set_visible(False) panel._lux.set_visible(False)
else: else:
@ -669,11 +663,11 @@ def update(device, need_popup=False):
item = _device_row(device.receiver.path, device.serial, device if is_alive else None) item = _device_row(device.receiver.path, device.serial, device if is_alive else None)
if is_alive and item: if is_alive and item:
_model.set_value(item, _COLUMN.ACTIVE, bool(device.status)) _model.set_value(item, _COLUMN.ACTIVE, bool(device.status))
battery_level = device.status.get(_BATTERY_LEVEL) battery_level = device.status.get(_K.BATTERY_LEVEL)
if battery_level is None: if battery_level is None:
_model.set_value(item, _COLUMN.STATUS_ICON, '') _model.set_value(item, _COLUMN.STATUS_ICON, '')
else: else:
charging = device.status.get(_BATTERY_CHARGING) charging = device.status.get(_K.BATTERY_CHARGING)
icon_name = _icons.battery(battery_level, charging) icon_name = _icons.battery(battery_level, charging)
_model.set_value(item, _COLUMN.STATUS_ICON, icon_name) _model.set_value(item, _COLUMN.STATUS_ICON, icon_name)