handle all 07/0D register notifications
This commit is contained in:
parent
55ca9927b0
commit
3ecfdd027e
|
|
@ -88,21 +88,26 @@ def get_battery(device):
|
||||||
|
|
||||||
reply = get_register(device, 'battery_charge', 0x0D)
|
reply = get_register(device, 'battery_charge', 0x0D)
|
||||||
if reply:
|
if reply:
|
||||||
charge = ord(reply[:1])
|
level = ord(reply[:1])
|
||||||
status = ord(reply[2:3]) & 0xF0
|
battery_status = ord(reply[2:3])
|
||||||
status = ('discharging' if status == 0x30
|
return parse_battery_reply_0D(level, battery_status)
|
||||||
else 'charging' if status == 0x50
|
|
||||||
else 'fully charged' if status == 0x90
|
|
||||||
else None)
|
|
||||||
return charge, status
|
|
||||||
|
|
||||||
reply = get_register(device, 'battery_status', 0x07)
|
reply = get_register(device, 'battery_status', 0x07)
|
||||||
if reply:
|
if reply:
|
||||||
level = ord(reply[:1])
|
level = ord(reply[:1])
|
||||||
battery_status = ord(reply[1:2])
|
battery_status = ord(reply[1:2])
|
||||||
return parse_battery_reply(level, battery_status)
|
return parse_battery_reply_07(level, battery_status)
|
||||||
|
|
||||||
def parse_battery_reply(level, battery_status):
|
def parse_battery_reply_0D(level, battery_status):
|
||||||
|
charge = level
|
||||||
|
status = battery_status & 0xF0
|
||||||
|
status = ('discharging' if status == 0x30
|
||||||
|
else 'charging' if status == 0x50
|
||||||
|
else 'fully charged' if status == 0x90
|
||||||
|
else None)
|
||||||
|
return charge, status
|
||||||
|
|
||||||
|
def parse_battery_reply_07(level, battery_status):
|
||||||
charge = (90 if level == 7 # full
|
charge = (90 if level == 7 # full
|
||||||
else 50 if level == 5 # good
|
else 50 if level == 5 # good
|
||||||
else 20 if level == 3 # low
|
else 20 if level == 3 # low
|
||||||
|
|
|
||||||
|
|
@ -124,11 +124,10 @@ class PairedDevice(object):
|
||||||
@property
|
@property
|
||||||
def firmware(self):
|
def firmware(self):
|
||||||
if self._firmware is None:
|
if self._firmware is None:
|
||||||
p = self.protocol
|
if self.protocol < 2.0:
|
||||||
if p >= 2.0:
|
|
||||||
self._firmware = _hidpp20.get_firmware(self)
|
|
||||||
if self._firmware is None and p == 1.0:
|
|
||||||
self._firmware = _hidpp10.get_firmware(self)
|
self._firmware = _hidpp10.get_firmware(self)
|
||||||
|
else:
|
||||||
|
self._firmware = _hidpp20.get_firmware(self)
|
||||||
return self._firmware or ()
|
return self._firmware or ()
|
||||||
|
|
||||||
@property
|
@property
|
||||||
|
|
|
||||||
|
|
@ -57,6 +57,7 @@ class ReceiverStatus(dict):
|
||||||
|
|
||||||
self.lock_open = False
|
self.lock_open = False
|
||||||
self.new_device = None
|
self.new_device = None
|
||||||
|
|
||||||
self[ERROR] = None
|
self[ERROR] = None
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
|
|
@ -75,8 +76,9 @@ class ReceiverStatus(dict):
|
||||||
self.lock_open = bool(n.address & 0x01)
|
self.lock_open = bool(n.address & 0x01)
|
||||||
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
|
||||||
if self.lock_open:
|
if self.lock_open:
|
||||||
self[ERROR] = None
|
|
||||||
self.new_device = None
|
self.new_device = None
|
||||||
|
|
||||||
pair_error = ord(n.data[:1])
|
pair_error = ord(n.data[:1])
|
||||||
|
|
@ -84,8 +86,6 @@ class ReceiverStatus(dict):
|
||||||
self[ERROR] = _hidpp10.PAIRING_ERRORS[pair_error]
|
self[ERROR] = _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, self[ERROR])
|
||||||
else:
|
|
||||||
self[ERROR] = None
|
|
||||||
|
|
||||||
self._changed(reason=reason)
|
self._changed(reason=reason)
|
||||||
return True
|
return True
|
||||||
|
|
@ -134,25 +134,22 @@ class DeviceStatus(dict):
|
||||||
__nonzero__ = __bool__
|
__nonzero__ = __bool__
|
||||||
|
|
||||||
def set_battery_info(self, level, status, timestamp=None):
|
def set_battery_info(self, level, status, timestamp=None):
|
||||||
|
if _log.isEnabledFor(_DEBUG):
|
||||||
|
_log.debug("%s: battery %d%% charged, %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.
|
||||||
# Modify this such that alerts/writes are only done when the
|
old_level, self[BATTERY_LEVEL] = self.get(BATTERY_LEVEL), level
|
||||||
# level/status actually changes.
|
old_status, self[BATTERY_STATUS] = self.get(BATTERY_STATUS), status
|
||||||
self[BATTERY_LEVEL] = level
|
changed = old_level != level or old_status != status
|
||||||
self[BATTERY_STATUS] = status
|
alert, reason = ALERT.NONE, None
|
||||||
error = None
|
|
||||||
if _hidpp20.BATTERY_OK(status):
|
if not _hidpp20.BATTERY_OK(status):
|
||||||
alert = ALERT.NONE
|
_log.warn("%s: battery %d%% charged, ALERT %s", self._device, level, status)
|
||||||
reason = self[ERROR] = None
|
alert = ALERT.NOTIFICATION
|
||||||
if _log.isEnabledFor(_DEBUG):
|
reason = status
|
||||||
_log.debug("%s: battery %d%% charged, %s", self._device, level, status)
|
|
||||||
else:
|
if changed or reason:
|
||||||
alert = ALERT.ALL
|
self._changed(alert=alert, reason=reason, timestamp=timestamp)
|
||||||
error = status
|
|
||||||
_log.warn("%s: battery %d%% charged, ALERT %s", self._device, level, error)
|
|
||||||
if error is not None:
|
|
||||||
# TODO: show visual warning/notif to user
|
|
||||||
self[ERROR] = error
|
|
||||||
self._changed(alert=alert, reason=error, timestamp=timestamp)
|
|
||||||
|
|
||||||
def read_battery(self, timestamp=None):
|
def read_battery(self, timestamp=None):
|
||||||
d = self._device
|
d = self._device
|
||||||
|
|
@ -169,7 +166,7 @@ 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)
|
||||||
elif BATTERY_STATUS in self:
|
elif BATTERY_STATUS in self:
|
||||||
self[BATTERY_STATUS] = None
|
self[BATTERY_STATUS] = None
|
||||||
self._changed(timestamp=timestamp)
|
self._changed(timestamp=timestamp)
|
||||||
|
|
@ -222,29 +219,35 @@ class DeviceStatus(dict):
|
||||||
return self._process_hidpp10_notification(n)
|
return self._process_hidpp10_notification(n)
|
||||||
|
|
||||||
# some custom battery events for HID++ 1.0 devices
|
# some custom battery events for HID++ 1.0 devices
|
||||||
if n.sub_id in (0x07, 0x0D) and len(n.data) == 3 and n.data[2:3] == b'\x00':
|
if self._device.protocol < 2.0:
|
||||||
# _log.debug("%s (%s) custom battery notification %s", self._device, self._device.protocol, n)
|
# README assuming HID++ 2.0 devices don't use the 0x07/0x0D registers
|
||||||
if self._device.protocol < 2:
|
# however, this has not been fully verified yet
|
||||||
|
if n.sub_id in (0x07, 0x0D) and len(n.data) == 3 and n.data[2:3] == b'\x00':
|
||||||
return self._process_hidpp10_custom_notification(n)
|
return self._process_hidpp10_custom_notification(n)
|
||||||
|
else:
|
||||||
|
# assuming 0x00 to 0x3F are feature (HID++ 2.0) notifications
|
||||||
|
try:
|
||||||
|
feature = self._device.features[n.sub_id]
|
||||||
|
except IndexError:
|
||||||
|
_log.warn("%s: notification from invalid feature index %02X: %s", self._device, n.sub_id, n)
|
||||||
|
return False
|
||||||
|
|
||||||
# assuming 0x00 to 0x3F are feature (HID++ 2.0) notifications
|
return self._process_feature_notification(n, feature)
|
||||||
try:
|
|
||||||
feature = self._device.features[n.sub_id]
|
|
||||||
except IndexError:
|
|
||||||
_log.warn("%s: notification from invalid feature index %02X: %s", self._device, n.sub_id, n)
|
|
||||||
return False
|
|
||||||
|
|
||||||
return self._process_feature_notification(n, feature)
|
|
||||||
|
|
||||||
def _process_hidpp10_custom_notification(self, n):
|
def _process_hidpp10_custom_notification(self, n):
|
||||||
|
if _log.isEnabledFor(_DEBUG):
|
||||||
|
_log.debug("%s (%s) custom battery notification %s", self._device, self._device.protocol, n)
|
||||||
|
|
||||||
if n.sub_id == 0x07:
|
if n.sub_id == 0x07:
|
||||||
# message layout: 10 ix 07("address") <LEVEL> <STATUS> 00 00
|
# message layout: 10 ix 07("address") <LEVEL> <STATUS> 00 00
|
||||||
level, status = _hidpp10.parse_battery_reply(n.address, ord(n.data[:1]))
|
level, status = _hidpp10.parse_battery_reply_07(n.address, ord(n.data[:1]))
|
||||||
self.set_battery_info(level, status)
|
self.set_battery_info(level, status)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
if n.sub_id == 0x0D:
|
if n.sub_id == 0x0D:
|
||||||
# TODO
|
# message layout: 10 ix 0D("address") <CHARGE> <?> <STATUS> 00
|
||||||
|
level, status = _hidpp10.parse_battery_reply_0D(n.address, ord(n.data[1:2]))
|
||||||
|
self.set_battery_info(level, status)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
_log.warn("%s: unrecognized %s", self._device, n)
|
_log.warn("%s: unrecognized %s", self._device, n)
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue