Coverage for src / bluetooth_sig / types / data_types.py: 95%
37 statements
« prev ^ index » next coverage.py v7.13.1, created at 2026-01-11 20:14 +0000
« prev ^ index » next coverage.py v7.13.1, created at 2026-01-11 20:14 +0000
1"""Data types for Bluetooth SIG standards."""
3from __future__ import annotations
5from datetime import datetime
7import msgspec
9from .base_types import SIGInfo
10from .gatt_enums import ValueType
13class ParseFieldError(msgspec.Struct, frozen=True, kw_only=True):
14 """Represents a field-level parsing error with diagnostic information.
16 This provides structured error information similar to Pydantic's validation
17 errors, making it easier to debug which specific field failed and why.
19 Attributes:
20 field: Name of the field that failed (e.g., "temperature", "flags")
21 reason: Human-readable description of why parsing failed
22 offset: Optional byte offset where the field starts in raw data
23 raw_slice: Optional raw bytes that were being parsed when error occurred
25 """
27 field: str
28 reason: str
29 offset: int | None = None
30 raw_slice: bytes | None = None
33class DateData(msgspec.Struct, frozen=True, kw_only=True):
34 """Shared data type for date values with year, month, and day fields."""
36 year: int
37 month: int
38 day: int
40 def to_datetime(self) -> datetime:
41 """Convert to Python datetime (time components set to 00:00:00).
43 Returns:
44 datetime object with date components
45 """
46 return datetime(self.year, self.month, self.day)
49class CharacteristicInfo(SIGInfo):
50 """Information about a Bluetooth characteristic from SIG/YAML specifications.
52 This contains only static metadata resolved from YAML or SIG specs.
53 Runtime properties (read/write/notify capabilities) are stored separately
54 on the BaseCharacteristic instance as they're discovered from the actual device.
55 """
57 value_type: ValueType = ValueType.UNKNOWN
58 unit: str = ""
61class ServiceInfo(SIGInfo):
62 """Information about a Bluetooth service."""
64 characteristics: list[CharacteristicInfo] = msgspec.field(default_factory=list[CharacteristicInfo])
67class ValidationAccumulator:
68 """Result of characteristic data validation with error/warning accumulation.
70 Used during parsing to accumulate validation issues from multiple validation steps.
71 Provides methods to add errors/warnings and check overall validity.
72 """
74 def __init__(self) -> None:
75 """Initialize empty validation result."""
76 self.errors: list[str] = []
77 self.warnings: list[str] = []
79 def add_error(self, message: str) -> None:
80 """Add a validation error message.
82 Args:
83 message: Error message to add
84 """
85 self.errors.append(message)
87 def add_warning(self, message: str) -> None:
88 """Add a validation warning message.
90 Args:
91 message: Warning message to add
92 """
93 self.warnings.append(message)
95 @property
96 def valid(self) -> bool:
97 """Check if validation passed (no errors).
99 Returns:
100 True if no errors, False otherwise
101 """
102 return len(self.errors) == 0
105class ValidationResult(msgspec.Struct, frozen=True, kw_only=True):
106 """Summary of validation results for external API consumption.
108 Lightweight validation result for API responses, not for accumulation.
109 """
111 is_valid: bool
112 actual_length: int
113 expected_length: int | None = None
114 error_message: str = ""