Speedup lookup of known receivers

Refactor get_receiver_info. Replacing data structure of known receivers
to avoid for loop, when an efficient dictionary lookup is possible.

Related #2273
This commit is contained in:
MattHag 2024-12-28 23:51:55 +01:00 committed by Peter F. Patel-Schneider
parent 3186d880fc
commit 1a3f4dab36
2 changed files with 79 additions and 36 deletions

View File

@ -27,6 +27,10 @@ USB ids of Logitech wireless receivers.
Only receivers supporting the HID++ protocol can go in here. Only receivers supporting the HID++ protocol can go in here.
""" """
from __future__ import annotations
from typing import Any
from solaar.i18n import _ from solaar.i18n import _
# max_devices is only used for receivers that do not support reading from Registers.RECEIVER_INFO offset 0x03, default # max_devices is only used for receivers that do not support reading from Registers.RECEIVER_INFO offset 0x03, default
@ -174,49 +178,58 @@ LIGHTSPEED_RECEIVER_C547 = _lightspeed_receiver(0xC547)
# EX100 old style receiver pre-unifying protocol # EX100 old style receiver pre-unifying protocol
EX100_27MHZ_RECEIVER_C517 = _ex100_receiver(0xC517) EX100_27MHZ_RECEIVER_C517 = _ex100_receiver(0xC517)
KNOWN_RECEIVERS = ( KNOWN_RECEIVERS = {
BOLT_RECEIVER_C548, 0xC548: BOLT_RECEIVER_C548,
UNIFYING_RECEIVER_C52B, 0xC52B: UNIFYING_RECEIVER_C52B,
UNIFYING_RECEIVER_C532, 0xC532: UNIFYING_RECEIVER_C532,
NANO_RECEIVER_ADVANCED, 0xC52F: NANO_RECEIVER_ADVANCED,
NANO_RECEIVER_C518, 0xC518: NANO_RECEIVER_C518,
NANO_RECEIVER_C51A, 0xC51A: NANO_RECEIVER_C51A,
NANO_RECEIVER_C51B, 0xC51B: NANO_RECEIVER_C51B,
NANO_RECEIVER_C521, 0xC521: NANO_RECEIVER_C521,
NANO_RECEIVER_C525, 0xC525: NANO_RECEIVER_C525,
NANO_RECEIVER_C526, 0xC526: NANO_RECEIVER_C526,
NANO_RECEIVER_C52E, 0xC52E: NANO_RECEIVER_C52E,
NANO_RECEIVER_C531, 0xC531: NANO_RECEIVER_C531,
NANO_RECEIVER_C534, 0xC534: NANO_RECEIVER_C534,
NANO_RECEIVER_C535, 0xC535: NANO_RECEIVER_C535,
NANO_RECEIVER_C537, 0xC537: NANO_RECEIVER_C537,
NANO_RECEIVER_6042, 0x6042: NANO_RECEIVER_6042,
LIGHTSPEED_RECEIVER_C539, 0xC539: LIGHTSPEED_RECEIVER_C539,
LIGHTSPEED_RECEIVER_C53A, 0xC53A: LIGHTSPEED_RECEIVER_C53A,
LIGHTSPEED_RECEIVER_C53D, 0xC53D: LIGHTSPEED_RECEIVER_C53D,
LIGHTSPEED_RECEIVER_C53F, 0xC53F: LIGHTSPEED_RECEIVER_C53F,
LIGHTSPEED_RECEIVER_C541, 0xC541: LIGHTSPEED_RECEIVER_C541,
LIGHTSPEED_RECEIVER_C545, 0xC545: LIGHTSPEED_RECEIVER_C545,
LIGHTSPEED_RECEIVER_C547, 0xC547: LIGHTSPEED_RECEIVER_C547,
EX100_27MHZ_RECEIVER_C517, 0xC517: EX100_27MHZ_RECEIVER_C517,
) }
def get_receiver_info(product_id: int) -> dict: def get_receiver_info(product_id: int) -> dict[str, Any]:
"""Returns hardcoded information about Logitech receiver. """Returns hardcoded information about a Logitech receiver.
Parameters Parameters
---------- ----------
product_id product_id
Product ID of receiver e.g. 0xC548 for a Logitech Bolt receiver. Product ID (pid) of the receiver, e.g. 0xC548 for a Logitech
Bolt receiver.
Returns Returns
------- -------
dict dict[str, Any]
Product info with mandatory vendor_id, product_id, Receiver info with mandatory fields:
usb_interface, name, receiver_kind - vendor_id
- product_id
Raises
------
ValueError
If the product ID is unknown.
""" """
for receiver in KNOWN_RECEIVERS: try:
if product_id == receiver.get("product_id"): return KNOWN_RECEIVERS[product_id]
return receiver except KeyError:
raise ValueError(f"Unknown product ID '0x{product_id:02X}") pass
raise ValueError(f"Unknown product ID '0x{product_id:02X}'")

View File

@ -0,0 +1,30 @@
import pytest
from logitech_receiver import base_usb
from logitech_receiver.common import LOGITECH_VENDOR_ID
def test_ensure_known_receivers_mappings_are_valid():
for key, receiver in base_usb.KNOWN_RECEIVERS.items():
assert key == receiver["product_id"]
def test_get_receiver_info():
expected = {
"vendor_id": LOGITECH_VENDOR_ID,
"product_id": 0xC548,
"usb_interface": 2,
"name": "Bolt Receiver",
"receiver_kind": "bolt",
"max_devices": 6,
"may_unpair": True,
}
res = base_usb.get_receiver_info(0xC548)
assert res == expected
def test_get_receiver_info_unknown_device_fails():
with pytest.raises(ValueError):
base_usb.get_receiver_info(0xC500)