Skip to content

Commit 0058a10

Browse files
authored
Merge pull request #217 from tkomde/main
Implemented ble hid Device class
2 parents 6744b68 + 617d297 commit 0058a10

File tree

2 files changed

+89
-20
lines changed

2 files changed

+89
-20
lines changed

adafruit_ble/services/standard/hid.py

Lines changed: 88 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
from .. import Service
2727

2828
try:
29-
from typing import Dict, Optional
29+
from typing import Dict, Optional, Sequence
3030
except ImportError:
3131
pass
3232

@@ -248,6 +248,60 @@ def report(self) -> Dict:
248248
return self._characteristic.value
249249

250250

251+
class Device:
252+
"""Container that groups multiple ReportIn and ReportOut objects for a given
253+
usage_page/usage.
254+
255+
Each device may have multiple report IDs. This class keeps mappings from
256+
report_id -> ReportIn/ReportOut and provides convenience methods that use
257+
the first-added report_id when none is specified.
258+
"""
259+
260+
def __init__(self, usage_page, usage):
261+
self._usage_page = usage_page
262+
self._usage = usage
263+
self._first_report_in_id = None
264+
self._first_report_out_id = None
265+
self._report_ins = {} # report_id -> ReportIn
266+
self._report_outs = {} # report_id -> ReportOut
267+
268+
@property
269+
def usage_page(self):
270+
return self._usage_page
271+
272+
@property
273+
def usage(self):
274+
return self._usage
275+
276+
def add_report_in(self, report_id: int, report_in: ReportIn) -> None:
277+
"""Register a ReportIn instance for a report_id."""
278+
if self._first_report_in_id is None:
279+
self._first_report_in_id = report_id
280+
self._report_ins[report_id] = report_in
281+
282+
def add_report_out(self, report_id: int, report_out: ReportOut) -> None:
283+
"""Register a ReportOut instance for a report_id."""
284+
if self._first_report_out_id is None:
285+
self._first_report_out_id = report_id
286+
self._report_outs[report_id] = report_out
287+
288+
def send_report(self, report: Dict, report_id: int | None = None) -> None:
289+
"""Send a report via the ReportIn class."""
290+
if report_id is None and self._first_report_in_id is not None:
291+
report_id = self._first_report_in_id
292+
if report_id is None:
293+
raise RuntimeError("No input report available")
294+
self._report_ins[report_id].send_report(report)
295+
296+
def get_last_received_report(self, report_id: int | None = None):
297+
"""Return the last OUT report received."""
298+
if report_id is None and self._first_report_out_id is not None:
299+
report_id = self._first_report_out_id
300+
if report_id is None:
301+
raise RuntimeError("No output report available")
302+
return self._report_outs[report_id].report
303+
304+
251305
_ITEM_TYPE_MAIN = const(0)
252306
_ITEM_TYPE_GLOBAL = const(1)
253307
_ITEM_TYPE_LOCAL = const(2)
@@ -268,9 +322,9 @@ class HIDService(Service):
268322
269323
Example::
270324
271-
from adafruit_ble.hid_server import HIDServer
325+
from adafruit_ble.services.standard.hid import HIDService
272326
273-
hid = HIDServer()
327+
hid = HIDService()
274328
"""
275329

276330
uuid = StandardUUID(0x1812)
@@ -429,25 +483,39 @@ def get_report_info(collection: Dict, reports: Dict) -> None:
429483
get_report_info(collection, reports)
430484
for report_id, report in reports.items():
431485
output_size = report["output_size"]
486+
# Group ReportIn and ReportOut by usage_page and usage into a Devices
487+
input_size = report["input_size"]
488+
489+
# Find an existing device with same usage_page and usage
490+
device = None
491+
for d in self.devices:
492+
# Device instances expose usage_page and usage properties
493+
if d.usage_page == usage_page and d.usage == usage:
494+
device = d
495+
break
496+
497+
if device is None:
498+
device = Device(usage_page, usage)
499+
self.devices.append(device)
500+
432501
if output_size > 0:
433-
self.devices.append(
434-
ReportOut(
435-
self,
436-
report_id,
437-
usage_page,
438-
usage,
439-
max_length=output_size // 8,
440-
)
502+
# Create ReportOut and attach to device
503+
report_out = ReportOut(
504+
self,
505+
report_id,
506+
usage_page,
507+
usage,
508+
max_length=output_size // 8,
441509
)
510+
device.add_report_out(report_id, report_out)
442511

443-
input_size = report["input_size"]
444512
if input_size > 0:
445-
self.devices.append(
446-
ReportIn(
447-
self,
448-
report_id,
449-
usage_page,
450-
usage,
451-
max_length=input_size // 8,
452-
)
513+
# Create ReportIn and attach to device
514+
report_in = ReportIn(
515+
self,
516+
report_id,
517+
usage_page,
518+
usage,
519+
max_length=input_size // 8,
453520
)
521+
device.add_report_in(report_id, report_in)

examples/ble_hid_periph.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,5 +46,6 @@
4646
sys.stdout.write(c)
4747
kl.write(c)
4848
# print("sleeping")
49+
# print(f"{k.led_status}") #read led_status
4950
time.sleep(0.1)
5051
ble.start_advertising(advertisement)

0 commit comments

Comments
 (0)