0
# Utilities
1
2
Utility functions and classes for UUID conversion, device discovery, and USB serial device management. These utilities provide helper functionality for common BLE development tasks and hardware integration.
3
4
## Capabilities
5
6
### UUID Conversion
7
8
Convert between different UUID formats commonly used in BLE applications.
9
10
```python { .api }
11
def uuid16_to_uuid(uuid16: int) -> UUID:
12
"""
13
Convert 16-bit UUID to full 128-bit UUID format.
14
15
Converts Bluetooth SIG assigned 16-bit UUIDs to their full 128-bit
16
representation using the Bluetooth base UUID.
17
18
Args:
19
uuid16: 16-bit UUID as integer (e.g., 0x180F for Battery Service)
20
21
Returns:
22
UUID: Full 128-bit UUID object
23
24
Example:
25
Battery Service UUID 0x180F becomes:
26
0000180F-0000-1000-8000-00805F9B34FB
27
"""
28
```
29
30
**Usage Example:**
31
32
```python
33
import pygatt
34
from pygatt.util import uuid16_to_uuid
35
36
# Convert standard Bluetooth service UUIDs
37
battery_service = uuid16_to_uuid(0x180F)
38
print(battery_service) # 0000180f-0000-1000-8000-00805f9b34fb
39
40
device_info_service = uuid16_to_uuid(0x180A)
41
print(device_info_service) # 0000180a-0000-1000-8000-00805f9b34fb
42
43
# Use converted UUID with pygatt
44
adapter = pygatt.BGAPIBackend()
45
adapter.start()
46
device = adapter.connect('01:23:45:67:89:ab')
47
48
# Read battery level using converted UUID
49
battery_level = device.char_read(str(battery_service))
50
```
51
52
### USB Device Discovery
53
54
Discover and enumerate USB serial devices for BGAPI backend configuration.
55
56
```python { .api }
57
def find_usb_serial_devices(vendor_id: int = None, product_id: int = None) -> list:
58
"""
59
Discover USB serial devices matching optional vendor/product ID filters.
60
61
Args:
62
vendor_id: USB vendor ID to filter by (e.g., 0x2458 for Silicon Labs)
63
product_id: USB product ID to filter by (e.g., 0x0001 for BLED112)
64
65
Returns:
66
list: List of USBSerialDeviceInfo objects for matching devices
67
68
Raises:
69
ImportError: If required USB enumeration libraries not available
70
"""
71
72
def extract_vid_pid(info_string: str) -> tuple:
73
"""
74
Extract vendor ID and product ID from USB device info string.
75
76
Args:
77
info_string: USB device information string from system
78
79
Returns:
80
tuple: (vendor_id: int, product_id: int) or (None, None) if not found
81
"""
82
```
83
84
**Usage Example:**
85
86
```python
87
import pygatt
88
from pygatt.backends.bgapi.util import find_usb_serial_devices, extract_vid_pid
89
90
# Find all USB serial devices
91
all_devices = find_usb_serial_devices()
92
for device in all_devices:
93
print(f"Device: {device.device_name}")
94
print(f"Port: {device.port_name}")
95
print(f"VID: 0x{device.vendor_id:04X}, PID: 0x{device.product_id:04X}")
96
97
# Find BLED112 devices specifically
98
bled112_devices = find_usb_serial_devices(
99
vendor_id=0x2458, # Silicon Labs
100
product_id=0x0001 # BLED112
101
)
102
103
if bled112_devices:
104
# Use first BLED112 found
105
device = bled112_devices[0]
106
adapter = pygatt.BGAPIBackend(serial_port=device.port_name)
107
print(f"Using BLED112 on {device.port_name}")
108
else:
109
print("No BLED112 devices found")
110
111
# Parse device info manually
112
info = "USB\\VID_2458&PID_0001\\12345"
113
vid, pid = extract_vid_pid(info)
114
if vid and pid:
115
print(f"Found device: VID=0x{vid:04X}, PID=0x{pid:04X}")
116
```
117
118
### USB Device Information
119
120
Container class for USB serial device metadata and connection details.
121
122
```python { .api }
123
class USBSerialDeviceInfo:
124
"""
125
Container for USB serial device information.
126
127
Attributes:
128
device_name: Human-readable device name
129
port_name: System port name for serial connection
130
vendor_id: USB vendor ID as integer
131
product_id: USB product ID as integer
132
"""
133
def __init__(self, device_name: str, port_name: str, vendor_id: int, product_id: int):
134
self.device_name = device_name
135
self.port_name = port_name
136
self.vendor_id = vendor_id
137
self.product_id = product_id
138
```
139
140
**Usage Example:**
141
142
```python
143
from pygatt.backends.bgapi.util import USBSerialDeviceInfo
144
145
# Create device info manually
146
device_info = USBSerialDeviceInfo(
147
device_name="Silicon Labs BLED112",
148
port_name="COM9", # Windows
149
vendor_id=0x2458,
150
product_id=0x0001
151
)
152
153
print(f"Device: {device_info.device_name}")
154
print(f"Connect via: {device_info.port_name}")
155
156
# Use with BGAPI backend
157
adapter = pygatt.BGAPIBackend(serial_port=device_info.port_name)
158
```
159
160
## BGAPI Hardware Constants
161
162
Predefined constants for common BGAPI-compatible hardware identification.
163
164
```python { .api }
165
# Silicon Labs BLED112 USB BLE adapter
166
BLED112_VENDOR_ID = 0x2458
167
BLED112_PRODUCT_ID = 0x0001
168
169
# Usage in device discovery
170
from pygatt.backends.bgapi.constants import BLED112_VENDOR_ID, BLED112_PRODUCT_ID
171
172
bled112_devices = find_usb_serial_devices(
173
vendor_id=BLED112_VENDOR_ID,
174
product_id=BLED112_PRODUCT_ID
175
)
176
```
177
178
## Platform-Specific Utilities
179
180
Handle cross-platform differences in USB device enumeration and serial port naming.
181
182
### Windows COM Port Discovery
183
184
```python
185
import pygatt
186
from pygatt.backends.bgapi.util import find_usb_serial_devices
187
188
# Windows-specific COM port handling
189
devices = find_usb_serial_devices()
190
for device in devices:
191
if device.port_name.startswith('COM'):
192
print(f"Windows COM port: {device.port_name}")
193
194
# Handle COM ports > 9 (Windows limitation)
195
if int(device.port_name[3:]) > 9:
196
print("Warning: COM ports >9 may require special handling")
197
```
198
199
### Linux/macOS Device Path Discovery
200
201
```python
202
import pygatt
203
from pygatt.backends.bgapi.util import find_usb_serial_devices
204
205
# Unix-style device path handling
206
devices = find_usb_serial_devices()
207
for device in devices:
208
if device.port_name.startswith('/dev/'):
209
print(f"Unix device path: {device.port_name}")
210
211
# Common Linux patterns
212
if 'ttyACM' in device.port_name:
213
print("USB CDC ACM device (typical for BGAPI)")
214
elif 'ttyUSB' in device.port_name:
215
print("USB serial converter device")
216
elif 'cu.usbmodem' in device.port_name:
217
print("macOS USB modem device")
218
```
219
220
## Automated Device Selection
221
222
Implement intelligent device selection for robust applications.
223
224
```python
225
import pygatt
226
from pygatt.backends.bgapi.util import find_usb_serial_devices
227
from pygatt.backends.bgapi.constants import BLED112_VENDOR_ID, BLED112_PRODUCT_ID
228
229
def auto_select_bgapi_device():
230
"""
231
Automatically select best BGAPI device available.
232
233
Returns:
234
str: Serial port name for selected device
235
236
Raises:
237
pygatt.BGAPIError: No suitable devices found
238
"""
239
# First, look for known BGAPI devices
240
bgapi_devices = find_usb_serial_devices(
241
vendor_id=BLED112_VENDOR_ID,
242
product_id=BLED112_PRODUCT_ID
243
)
244
245
if bgapi_devices:
246
device = bgapi_devices[0] # Use first BLED112
247
print(f"Selected BLED112: {device.port_name}")
248
return device.port_name
249
250
# Fallback: look for any Silicon Labs device
251
siliconlabs_devices = find_usb_serial_devices(vendor_id=0x2458)
252
if siliconlabs_devices:
253
device = siliconlabs_devices[0]
254
print(f"Selected Silicon Labs device: {device.port_name}")
255
return device.port_name
256
257
# Last resort: let BGAPI backend auto-discover
258
print("No specific devices found, using auto-discovery")
259
return None
260
261
# Usage
262
try:
263
port = auto_select_bgapi_device()
264
adapter = pygatt.BGAPIBackend(serial_port=port)
265
adapter.start()
266
print("BGAPI backend initialized successfully")
267
268
except pygatt.BGAPIError as e:
269
print(f"Failed to initialize BGAPI: {e}")
270
print("Check USB connections and drivers")
271
```
272
273
## Device Health Monitoring
274
275
Monitor USB device health and connection stability.
276
277
```python
278
import time
279
import threading
280
from pygatt.backends.bgapi.util import find_usb_serial_devices
281
282
class BGAPIDeviceMonitor:
283
"""
284
Monitor BGAPI device availability and health.
285
"""
286
287
def __init__(self, vendor_id=0x2458, product_id=0x0001):
288
self.vendor_id = vendor_id
289
self.product_id = product_id
290
self.monitoring = False
291
self.last_seen_devices = set()
292
293
def start_monitoring(self, callback=None):
294
"""
295
Start monitoring device availability.
296
297
Args:
298
callback: Function called on device changes: callback(added, removed)
299
"""
300
self.monitoring = True
301
302
def monitor_loop():
303
while self.monitoring:
304
current_devices = set()
305
306
try:
307
devices = find_usb_serial_devices(
308
vendor_id=self.vendor_id,
309
product_id=self.product_id
310
)
311
current_devices = {d.port_name for d in devices}
312
313
if current_devices != self.last_seen_devices:
314
added = current_devices - self.last_seen_devices
315
removed = self.last_seen_devices - current_devices
316
317
if callback:
318
callback(added, removed)
319
320
if added:
321
print(f"BGAPI devices added: {added}")
322
if removed:
323
print(f"BGAPI devices removed: {removed}")
324
325
self.last_seen_devices = current_devices
326
327
except Exception as e:
328
print(f"Device monitoring error: {e}")
329
330
time.sleep(2) # Check every 2 seconds
331
332
threading.Thread(target=monitor_loop, daemon=True).start()
333
334
def stop_monitoring(self):
335
self.monitoring = False
336
337
# Usage
338
def device_change_handler(added, removed):
339
if removed:
340
print("BGAPI device disconnected - applications may need restart")
341
if added:
342
print("New BGAPI device available")
343
344
monitor = BGAPIDeviceMonitor()
345
monitor.start_monitoring(callback=device_change_handler)
346
347
# Run for 30 seconds
348
time.sleep(30)
349
monitor.stop_monitoring()
350
```
351
352
## Error Handling for Utilities
353
354
Handle common issues in device discovery and USB enumeration.
355
356
```python
357
import pygatt
358
from pygatt.backends.bgapi.util import find_usb_serial_devices
359
360
def safe_device_discovery():
361
"""
362
Safely discover USB devices with comprehensive error handling.
363
"""
364
try:
365
devices = find_usb_serial_devices()
366
return devices
367
368
except ImportError as e:
369
print(f"USB enumeration not available: {e}")
370
print("Install: pip install pyusb or pip install pyserial")
371
return []
372
373
except PermissionError:
374
print("Permission denied accessing USB devices")
375
print("Try running with elevated privileges")
376
return []
377
378
except Exception as e:
379
print(f"Unexpected error in device discovery: {e}")
380
return []
381
382
# Usage with fallback
383
devices = safe_device_discovery()
384
if devices:
385
print(f"Found {len(devices)} USB serial devices")
386
else:
387
print("No devices found or discovery failed")
388
print("Specify serial port manually:")
389
print("adapter = pygatt.BGAPIBackend(serial_port='COM9')")
390
```