Refactor: Use dataclasses and enums
Replace unnecessary NamedInts in favour of default data types. Simplify interfaces by reducing possible input from strings to members of an enum.
This commit is contained in:
parent
469c04faaf
commit
c9dc232951
|
@ -18,8 +18,8 @@
|
|||
# Some common functions and types.
|
||||
|
||||
from binascii import hexlify as _hexlify
|
||||
from collections import namedtuple
|
||||
from dataclasses import dataclass
|
||||
from enum import IntEnum
|
||||
from typing import Optional
|
||||
from typing import Union
|
||||
|
||||
|
@ -28,15 +28,6 @@ import yaml as _yaml
|
|||
from solaar.i18n import _
|
||||
|
||||
|
||||
def is_string(d):
|
||||
return isinstance(d, str)
|
||||
|
||||
|
||||
#
|
||||
#
|
||||
#
|
||||
|
||||
|
||||
def crc16(data: bytes):
|
||||
"""
|
||||
CRC-16 (CCITT) implemented with a precomputed lookup table
|
||||
|
@ -314,7 +305,7 @@ class NamedInt(int):
|
|||
(case-insensitive)."""
|
||||
|
||||
def __new__(cls, value, name):
|
||||
assert is_string(name)
|
||||
assert isinstance(name, str)
|
||||
obj = int.__new__(cls, value)
|
||||
obj.name = str(name)
|
||||
return obj
|
||||
|
@ -329,7 +320,7 @@ class NamedInt(int):
|
|||
return int(self) == int(other) and self.name == other.name
|
||||
if isinstance(other, int):
|
||||
return int(self) == int(other)
|
||||
if is_string(other):
|
||||
if isinstance(other, str):
|
||||
return self.name.lower() == other.lower()
|
||||
# this should catch comparisons with bytes in Py3
|
||||
if other is not None:
|
||||
|
@ -430,7 +421,7 @@ class NamedInts:
|
|||
self._sort_values()
|
||||
return value
|
||||
|
||||
elif is_string(index):
|
||||
elif isinstance(index, str):
|
||||
if index in self.__dict__:
|
||||
return self.__dict__[index]
|
||||
return next((x for x in self._values if str(x) == index), None)
|
||||
|
@ -469,7 +460,7 @@ class NamedInts:
|
|||
if isinstance(name, NamedInt):
|
||||
assert int(index) == int(name), repr(index) + " " + repr(name)
|
||||
value = name
|
||||
elif is_string(name):
|
||||
elif isinstance(name, str):
|
||||
value = NamedInt(index, name)
|
||||
else:
|
||||
raise TypeError("name must be a string")
|
||||
|
@ -490,7 +481,7 @@ class NamedInts:
|
|||
return self[value] == value
|
||||
elif isinstance(value, int):
|
||||
return value in self._indexed
|
||||
elif is_string(value):
|
||||
elif isinstance(value, str):
|
||||
return value in self.__dict__ or value in self._values
|
||||
|
||||
def __iter__(self):
|
||||
|
@ -550,63 +541,81 @@ class KwException(Exception):
|
|||
return self.args[0].get(k) # was self.args[0][k]
|
||||
|
||||
|
||||
"""Firmware information."""
|
||||
FirmwareInfo = namedtuple("FirmwareInfo", ["kind", "name", "version", "extras"])
|
||||
@dataclass
|
||||
class FirmwareInfo:
|
||||
kind: str
|
||||
name: str
|
||||
version: str
|
||||
extras: str
|
||||
|
||||
|
||||
class BatteryStatus(IntEnum):
|
||||
DISCHARGING = 0x00
|
||||
RECHARGING = 0x01
|
||||
ALMOST_FULL = 0x02
|
||||
FULL = 0x03
|
||||
SLOW_RECHARGE = 0x04
|
||||
INVALID_BATTERY = 0x05
|
||||
THERMAL_ERROR = 0x06
|
||||
|
||||
|
||||
class BatteryLevelApproximation(IntEnum):
|
||||
EMPTY = 0
|
||||
CRITICAL = 5
|
||||
LOW = 20
|
||||
GOOD = 50
|
||||
FULL = 90
|
||||
|
||||
|
||||
@dataclass
|
||||
class Battery:
|
||||
"""Information about the current state of a battery"""
|
||||
|
||||
level: Optional[Union[NamedInt, int]]
|
||||
ATTENTION_LEVEL = 5
|
||||
|
||||
level: Optional[Union[BatteryLevelApproximation, int]]
|
||||
next_level: Optional[Union[NamedInt, int]]
|
||||
status: Optional[NamedInt]
|
||||
status: Optional[BatteryStatus]
|
||||
voltage: Optional[int]
|
||||
light_level: Optional[int] = None # light level for devices with solaar recharging
|
||||
|
||||
def __post_init__(self):
|
||||
if self.level is None: # infer level from status if needed and possible
|
||||
if self.status == Battery.STATUS.full:
|
||||
self.level = Battery.APPROX.full
|
||||
elif self.status in (Battery.STATUS.almost_full, Battery.STATUS.recharging):
|
||||
self.level = Battery.APPROX.good
|
||||
elif self.status == Battery.STATUS.slow_recharge:
|
||||
self.level = Battery.APPROX.low
|
||||
if self.status == BatteryStatus.FULL:
|
||||
self.level = BatteryLevelApproximation.FULL
|
||||
elif self.status in (BatteryStatus.ALMOST_FULL, BatteryStatus.RECHARGING):
|
||||
self.level = BatteryLevelApproximation.GOOD
|
||||
elif self.status == BatteryStatus.SLOW_RECHARGE:
|
||||
self.level = BatteryLevelApproximation.LOW
|
||||
|
||||
STATUS = NamedInts(
|
||||
discharging=0x00,
|
||||
recharging=0x01,
|
||||
almost_full=0x02,
|
||||
full=0x03,
|
||||
slow_recharge=0x04,
|
||||
invalid_battery=0x05,
|
||||
thermal_error=0x06,
|
||||
)
|
||||
|
||||
APPROX = NamedInts(empty=0, critical=5, low=20, good=50, full=90)
|
||||
|
||||
ATTENTION_LEVEL = 5
|
||||
|
||||
def ok(self):
|
||||
return self.status not in (Battery.STATUS.invalid_battery, Battery.STATUS.thermal_error) and (
|
||||
def ok(self) -> bool:
|
||||
return self.status not in (BatteryStatus.INVALID_BATTERY, BatteryStatus.THERMAL_ERROR) and (
|
||||
self.level is None or self.level > Battery.ATTENTION_LEVEL
|
||||
)
|
||||
|
||||
def charging(self):
|
||||
def charging(self) -> bool:
|
||||
return self.status in (
|
||||
Battery.STATUS.recharging,
|
||||
Battery.STATUS.almost_full,
|
||||
Battery.STATUS.full,
|
||||
Battery.STATUS.slow_recharge,
|
||||
BatteryStatus.RECHARGING,
|
||||
BatteryStatus.ALMOST_FULL,
|
||||
BatteryStatus.FULL,
|
||||
BatteryStatus.SLOW_RECHARGE,
|
||||
)
|
||||
|
||||
def to_str(self):
|
||||
if isinstance(self.level, NamedInt):
|
||||
return _("Battery: %(level)s (%(status)s)") % {"level": _(self.level), "status": _(self.status)}
|
||||
def to_str(self) -> str:
|
||||
if isinstance(self.level, BatteryLevelApproximation):
|
||||
level = self.level.name.lower()
|
||||
status = self.status.name.lower().replace("_", " ")
|
||||
return _("Battery: %(level)s (%(status)s)") % {"level": _(level), "status": _(status)}
|
||||
elif isinstance(self.level, int):
|
||||
return _("Battery: %(percent)d%% (%(status)s)") % {"percent": self.level, "status": _(self.status)}
|
||||
status = self.status.name.lower().replace("_", " ")
|
||||
return _("Battery: %(percent)d%% (%(status)s)") % {"percent": self.level, "status": _(status)}
|
||||
else:
|
||||
return ""
|
||||
|
||||
|
||||
ALERT = NamedInts(NONE=0x00, NOTIFICATION=0x01, SHOW_WINDOW=0x02, ATTENTION=0x04, ALL=0xFF)
|
||||
class Alert(IntEnum):
|
||||
NONE = 0x00
|
||||
NOTIFICATION = 0x01
|
||||
SHOW_WINDOW = 0x02
|
||||
ATTENTION = 0x04
|
||||
ALL = 0xFF
|
||||
|
|
|
@ -34,7 +34,7 @@ from . import hidpp10_constants
|
|||
from . import hidpp20
|
||||
from . import hidpp20_constants
|
||||
from . import settings
|
||||
from .common import ALERT
|
||||
from .common import Alert
|
||||
from .common import Battery
|
||||
from .settings_templates import check_feature_settings as _check_feature_settings
|
||||
|
||||
|
@ -375,11 +375,11 @@ class Device:
|
|||
if old_info is None:
|
||||
old_info = Battery(None, None, None, None)
|
||||
|
||||
alert, reason = ALERT.NONE, None
|
||||
alert, reason = Alert.NONE, None
|
||||
if not info.ok():
|
||||
logger.warning("%s: battery %d%%, ALERT %s", self, info.level, info.status)
|
||||
if old_info.status != info.status:
|
||||
alert = ALERT.NOTIFICATION | ALERT.ATTENTION
|
||||
alert = Alert.NOTIFICATION | Alert.ATTENTION
|
||||
reason = info.to_str()
|
||||
|
||||
if changed or reason:
|
||||
|
@ -393,7 +393,7 @@ class Device:
|
|||
battery = self.battery()
|
||||
self.set_battery_info(battery if battery is not None else Battery(None, None, None, None))
|
||||
|
||||
def changed(self, active=None, alert=ALERT.NONE, reason=None, push=False):
|
||||
def changed(self, active=None, alert=Alert.NONE, reason=None, push=False):
|
||||
"""The status of the device had changed, so invoke the status callback.
|
||||
Also push notifications and settings to the device when necessary."""
|
||||
if active is not None:
|
||||
|
|
|
@ -22,7 +22,7 @@ from typing import Any
|
|||
from typing_extensions import Protocol
|
||||
|
||||
from .common import Battery
|
||||
from .common import BatteryChargeApproximation
|
||||
from .common import BatteryLevelApproximation
|
||||
from .common import BatteryStatus
|
||||
from .common import FirmwareInfo as _FirmwareInfo
|
||||
from .common import bytes2int as _bytes2int
|
||||
|
@ -158,17 +158,17 @@ class Hidpp10:
|
|||
return
|
||||
|
||||
if battery_level is not None:
|
||||
if battery_level < BatteryChargeApproximation.CRITICAL:
|
||||
if battery_level < BatteryLevelApproximation.CRITICAL:
|
||||
# 1 orange, and force blink
|
||||
v1, v2 = 0x22, 0x00
|
||||
warning = True
|
||||
elif battery_level < BatteryChargeApproximation.LOW:
|
||||
elif battery_level < BatteryLevelApproximation.LOW:
|
||||
# 1 orange
|
||||
v1, v2 = 0x22, 0x00
|
||||
elif battery_level < BatteryChargeApproximation.GOOD:
|
||||
elif battery_level < BatteryLevelApproximation.GOOD:
|
||||
# 1 green
|
||||
v1, v2 = 0x20, 0x00
|
||||
elif battery_level < BatteryChargeApproximation.FULL:
|
||||
elif battery_level < BatteryLevelApproximation.FULL:
|
||||
# 2 greens
|
||||
v1, v2 = 0x20, 0x02
|
||||
else:
|
||||
|
@ -228,18 +228,18 @@ class Hidpp10:
|
|||
|
||||
|
||||
def parse_battery_status(register, reply) -> Battery | None:
|
||||
def status_byte_to_charge(status_byte_: int) -> BatteryChargeApproximation:
|
||||
def status_byte_to_charge(status_byte_: int) -> BatteryLevelApproximation:
|
||||
if status_byte_ == 7:
|
||||
charge_ = BatteryChargeApproximation.FULL
|
||||
charge_ = BatteryLevelApproximation.FULL
|
||||
elif status_byte_ == 5:
|
||||
charge_ = BatteryChargeApproximation.GOOD
|
||||
charge_ = BatteryLevelApproximation.GOOD
|
||||
elif status_byte_ == 3:
|
||||
charge_ = BatteryChargeApproximation.LOW
|
||||
charge_ = BatteryLevelApproximation.LOW
|
||||
elif status_byte_ == 1:
|
||||
charge_ = BatteryChargeApproximation.CRITICAL
|
||||
charge_ = BatteryLevelApproximation.CRITICAL
|
||||
else:
|
||||
# pure 'charging' notifications may come without a status
|
||||
charge_ = BatteryChargeApproximation.EMPTY
|
||||
charge_ = BatteryLevelApproximation.EMPTY
|
||||
return charge_
|
||||
|
||||
def status_byte_to_battery_status(status_byte_: int) -> BatteryStatus:
|
||||
|
|
|
@ -21,8 +21,10 @@ import threading as _threading
|
|||
|
||||
from struct import pack as _pack
|
||||
from struct import unpack as _unpack
|
||||
from typing import Any
|
||||
from typing import List
|
||||
from typing import Optional
|
||||
from typing import Tuple
|
||||
|
||||
import yaml as _yaml
|
||||
|
||||
|
@ -33,6 +35,8 @@ from . import exceptions
|
|||
from . import hidpp10_constants as _hidpp10_constants
|
||||
from . import special_keys
|
||||
from .common import Battery
|
||||
from .common import BatteryLevelApproximation
|
||||
from .common import BatteryStatus
|
||||
from .common import FirmwareInfo as _FirmwareInfo
|
||||
from .common import NamedInt as _NamedInt
|
||||
from .common import NamedInts as _NamedInts
|
||||
|
@ -51,6 +55,8 @@ from .hidpp20_constants import GESTURE
|
|||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
FixedBytes5 = bytes
|
||||
|
||||
KIND_MAP = {kind: _hidpp10_constants.DEVICE_KIND[str(kind)] for kind in DEVICE_KIND}
|
||||
|
||||
|
||||
|
@ -1747,34 +1753,41 @@ battery_functions = {
|
|||
}
|
||||
|
||||
|
||||
def decipher_battery_status(report):
|
||||
discharge, next, status = _unpack("!BBB", report[:3])
|
||||
discharge = None if discharge == 0 else discharge
|
||||
status = Battery.STATUS[status]
|
||||
def decipher_battery_status(report: FixedBytes5) -> Tuple[Any, Battery]:
|
||||
battery_discharge_level, battery_discharge_next_level, battery_status = _unpack("!BBB", report[:3])
|
||||
if battery_discharge_level == 0:
|
||||
battery_discharge_level = None
|
||||
try:
|
||||
status = BatteryStatus(battery_status)
|
||||
except ValueError:
|
||||
status = None
|
||||
logger.debug(f"Unknown battery status byte 0x{battery_status:02X}")
|
||||
if logger.isEnabledFor(logging.DEBUG):
|
||||
logger.debug("battery status %s%% charged, next %s%%, status %s", discharge, next, status)
|
||||
return FEATURE.BATTERY_STATUS, Battery(discharge, next, status, None)
|
||||
logger.debug(
|
||||
"battery status %s%% charged, next %s%%, status %s", battery_discharge_level, battery_discharge_next_level, status
|
||||
)
|
||||
return FEATURE.BATTERY_STATUS, Battery(battery_discharge_level, battery_discharge_next_level, status, None)
|
||||
|
||||
|
||||
def decipher_battery_voltage(report):
|
||||
voltage, flags = _unpack(">HB", report[:3])
|
||||
status = Battery.STATUS.discharging
|
||||
status = BatteryStatus.DISCHARGING
|
||||
charge_sts = ERROR.unknown
|
||||
charge_lvl = CHARGE_LEVEL.average
|
||||
charge_type = CHARGE_TYPE.standard
|
||||
if flags & (1 << 7):
|
||||
status = Battery.STATUS.recharging
|
||||
status = BatteryStatus.RECHARGING
|
||||
charge_sts = CHARGE_STATUS[flags & 0x03]
|
||||
if charge_sts is None:
|
||||
charge_sts = ERROR.unknown
|
||||
elif charge_sts == CHARGE_STATUS.full:
|
||||
charge_lvl = CHARGE_LEVEL.full
|
||||
status = Battery.STATUS.full
|
||||
status = BatteryStatus.FULL
|
||||
if flags & (1 << 3):
|
||||
charge_type = CHARGE_TYPE.fast
|
||||
elif flags & (1 << 4):
|
||||
charge_type = CHARGE_TYPE.slow
|
||||
status = Battery.STATUS.slow_recharge
|
||||
status = BatteryStatus.SLOW_RECHARGE
|
||||
elif flags & (1 << 5):
|
||||
charge_lvl = CHARGE_LEVEL.critical
|
||||
for level in battery_voltage_remaining:
|
||||
|
@ -1795,21 +1808,26 @@ def decipher_battery_voltage(report):
|
|||
|
||||
|
||||
def decipher_battery_unified(report):
|
||||
discharge, level, status, _ignore = _unpack("!BBBB", report[:4])
|
||||
status = Battery.STATUS[status]
|
||||
discharge, level, status_byte, _ignore = _unpack("!BBBB", report[:4])
|
||||
try:
|
||||
status = BatteryStatus(status_byte)
|
||||
except ValueError:
|
||||
status = None
|
||||
logger.debug(f"Unknown battery status byte 0x{status_byte:02X}")
|
||||
if logger.isEnabledFor(logging.DEBUG):
|
||||
logger.debug("battery unified %s%% charged, level %s, charging %s", discharge, level, status)
|
||||
level = (
|
||||
Battery.APPROX.full
|
||||
if level == 8 # full
|
||||
else Battery.APPROX.good
|
||||
if level == 4 # good
|
||||
else Battery.APPROX.low
|
||||
if level == 2 # low
|
||||
else Battery.APPROX.critical
|
||||
if level == 1 # critical
|
||||
else Battery.APPROX.empty
|
||||
)
|
||||
|
||||
if level == 8:
|
||||
level = BatteryLevelApproximation.FULL
|
||||
elif level == 4:
|
||||
level = BatteryLevelApproximation.GOOD
|
||||
elif level == 2:
|
||||
level = BatteryLevelApproximation.LOW
|
||||
elif level == 1:
|
||||
level = BatteryLevelApproximation.CRITICAL
|
||||
else:
|
||||
level = BatteryLevelApproximation.EMPTY
|
||||
|
||||
return FEATURE.UNIFIED_BATTERY, Battery(discharge if discharge else level, None, status, None)
|
||||
|
||||
|
||||
|
@ -1821,5 +1839,5 @@ def decipher_adc_measurement(report):
|
|||
charge_level = level[1]
|
||||
break
|
||||
if flags & 0x01:
|
||||
status = Battery.STATUS.recharging if flags & 0x02 else Battery.STATUS.discharging
|
||||
status = BatteryStatus.RECHARGING if flags & 0x02 else BatteryStatus.DISCHARGING
|
||||
return FEATURE.ADC_MEASUREMENT, Battery(charge_level, None, status, adc)
|
||||
|
|
|
@ -31,8 +31,9 @@ from . import hidpp20
|
|||
from . import hidpp20_constants as _hidpp20_constants
|
||||
from . import settings_templates as _st
|
||||
from .base import DJ_MESSAGE_ID as _DJ_MESSAGE_ID
|
||||
from .common import ALERT as _ALERT
|
||||
from .common import Alert
|
||||
from .common import Battery as _Battery
|
||||
from .common import BatteryStatus
|
||||
from .common import strhex as _strhex
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
@ -203,7 +204,7 @@ def _process_dj_notification(device, n):
|
|||
connected = not n.address & 0x01
|
||||
if logger.isEnabledFor(logging.INFO):
|
||||
logger.info("%s: DJ connection: %s %s", device, connected, n)
|
||||
device.changed(active=connected, alert=_ALERT.NONE, reason=_("connected") if connected else _("disconnected"))
|
||||
device.changed(active=connected, alert=Alert.NONE, reason=_("connected") if connected else _("disconnected"))
|
||||
return True
|
||||
|
||||
logger.warning("%s: unrecognized DJ %s", device, n)
|
||||
|
@ -229,7 +230,7 @@ def _process_hidpp10_notification(device, n):
|
|||
device.wpid = None
|
||||
if device.number in device.receiver:
|
||||
del device.receiver[device.number]
|
||||
device.changed(active=False, alert=_ALERT.ALL, reason=_("unpaired"))
|
||||
device.changed(active=False, alert=Alert.ALL, reason=_("unpaired"))
|
||||
## device.status = None
|
||||
else:
|
||||
logger.warning("%s: disconnection with unknown type %02X: %s", device, n.address, n)
|
||||
|
@ -277,7 +278,7 @@ def _process_hidpp10_notification(device, n):
|
|||
if logger.isEnabledFor(logging.DEBUG):
|
||||
logger.debug("%s: device powered on", device)
|
||||
reason = device.status_string() or _("powered on")
|
||||
device.changed(active=True, alert=_ALERT.NOTIFICATION, reason=reason)
|
||||
device.changed(active=True, alert=Alert.NOTIFICATION, reason=reason)
|
||||
else:
|
||||
logger.warning("%s: unknown %s", device, n)
|
||||
return True
|
||||
|
@ -325,17 +326,17 @@ def _process_feature_notification(device, n, feature):
|
|||
charge, lux, adc = _unpack("!BHH", n.data[:5])
|
||||
# guesstimate the battery voltage, emphasis on 'guess'
|
||||
# status_text = '%1.2fV' % (adc * 2.67793237653 / 0x0672)
|
||||
status_text = _Battery.STATUS.discharging
|
||||
status_text = BatteryStatus.DISCHARGING
|
||||
if n.address == 0x00:
|
||||
device.set_battery_info(_Battery(charge, None, status_text, None))
|
||||
elif n.address == 0x10:
|
||||
if lux > 200:
|
||||
status_text = _Battery.STATUS.recharging
|
||||
status_text = BatteryStatus.RECHARGING
|
||||
device.set_battery_info(_Battery(charge, None, status_text, None, lux))
|
||||
elif n.address == 0x20:
|
||||
if logger.isEnabledFor(logging.DEBUG):
|
||||
logger.debug("%s: Light Check button pressed", device)
|
||||
device.changed(alert=_ALERT.SHOW_WINDOW)
|
||||
device.changed(alert=Alert.SHOW_WINDOW)
|
||||
# first cancel any reporting
|
||||
# device.feature_request(_F.SOLAR_DASHBOARD)
|
||||
# trigger a new report chain
|
||||
|
@ -353,7 +354,7 @@ def _process_feature_notification(device, n, feature):
|
|||
logger.debug("wireless status: %s", n)
|
||||
reason = "powered on" if n.data[2] == 1 else None
|
||||
if n.data[1] == 1: # device is asking for software reconfiguration so need to change status
|
||||
alert = _ALERT.NONE
|
||||
alert = Alert.NONE
|
||||
device.changed(active=True, alert=alert, reason=reason, push=True)
|
||||
else:
|
||||
logger.warning("%s: unknown WIRELESS %s", device, n)
|
||||
|
|
|
@ -32,7 +32,7 @@ from . import base as _base
|
|||
from . import exceptions
|
||||
from . import hidpp10
|
||||
from . import hidpp10_constants
|
||||
from .common import ALERT
|
||||
from .common import Alert
|
||||
from .device import Device
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
@ -113,7 +113,7 @@ class Receiver:
|
|||
def __del__(self):
|
||||
self.close()
|
||||
|
||||
def changed(self, alert=ALERT.NOTIFICATION, reason=None):
|
||||
def changed(self, alert=Alert.NOTIFICATION, reason=None):
|
||||
"""The status of the device had changed, so invoke the status callback"""
|
||||
if self.status_callback is not None:
|
||||
self.status_callback(self, alert=alert, reason=reason)
|
||||
|
|
|
@ -20,7 +20,7 @@ import logging
|
|||
import gi
|
||||
import yaml as _yaml
|
||||
|
||||
from logitech_receiver.common import ALERT
|
||||
from logitech_receiver.common import Alert
|
||||
|
||||
from solaar.i18n import _
|
||||
from solaar.ui.config_panel import change_setting
|
||||
|
@ -109,21 +109,21 @@ def _status_changed(device, alert, reason, refresh=False):
|
|||
if logger.isEnabledFor(logging.DEBUG):
|
||||
logger.debug("status changed: %s (%s) %s", device, alert, reason)
|
||||
if alert is None:
|
||||
alert = ALERT.NONE
|
||||
alert = Alert.NONE
|
||||
|
||||
tray.update(device)
|
||||
if alert & ALERT.ATTENTION:
|
||||
if alert & Alert.ATTENTION:
|
||||
tray.attention(reason)
|
||||
|
||||
need_popup = alert & ALERT.SHOW_WINDOW
|
||||
need_popup = alert & Alert.SHOW_WINDOW
|
||||
window.update(device, need_popup, refresh)
|
||||
diversion_rules.update_devices()
|
||||
|
||||
if alert & (ALERT.NOTIFICATION | ALERT.ATTENTION):
|
||||
if alert & (Alert.NOTIFICATION | Alert.ATTENTION):
|
||||
notify.show(device, reason)
|
||||
|
||||
|
||||
def status_changed(device, alert=ALERT.NONE, reason=None, refresh=False):
|
||||
def status_changed(device, alert=Alert.NONE, reason=None, refresh=False):
|
||||
GLib.idle_add(_status_changed, device, alert, reason, refresh)
|
||||
|
||||
|
||||
|
|
|
@ -218,11 +218,17 @@ def test_kw_exception():
|
|||
@pytest.mark.parametrize(
|
||||
"status, expected_level, expected_ok, expected_charging, expected_string",
|
||||
[
|
||||
(common.Battery.STATUS.full, common.Battery.APPROX.full, True, True, "Battery: full (full)"),
|
||||
(common.Battery.STATUS.almost_full, common.Battery.APPROX.good, True, True, "Battery: good (almost full)"),
|
||||
(common.Battery.STATUS.recharging, common.Battery.APPROX.good, True, True, "Battery: good (recharging)"),
|
||||
(common.Battery.STATUS.slow_recharge, common.Battery.APPROX.low, True, True, "Battery: low (slow recharge)"),
|
||||
(common.Battery.STATUS.discharging, None, True, False, ""),
|
||||
(common.BatteryStatus.FULL, common.BatteryLevelApproximation.FULL, True, True, "Battery: full (full)"),
|
||||
(common.BatteryStatus.ALMOST_FULL, common.BatteryLevelApproximation.GOOD, True, True, "Battery: good (almost full)"),
|
||||
(common.BatteryStatus.RECHARGING, common.BatteryLevelApproximation.GOOD, True, True, "Battery: good (recharging)"),
|
||||
(
|
||||
common.BatteryStatus.SLOW_RECHARGE,
|
||||
common.BatteryLevelApproximation.LOW,
|
||||
True,
|
||||
True,
|
||||
"Battery: low (slow recharge)",
|
||||
),
|
||||
(common.BatteryStatus.DISCHARGING, None, True, False, ""),
|
||||
],
|
||||
)
|
||||
def test_battery(status, expected_level, expected_ok, expected_charging, expected_string):
|
||||
|
@ -236,9 +242,9 @@ def test_battery(status, expected_level, expected_ok, expected_charging, expecte
|
|||
|
||||
|
||||
def test_battery_2():
|
||||
battery = common.Battery(50, None, common.Battery.STATUS.discharging, None)
|
||||
battery = common.Battery(50, None, common.BatteryStatus.DISCHARGING, None)
|
||||
|
||||
assert battery.status == common.Battery.STATUS.discharging
|
||||
assert battery.status == common.BatteryStatus.DISCHARGING
|
||||
assert battery.level == 50
|
||||
assert battery.ok()
|
||||
assert not battery.charging()
|
||||
|
|
|
@ -135,53 +135,53 @@ device_status6 = device_status("NOSTATUS", "002200")
|
|||
(device_leds, None, None),
|
||||
(
|
||||
device_standard,
|
||||
common.Battery(common.Battery.APPROX.good, None, common.Battery.STATUS.recharging, None),
|
||||
common.Battery(common.BatteryLevelApproximation.GOOD, None, common.BatteryStatus.RECHARGING, None),
|
||||
hidpp10_constants.REGISTERS.battery_status,
|
||||
),
|
||||
(
|
||||
device_charge1,
|
||||
common.Battery(0x55, None, common.Battery.STATUS.discharging, None),
|
||||
common.Battery(0x55, None, common.BatteryStatus.DISCHARGING, None),
|
||||
hidpp10_constants.REGISTERS.battery_charge,
|
||||
),
|
||||
(
|
||||
device_charge2,
|
||||
common.Battery(0x44, None, common.Battery.STATUS.recharging, None),
|
||||
common.Battery(0x44, None, common.BatteryStatus.RECHARGING, None),
|
||||
hidpp10_constants.REGISTERS.battery_charge,
|
||||
),
|
||||
(
|
||||
device_charge3,
|
||||
common.Battery(0x60, None, common.Battery.STATUS.full, None),
|
||||
common.Battery(0x60, None, common.BatteryStatus.FULL, None),
|
||||
hidpp10_constants.REGISTERS.battery_charge,
|
||||
),
|
||||
(device_charge4, common.Battery(0x22, None, None, None), hidpp10_constants.REGISTERS.battery_charge),
|
||||
(
|
||||
device_status1,
|
||||
common.Battery(common.Battery.APPROX.full, None, common.Battery.STATUS.full, None),
|
||||
common.Battery(common.BatteryLevelApproximation.FULL, None, common.BatteryStatus.FULL, None),
|
||||
hidpp10_constants.REGISTERS.battery_status,
|
||||
),
|
||||
(
|
||||
device_status2,
|
||||
common.Battery(common.Battery.APPROX.good, None, common.Battery.STATUS.recharging, None),
|
||||
common.Battery(common.BatteryLevelApproximation.GOOD, None, common.BatteryStatus.RECHARGING, None),
|
||||
hidpp10_constants.REGISTERS.battery_status,
|
||||
),
|
||||
(
|
||||
device_status3,
|
||||
common.Battery(common.Battery.APPROX.low, None, common.Battery.STATUS.full, None),
|
||||
common.Battery(common.BatteryLevelApproximation.LOW, None, common.BatteryStatus.FULL, None),
|
||||
hidpp10_constants.REGISTERS.battery_status,
|
||||
),
|
||||
(
|
||||
device_status4,
|
||||
common.Battery(common.Battery.APPROX.critical, None, None, None),
|
||||
common.Battery(common.BatteryLevelApproximation.CRITICAL, None, None, None),
|
||||
hidpp10_constants.REGISTERS.battery_status,
|
||||
),
|
||||
(
|
||||
device_status5,
|
||||
common.Battery(common.Battery.APPROX.empty, None, common.Battery.STATUS.discharging, None),
|
||||
common.Battery(common.BatteryLevelApproximation.EMPTY, None, common.BatteryStatus.DISCHARGING, None),
|
||||
hidpp10_constants.REGISTERS.battery_status,
|
||||
),
|
||||
(
|
||||
device_status6,
|
||||
common.Battery(None, None, common.Battery.STATUS.full, None),
|
||||
common.Battery(None, None, common.BatteryStatus.FULL, None),
|
||||
hidpp10_constants.REGISTERS.battery_status,
|
||||
),
|
||||
],
|
||||
|
@ -212,11 +212,11 @@ def test_hidpp10_get_firmware(device, expected_length):
|
|||
@pytest.mark.parametrize(
|
||||
"device, level, charging, warning, p1, p2",
|
||||
[
|
||||
(device_leds, common.Battery.APPROX.empty, False, False, 0x33, 0x00),
|
||||
(device_leds, common.Battery.APPROX.critical, False, False, 0x22, 0x00),
|
||||
(device_leds, common.Battery.APPROX.low, False, False, 0x20, 0x00),
|
||||
(device_leds, common.Battery.APPROX.good, False, False, 0x20, 0x02),
|
||||
(device_leds, common.Battery.APPROX.full, False, False, 0x20, 0x22),
|
||||
(device_leds, common.BatteryLevelApproximation.EMPTY, False, False, 0x33, 0x00),
|
||||
(device_leds, common.BatteryLevelApproximation.CRITICAL, False, False, 0x22, 0x00),
|
||||
(device_leds, common.BatteryLevelApproximation.LOW, False, False, 0x20, 0x00),
|
||||
(device_leds, common.BatteryLevelApproximation.GOOD, False, False, 0x20, 0x02),
|
||||
(device_leds, common.BatteryLevelApproximation.FULL, False, False, 0x20, 0x22),
|
||||
(device_leds, None, True, False, 0x30, 0x33),
|
||||
(device_leds, None, False, True, 0x02, 0x00),
|
||||
(device_leds, None, False, False, 0x11, 0x11),
|
||||
|
|
|
@ -96,7 +96,7 @@ def test_get_battery_status():
|
|||
assert feature == hidpp20_constants.FEATURE.BATTERY_STATUS
|
||||
assert battery.level == 80
|
||||
assert battery.next_level == 32
|
||||
assert battery.status == common.Battery.STATUS.discharging
|
||||
assert battery.status == common.BatteryStatus.DISCHARGING
|
||||
|
||||
|
||||
def test_get_battery_voltage():
|
||||
|
@ -107,7 +107,7 @@ def test_get_battery_voltage():
|
|||
|
||||
assert feature == hidpp20_constants.FEATURE.BATTERY_VOLTAGE
|
||||
assert battery.level == 90
|
||||
assert battery.status == common.Battery.STATUS.recharging
|
||||
assert battery.status == common.BatteryStatus.RECHARGING
|
||||
assert battery.voltage == 0x1000
|
||||
|
||||
|
||||
|
@ -119,7 +119,7 @@ def test_get_battery_unified():
|
|||
|
||||
assert feature == hidpp20_constants.FEATURE.UNIFIED_BATTERY
|
||||
assert battery.level == 80
|
||||
assert battery.status == common.Battery.STATUS.discharging
|
||||
assert battery.status == common.BatteryStatus.DISCHARGING
|
||||
|
||||
|
||||
def test_get_adc_measurement():
|
||||
|
@ -130,7 +130,7 @@ def test_get_adc_measurement():
|
|||
|
||||
assert feature == hidpp20_constants.FEATURE.ADC_MEASUREMENT
|
||||
assert battery.level == 90
|
||||
assert battery.status == common.Battery.STATUS.recharging
|
||||
assert battery.status == common.BatteryStatus.RECHARGING
|
||||
assert battery.voltage == 0x1000
|
||||
|
||||
|
||||
|
@ -143,7 +143,7 @@ def test_get_battery():
|
|||
assert feature == hidpp20_constants.FEATURE.BATTERY_STATUS
|
||||
assert battery.level == 80
|
||||
assert battery.next_level == 32
|
||||
assert battery.status == common.Battery.STATUS.discharging
|
||||
assert battery.status == common.BatteryStatus.DISCHARGING
|
||||
|
||||
|
||||
def test_get_battery_none():
|
||||
|
@ -158,7 +158,7 @@ def test_get_battery_none():
|
|||
|
||||
assert feature == hidpp20_constants.FEATURE.UNIFIED_BATTERY
|
||||
assert battery.level == 80
|
||||
assert battery.status == common.Battery.STATUS.discharging
|
||||
assert battery.status == common.BatteryStatus.DISCHARGING
|
||||
|
||||
|
||||
# get_keys is in test_hidpp20_complex
|
||||
|
@ -379,7 +379,7 @@ def test_decipher_battery_status():
|
|||
assert feature == hidpp20_constants.FEATURE.BATTERY_STATUS
|
||||
assert battery.level == 80
|
||||
assert battery.next_level == 32
|
||||
assert battery.status == common.Battery.STATUS.discharging
|
||||
assert battery.status == common.BatteryStatus.DISCHARGING
|
||||
|
||||
|
||||
def test_decipher_battery_voltage():
|
||||
|
@ -389,7 +389,7 @@ def test_decipher_battery_voltage():
|
|||
|
||||
assert feature == hidpp20_constants.FEATURE.BATTERY_VOLTAGE
|
||||
assert battery.level == 90
|
||||
assert battery.status == common.Battery.STATUS.recharging
|
||||
assert battery.status == common.BatteryStatus.RECHARGING
|
||||
assert battery.voltage == 0x1000
|
||||
|
||||
|
||||
|
@ -400,7 +400,7 @@ def test_decipher_battery_unified():
|
|||
|
||||
assert feature == hidpp20_constants.FEATURE.UNIFIED_BATTERY
|
||||
assert battery.level == 80
|
||||
assert battery.status == common.Battery.STATUS.discharging
|
||||
assert battery.status == common.BatteryStatus.DISCHARGING
|
||||
|
||||
|
||||
def test_decipher_adc_measurement():
|
||||
|
@ -410,5 +410,5 @@ def test_decipher_adc_measurement():
|
|||
|
||||
assert feature == hidpp20_constants.FEATURE.ADC_MEASUREMENT
|
||||
assert battery.level == 90
|
||||
assert battery.status == common.Battery.STATUS.recharging
|
||||
assert battery.status == common.BatteryStatus.RECHARGING
|
||||
assert battery.voltage == 0x1000
|
||||
|
|
Loading…
Reference in New Issue