Perform an interactive Bluetooth scan on Linux that captures devices in real-time This is more reliable than relying on 'bluetoothctl devices' which may not update
(self, duration: int)
| 1283 | return devices |
| 1284 | |
| 1285 | def _linux_interactive_scan(self, duration: int) -> Dict[str, Dict[str, Any]]: |
| 1286 | """ |
| 1287 | Perform an interactive Bluetooth scan on Linux that captures devices in real-time |
| 1288 | This is more reliable than relying on 'bluetoothctl devices' which may not update |
| 1289 | """ |
| 1290 | devices = {} |
| 1291 | |
| 1292 | try: |
| 1293 | import threading |
| 1294 | import queue |
| 1295 | |
| 1296 | # Create a queue to collect output |
| 1297 | output_queue = queue.Queue() |
| 1298 | |
| 1299 | # Start bluetoothctl process |
| 1300 | proc = subprocess.Popen( |
| 1301 | ['bluetoothctl'], |
| 1302 | stdin=subprocess.PIPE, |
| 1303 | stdout=subprocess.PIPE, |
| 1304 | stderr=subprocess.STDOUT, |
| 1305 | text=True, |
| 1306 | bufsize=1 |
| 1307 | ) |
| 1308 | |
| 1309 | # Thread to read output |
| 1310 | def read_output(): |
| 1311 | try: |
| 1312 | for line in proc.stdout: |
| 1313 | output_queue.put(line) |
| 1314 | except: |
| 1315 | pass |
| 1316 | |
| 1317 | reader_thread = threading.Thread(target=read_output, daemon=True) |
| 1318 | reader_thread.start() |
| 1319 | |
| 1320 | # Send commands |
| 1321 | self.logger.info("Sending 'power on' to bluetoothctl") |
| 1322 | proc.stdin.write('power on\n') |
| 1323 | proc.stdin.flush() |
| 1324 | time.sleep(1) |
| 1325 | |
| 1326 | self.logger.info("Sending 'scan on' to bluetoothctl") |
| 1327 | proc.stdin.write('scan on\n') |
| 1328 | proc.stdin.flush() |
| 1329 | |
| 1330 | # Monitor output for device discoveries |
| 1331 | start_time = time.time() |
| 1332 | self.logger.info(f"Monitoring for {duration} seconds...") |
| 1333 | |
| 1334 | while time.time() - start_time < duration: |
| 1335 | try: |
| 1336 | line = output_queue.get(timeout=1) |
| 1337 | line = line.strip() |
| 1338 | |
| 1339 | # Log interesting lines |
| 1340 | if any(x in line for x in ['Device', 'CHG', 'NEW']): |
| 1341 | self.logger.debug(f"BT Output: {line}") |
| 1342 |