device: pause setting up features when error occurs; use ADC message to signal connection and disconnection
This commit is contained in:
parent
33a06ac834
commit
217b9360e6
|
|
@ -277,9 +277,10 @@ def _process_feature_notification(device: Device, notification: HIDPPNotificatio
|
||||||
elif feature == SupportedFeature.ADC_MEASUREMENT:
|
elif feature == SupportedFeature.ADC_MEASUREMENT:
|
||||||
if notification.address == 0x00:
|
if notification.address == 0x00:
|
||||||
result = hidpp20.decipher_adc_measurement(notification.data)
|
result = hidpp20.decipher_adc_measurement(notification.data)
|
||||||
if result:
|
if result: # this may be the only message signalling that the device has become active
|
||||||
device.set_battery_info(result[1])
|
device.set_battery_info(result[1])
|
||||||
else: # this feature is used to signal device becoming inactive
|
device.changed(active=True, alert=Alert.ALL, reason=_("ADC measurement notification"))
|
||||||
|
else: # this feature is also used to signal device becoming inactive
|
||||||
device.changed(active=False)
|
device.changed(active=False)
|
||||||
else:
|
else:
|
||||||
logger.warning("%s: unknown ADC MEASUREMENT %s", device, notification)
|
logger.warning("%s: unknown ADC MEASUREMENT %s", device, notification)
|
||||||
|
|
|
||||||
|
|
@ -32,6 +32,7 @@ from . import common
|
||||||
from . import descriptors
|
from . import descriptors
|
||||||
from . import desktop_notifications
|
from . import desktop_notifications
|
||||||
from . import diversion
|
from . import diversion
|
||||||
|
from . import exceptions
|
||||||
from . import hidpp20
|
from . import hidpp20
|
||||||
from . import hidpp20_constants
|
from . import hidpp20_constants
|
||||||
from . import settings
|
from . import settings
|
||||||
|
|
@ -1534,6 +1535,7 @@ class ADCPower(settings.Setting):
|
||||||
label = _("Power Management")
|
label = _("Power Management")
|
||||||
description = _("Power off in minutes (0 for never).")
|
description = _("Power off in minutes (0 for never).")
|
||||||
feature = _F.ADC_MEASUREMENT
|
feature = _F.ADC_MEASUREMENT
|
||||||
|
min_version = 2 # documentation for version 1 does not mention this capability
|
||||||
rw_options = {"read_fnid": 0x10, "write_fnid": 0x20}
|
rw_options = {"read_fnid": 0x10, "write_fnid": 0x20}
|
||||||
validator_class = settings_validator.RangeValidator
|
validator_class = settings_validator.RangeValidator
|
||||||
min_value = 0x00
|
min_value = 0x00
|
||||||
|
|
@ -1905,7 +1907,7 @@ def check_feature(device, settings_class: SettingsProtocol) -> None | bool | Set
|
||||||
logger.error(
|
logger.error(
|
||||||
"check_feature %s [%s] error %s\n%s", settings_class.name, settings_class.feature, e, traceback.format_exc()
|
"check_feature %s [%s] error %s\n%s", settings_class.name, settings_class.feature, e, traceback.format_exc()
|
||||||
)
|
)
|
||||||
return False # differentiate from an error-free determination that the setting is not supported
|
raise e # differentiate from an error-free determination that the setting is not supported
|
||||||
|
|
||||||
|
|
||||||
def check_feature_settings(device, already_known) -> bool:
|
def check_feature_settings(device, already_known) -> bool:
|
||||||
|
|
@ -1914,7 +1916,7 @@ def check_feature_settings(device, already_known) -> bool:
|
||||||
Returns
|
Returns
|
||||||
-------
|
-------
|
||||||
bool
|
bool
|
||||||
True, if device was queried to find features, False otherwise.
|
True, if device was fully queried to find features, False otherwise.
|
||||||
"""
|
"""
|
||||||
if not device.features or not device.online:
|
if not device.features or not device.online:
|
||||||
return False
|
return False
|
||||||
|
|
@ -1926,7 +1928,20 @@ def check_feature_settings(device, already_known) -> bool:
|
||||||
if sclass.feature:
|
if sclass.feature:
|
||||||
known_present = device.persister and sclass.name in device.persister
|
known_present = device.persister and sclass.name in device.persister
|
||||||
if not any(s.name == sclass.name for s in already_known) and (known_present or sclass.name not in absent):
|
if not any(s.name == sclass.name for s in already_known) and (known_present or sclass.name not in absent):
|
||||||
setting = check_feature(device, sclass)
|
try:
|
||||||
|
setting = check_feature(device, sclass)
|
||||||
|
except Exception as err:
|
||||||
|
# on an internal HID++ error, assume offline and stop further checking
|
||||||
|
if (
|
||||||
|
isinstance(err, exceptions.FeatureCallError)
|
||||||
|
and err.error == hidpp20_constants.ErrorCode.LOGITECH_ERROR
|
||||||
|
):
|
||||||
|
logger.warning(f"HID++ internal error when checking feature {sclass.name}: make device offline")
|
||||||
|
device.online = False
|
||||||
|
return False
|
||||||
|
else:
|
||||||
|
logger.warning(f"ignore feature {sclass.name} because of error {err}")
|
||||||
|
|
||||||
if isinstance(setting, list):
|
if isinstance(setting, list):
|
||||||
for s in setting:
|
for s in setting:
|
||||||
already_known.append(s)
|
already_known.append(s)
|
||||||
|
|
@ -1948,6 +1963,9 @@ def check_feature_settings(device, already_known) -> bool:
|
||||||
def check_feature_setting(device, setting_name: str) -> settings.Setting | None:
|
def check_feature_setting(device, setting_name: str) -> settings.Setting | None:
|
||||||
for sclass in SETTINGS:
|
for sclass in SETTINGS:
|
||||||
if sclass.feature and sclass.name == setting_name and device.features:
|
if sclass.feature and sclass.name == setting_name and device.features:
|
||||||
setting = check_feature(device, sclass)
|
try:
|
||||||
|
setting = check_feature(device, sclass)
|
||||||
|
except Exception:
|
||||||
|
return None
|
||||||
if setting:
|
if setting:
|
||||||
return setting
|
return setting
|
||||||
|
|
|
||||||
|
|
@ -268,7 +268,7 @@ simple_tests = [
|
||||||
fake_hidpp.Response("0A", 0x0410, "0A"),
|
fake_hidpp.Response("0A", 0x0410, "0A"),
|
||||||
),
|
),
|
||||||
Setup(
|
Setup(
|
||||||
FeatureTest(settings_templates.ADCPower, 5, 0xA),
|
FeatureTest(settings_templates.ADCPower, 5, 0xA, version=0x03),
|
||||||
fake_hidpp.Response("05", 0x0410),
|
fake_hidpp.Response("05", 0x0410),
|
||||||
fake_hidpp.Response("0A", 0x0420, "0A"),
|
fake_hidpp.Response("0A", 0x0420, "0A"),
|
||||||
),
|
),
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue