Coverage for src / bluetooth_sig / types / advertising / ad_structures.py: 93%
89 statements
« prev ^ index » next coverage.py v7.13.5, created at 2026-03-18 11:17 +0000
« prev ^ index » next coverage.py v7.13.5, created at 2026-03-18 11:17 +0000
1"""Parsed AD structure categories.
3Organized by Bluetooth Core Specification Supplement AD type categories.
4"""
6from __future__ import annotations
8import msgspec
10from bluetooth_sig.types.advertising.channel_map_update import ChannelMapUpdateIndication
11from bluetooth_sig.types.advertising.features import LEFeatures
12from bluetooth_sig.types.advertising.flags import BLEAdvertisingFlags
13from bluetooth_sig.types.advertising.indoor_positioning import IndoorPositioningData
14from bluetooth_sig.types.advertising.pdu import BLEAdvertisingPDU
15from bluetooth_sig.types.advertising.three_d_information import ThreeDInformationData
16from bluetooth_sig.types.advertising.transport_discovery import TransportDiscoveryData
17from bluetooth_sig.types.appearance import AppearanceData
18from bluetooth_sig.types.company import ManufacturerData
19from bluetooth_sig.types.mesh import (
20 MeshMessage,
21 ProvisioningBearerData,
22 SecureNetworkBeacon,
23 UnprovisionedDeviceBeacon,
24)
25from bluetooth_sig.types.registry.class_of_device import ClassOfDeviceInfo
26from bluetooth_sig.types.uri import URIData
27from bluetooth_sig.types.uuid import BluetoothUUID
30class ConnectionIntervalRange(msgspec.Struct, kw_only=True):
31 """Peripheral preferred connection interval range (Core Spec Supplement, Part A, Section 1.9).
33 Attributes:
34 min_interval: Minimum connection interval in 1.25ms units
35 max_interval: Maximum connection interval in 1.25ms units
36 min_interval_ms: Minimum connection interval in milliseconds
37 max_interval_ms: Maximum connection interval in milliseconds
38 """
40 INTERVAL_UNIT_MS: float = 1.25 # Connection interval unit in milliseconds
42 min_interval: int # In 1.25ms units
43 max_interval: int # In 1.25ms units
45 @property
46 def min_interval_ms(self) -> float:
47 """Get minimum interval in milliseconds."""
48 return self.min_interval * self.INTERVAL_UNIT_MS
50 @property
51 def max_interval_ms(self) -> float:
52 """Get maximum interval in milliseconds."""
53 return self.max_interval * self.INTERVAL_UNIT_MS
56class CoreAdvertisingData(msgspec.Struct, kw_only=True):
57 """Core advertising data - device identification and services.
59 Attributes:
60 manufacturer_data: Manufacturer-specific data keyed by company ID.
61 Each entry contains resolved company info and payload bytes.
62 service_uuids: List of advertised service UUIDs
63 service_data: Service-specific data keyed by service UUID
64 solicited_service_uuids: List of service UUIDs the device is seeking
65 local_name: Device's local name (complete or shortened)
66 uri_data: Parsed URI with scheme info from UriSchemesRegistry
67 """
69 manufacturer_data: dict[int, ManufacturerData] = msgspec.field(default_factory=dict)
70 service_uuids: list[BluetoothUUID] = msgspec.field(default_factory=list)
71 service_data: dict[BluetoothUUID, bytes] = msgspec.field(default_factory=dict)
72 solicited_service_uuids: list[BluetoothUUID] = msgspec.field(default_factory=list)
73 local_name: str = ""
74 uri_data: URIData | None = None
77class DeviceProperties(msgspec.Struct, kw_only=True):
78 """Device capability and appearance properties.
80 Attributes:
81 flags: BLE advertising flags (discoverable mode, capabilities)
82 appearance: Device appearance category and subcategory
83 tx_power: Transmission power level in dBm
84 le_role: LE role (peripheral, central, etc.)
85 le_supported_features: LE supported features with property accessors
86 class_of_device: Classic Bluetooth Class of Device value
87 class_of_device_info: Parsed Class of Device information
88 """
90 flags: BLEAdvertisingFlags = BLEAdvertisingFlags(0)
91 appearance: AppearanceData | None = None
92 tx_power: int = 0
93 le_role: int | None = None
94 le_supported_features: LEFeatures | None = None
95 class_of_device: ClassOfDeviceInfo | None = None
98class DirectedAdvertisingData(msgspec.Struct, kw_only=True):
99 """Directed advertising and timing parameters.
101 These AD types specify target devices and advertising timing.
103 Attributes:
104 public_target_address: List of public target addresses (AD 0x17)
105 random_target_address: List of random target addresses (AD 0x18)
106 le_bluetooth_device_address: LE Bluetooth device address (AD 0x1B)
107 advertising_interval: Advertising interval in 0.625ms units (AD 0x1A)
108 advertising_interval_long: Long advertising interval (AD 0x2F)
109 peripheral_connection_interval_range: Preferred connection interval with min/max (AD 0x12)
110 """
112 public_target_address: list[str] = msgspec.field(default_factory=list)
113 random_target_address: list[str] = msgspec.field(default_factory=list)
114 le_bluetooth_device_address: str = ""
115 advertising_interval: int | None = None
116 advertising_interval_long: int | None = None
117 peripheral_connection_interval_range: ConnectionIntervalRange | None = None
120class OOBSecurityData(msgspec.Struct, kw_only=True):
121 """Out-of-Band (OOB) security data advertised for pairing.
123 These AD types provide security material for OOB pairing mechanisms.
125 Attributes:
126 simple_pairing_hash_c: Simple Pairing Hash C-192/C-256 (AD 0x0E, 0x1D)
127 simple_pairing_randomizer_r: Simple Pairing Randomizer R-192/R-256 (AD 0x0F, 0x1E)
128 secure_connections_confirmation: LE SC Confirmation Value (AD 0x22)
129 secure_connections_random: LE SC Random Value (AD 0x23)
130 security_manager_tk_value: Security Manager TK Value (AD 0x10)
131 security_manager_oob_flags: SM Out of Band Flags (AD 0x11)
132 """
134 simple_pairing_hash_c: bytes = b""
135 simple_pairing_randomizer_r: bytes = b""
136 secure_connections_confirmation: bytes = b""
137 secure_connections_random: bytes = b""
138 security_manager_tk_value: bytes = b""
139 security_manager_oob_flags: bytes = b""
142class LocationAndSensingData(msgspec.Struct, kw_only=True):
143 """Location, positioning, and sensing related data.
145 Attributes:
146 indoor_positioning: Parsed Indoor Positioning AD (0x25), or ``None`` if absent.
147 three_d_information: Parsed 3D Information AD (0x3D), or ``None`` if absent.
148 transport_discovery_data: Parsed Transport Discovery AD (0x26), or ``None`` if absent.
149 channel_map_update_indication: Parsed Channel Map Update AD (0x28), or ``None`` if absent.
150 """
152 indoor_positioning: IndoorPositioningData | None = None
153 three_d_information: ThreeDInformationData | None = None
154 transport_discovery_data: TransportDiscoveryData | None = None
155 channel_map_update_indication: ChannelMapUpdateIndication | None = None
158class MeshAndBroadcastData(msgspec.Struct, kw_only=True):
159 """Bluetooth Mesh and audio broadcast related data.
161 Attributes:
162 mesh_message: Parsed Mesh Network PDU message
163 secure_network_beacon: Parsed Secure Network Beacon (provisioned nodes)
164 unprovisioned_device_beacon: Parsed Unprovisioned Device Beacon
165 provisioning_bearer: Parsed Provisioning Bearer (PB-ADV) data
166 broadcast_name: Broadcast name for LE Audio
167 broadcast_code: Broadcast Code for encrypted audio
168 biginfo: BIG Info for Broadcast Isochronous Groups
169 periodic_advertising_response_timing: Periodic Advertising Response Timing Info
170 electronic_shelf_label: Electronic Shelf Label data
172 """
174 mesh_message: MeshMessage | None = None
175 secure_network_beacon: SecureNetworkBeacon | None = None
176 unprovisioned_device_beacon: UnprovisionedDeviceBeacon | None = None
177 provisioning_bearer: ProvisioningBearerData | None = None
178 broadcast_name: str = ""
179 broadcast_code: bytes = b""
180 biginfo: bytes = b""
181 periodic_advertising_response_timing: bytes = b""
182 electronic_shelf_label: bytes = b""
185class SecurityData(msgspec.Struct, kw_only=True):
186 """Security and encryption related advertising data.
188 Attributes:
189 encrypted_advertising_data: Encrypted Advertising Data
190 resolvable_set_identifier: Resolvable Set Identifier
191 """
193 encrypted_advertising_data: bytes = b""
194 resolvable_set_identifier: bytes = b""
197class ExtendedAdvertisingData(msgspec.Struct, kw_only=True):
198 """Extended advertising PDU-level metadata (BLE 5.0+).
200 This contains PDU-level information specific to extended advertising,
201 NOT AD types (which go in AdvertisingDataStructures).
203 Attributes:
204 extended_payload: Raw extended advertising payload bytes
205 auxiliary_packets: Chained AUX_ADV_IND packets via AuxPtr
206 periodic_advertising_data: Data from periodic advertising train
207 """
209 extended_payload: bytes = b""
210 auxiliary_packets: list[BLEAdvertisingPDU] = msgspec.field(default_factory=list)
211 periodic_advertising_data: bytes = b""
214class AdvertisingDataStructures(msgspec.Struct, kw_only=True):
215 """Complete parsed advertising data structures organized by category.
217 Contains all AD Types parsed from advertising PDUs (both legacy and extended).
218 These are payload content, not PDU-level metadata.
220 Attributes:
221 core: Device identification and services (manufacturer data, UUIDs, name)
222 properties: Device capabilities (flags, appearance, tx_power, features)
223 directed: Directed advertising parameters (target addresses, intervals)
224 oob_security: Out-of-Band security data for pairing
225 location: Location and sensing data
226 mesh: Mesh network and broadcast audio data
227 security: Encrypted advertising and privacy data
228 """
230 core: CoreAdvertisingData = msgspec.field(default_factory=CoreAdvertisingData)
231 properties: DeviceProperties = msgspec.field(default_factory=DeviceProperties)
232 directed: DirectedAdvertisingData = msgspec.field(default_factory=DirectedAdvertisingData)
233 oob_security: OOBSecurityData = msgspec.field(default_factory=OOBSecurityData)
234 location: LocationAndSensingData = msgspec.field(default_factory=LocationAndSensingData)
235 mesh: MeshAndBroadcastData = msgspec.field(default_factory=MeshAndBroadcastData)
236 security: SecurityData = msgspec.field(default_factory=SecurityData)
238 @classmethod
239 def from_common_fields(
240 cls,
241 *,
242 manufacturer_data: dict[int, ManufacturerData] | None = None,
243 service_data: dict[BluetoothUUID, bytes] | None = None,
244 service_uuids: list[BluetoothUUID] | None = None,
245 local_name: str = "",
246 tx_power: int = 0,
247 address: str = "",
248 connectable: bool = False,
249 ) -> AdvertisingDataStructures:
250 """Create from common platform advertisement fields.
252 Builds an ``AdvertisingDataStructures`` with sensible defaults for
253 fields that are typically unavailable from BLE platform APIs
254 (OOB security, mesh, location, etc.).
256 Args:
257 manufacturer_data: Manufacturer-specific data keyed by company ID.
258 service_data: Service data keyed by service UUID.
259 service_uuids: Advertised service UUIDs.
260 local_name: Device local name.
261 tx_power: Transmission power level in dBm.
262 address: BLE device address (MAC).
263 connectable: Whether the device is connectable.
265 Returns:
266 Populated ``AdvertisingDataStructures`` instance.
268 """
269 flags = BLEAdvertisingFlags.BR_EDR_NOT_SUPPORTED
270 if connectable:
271 flags |= BLEAdvertisingFlags.LE_GENERAL_DISCOVERABLE_MODE
273 return cls(
274 core=CoreAdvertisingData(
275 manufacturer_data=manufacturer_data or {},
276 service_data=service_data or {},
277 service_uuids=service_uuids or [],
278 local_name=local_name,
279 ),
280 properties=DeviceProperties(
281 flags=flags,
282 tx_power=tx_power,
283 ),
284 directed=DirectedAdvertisingData(
285 le_bluetooth_device_address=address,
286 ),
287 )