Coverage for src/bluetooth_sig/types/data_types.py: 100%
58 statements
« prev ^ index » next coverage.py v7.11.0, created at 2025-10-30 00:10 +0000
« prev ^ index » next coverage.py v7.11.0, created at 2025-10-30 00:10 +0000
1"""Data types for Bluetooth SIG standards."""
3from __future__ import annotations
5from typing import Any
7import msgspec
9from .base_types import SIGInfo
10from .context import CharacteristicContext
11from .descriptor_types import DescriptorData
12from .gatt_enums import GattProperty, ValueType
13from .uuid import BluetoothUUID
16class ParseFieldError(msgspec.Struct, frozen=True, kw_only=True):
17 """Represents a field-level parsing error with diagnostic information.
19 This provides structured error information similar to Pydantic's validation
20 errors, making it easier to debug which specific field failed and why.
22 Attributes:
23 field: Name of the field that failed (e.g., "temperature", "flags")
24 reason: Human-readable description of why parsing failed
25 offset: Optional byte offset where the field starts in raw data
26 raw_slice: Optional raw bytes that were being parsed when error occurred
28 """
30 field: str
31 reason: str
32 offset: int | None = None
33 raw_slice: bytes | None = None
36class CharacteristicInfo(SIGInfo):
37 """Information about a Bluetooth characteristic."""
39 value_type: ValueType = ValueType.UNKNOWN
40 unit: str = ""
41 properties: list[GattProperty] = msgspec.field(default_factory=list)
44class ServiceInfo(SIGInfo):
45 """Information about a Bluetooth service."""
47 characteristics: list[CharacteristicInfo] = msgspec.field(default_factory=list)
50class CharacteristicData(msgspec.Struct, kw_only=True):
51 """Parsed characteristic data with validation results.
53 Provides structured error reporting with field-level diagnostics and parse traces
54 to help identify exactly where and why parsing failed.
56 NOTE: This struct intentionally has more attributes than the standard limit
57 to provide complete diagnostic information. The additional fields (field_errors,
58 parse_trace) are essential for actionable error reporting and debugging.
59 """
61 info: CharacteristicInfo
62 value: Any | None = None
63 raw_data: bytes = b""
64 parse_success: bool = False
65 error_message: str = ""
66 source_context: CharacteristicContext = msgspec.field(default_factory=CharacteristicContext)
67 field_errors: list[ParseFieldError] = msgspec.field(default_factory=list)
68 parse_trace: list[str] = msgspec.field(default_factory=list)
69 descriptors: dict[str, DescriptorData] = msgspec.field(default_factory=dict)
71 @property
72 def name(self) -> str:
73 """Get the characteristic name from info."""
74 return self.info.name
76 @property
77 def properties(self) -> list[GattProperty]:
78 """Get the properties as strings for protocol compatibility."""
79 return self.info.properties
81 @property
82 def uuid(self) -> BluetoothUUID:
83 """Get the characteristic UUID from info."""
84 return self.info.uuid
86 @property
87 def unit(self) -> str:
88 """Get the characteristic unit from info."""
89 return self.info.unit
92class ValidationResult(SIGInfo):
93 """Result of data validation."""
95 is_valid: bool = True
96 expected_length: int | None = None
97 actual_length: int | None = None
98 error_message: str = ""
101class CharacteristicRegistration(msgspec.Struct, kw_only=True):
102 """Unified metadata for custom UUID registration."""
104 uuid: BluetoothUUID
105 name: str = ""
106 id: str | None = None
107 summary: str = ""
108 unit: str = ""
109 value_type: ValueType = ValueType.STRING
112class ServiceRegistration(msgspec.Struct, kw_only=True):
113 """Unified metadata for custom UUID registration."""
115 uuid: BluetoothUUID
116 name: str = ""
117 id: str | None = None
118 summary: str = ""