Coverage for src / bluetooth_sig / types / io.py: 58%

19 statements  

« prev     ^ index     » next       coverage.py v7.13.1, created at 2026-01-11 20:14 +0000

1"""Typed containers for staging raw BLE I/O into the translator. 

2 

3These structs model common outputs from BLE connection managers (e.g., Bleak, 

4SimpleBLE) and provide a convenient way to feed raw bytes into the 

5`BluetoothSIGTranslator` batch parser, including descriptor bytes when 

6available. 

7""" 

8 

9from __future__ import annotations 

10 

11import msgspec 

12 

13from .uuid import BluetoothUUID 

14 

15 

16class RawCharacteristicRead(msgspec.Struct, kw_only=True): 

17 """Container for a single characteristic read. 

18 

19 This type is convenient for users to stage raw values coming from their BLE 

20 connection manager (e.g. Bleak, SimpleBLE) before handing them to the 

21 translator. It models the common shape produced by those libraries: 

22 

23 - `uuid`: characteristic UUID (short or full form) 

24 - `raw_data`: bytes value as returned by `read_gatt_char`/notification 

25 - `descriptors`: optional mapping of descriptor UUID -> raw bytes (if read) 

26 - `properties`: optional list of characteristic properties (e.g. "read", 

27 "notify"). These are currently informational for the parser. 

28 """ 

29 

30 uuid: BluetoothUUID | str 

31 raw_data: bytes 

32 descriptors: dict[str, bytes] = msgspec.field(default_factory=dict) 

33 properties: list[str] = msgspec.field(default_factory=list) 

34 

35 

36class RawCharacteristicBatch(msgspec.Struct, kw_only=True): 

37 """A batch of raw characteristic reads to be parsed together. 

38 

39 Use this when you have multiple related characteristics (e.g., Glucose 

40 Measurement + Glucose Measurement Context). The translator can parse them in 

41 dependency-aware order. 

42 """ 

43 

44 items: list[RawCharacteristicRead] 

45 

46 

47def to_parse_inputs( 

48 batch: RawCharacteristicBatch, 

49) -> tuple[dict[str, bytes], dict[str, dict[str, bytes]]]: 

50 """Convert a :class:`RawCharacteristicBatch` to translator inputs. 

51 

52 Returns a tuple of `(char_data, descriptor_data)` suitable for 

53 `BluetoothSIGTranslator.parse_characteristics(char_data, descriptor_data=...)`. 

54 

55 - `char_data` is a mapping of UUID -> raw bytes 

56 - `descriptor_data` is a nested mapping of char UUID -> (descriptor UUID -> raw bytes) 

57 """ 

58 char_data: dict[str, bytes] = {} 

59 descriptor_data: dict[str, dict[str, bytes]] = {} 

60 

61 for item in batch.items: 

62 uuid_str = str(item.uuid) 

63 char_data[uuid_str] = item.raw_data 

64 if item.descriptors: 

65 descriptor_data[uuid_str] = dict(item.descriptors) 

66 

67 return char_data, descriptor_data