Stop Bluetooth device discovery scan Returns: (success, message)
(self)
| 417 | return False, f"Error starting scan: {str(e)}" |
| 418 | |
| 419 | def stop_scan(self) -> Tuple[bool, str]: |
| 420 | """ |
| 421 | Stop Bluetooth device discovery scan |
| 422 | Returns: (success, message) |
| 423 | """ |
| 424 | try: |
| 425 | self.logger.info("Stopping Bluetooth device scan...") |
| 426 | |
| 427 | if self._is_windows(): |
| 428 | # On Windows, just mark scanning as inactive |
| 429 | self.scan_active = False |
| 430 | self.logger.info("Bluetooth scan stopped (Windows mode)") |
| 431 | return True, "Bluetooth scan stopped successfully" |
| 432 | |
| 433 | # Linux method |
| 434 | result = subprocess.run(['bluetoothctl', 'scan', 'off'], |
| 435 | capture_output=True, text=True, timeout=10) |
| 436 | |
| 437 | # bluetoothctl scan off sometimes returns non-zero even when successful |
| 438 | success_indicators = [ |
| 439 | 'success', 'Discovery stopped', 'Discovering: no', |
| 440 | 'discovery stopped', 'stopped discovery' |
| 441 | ] |
| 442 | output_text = (result.stdout + result.stderr).lower() |
| 443 | |
| 444 | # Check for success indicators or determine if scan actually stopped |
| 445 | scan_actually_stopped = False |
| 446 | if result.returncode == 0: |
| 447 | scan_actually_stopped = True |
| 448 | elif any(indicator.lower() in output_text for indicator in success_indicators): |
| 449 | scan_actually_stopped = True |
| 450 | elif 'not available' not in output_text and 'failed' not in output_text and 'error' not in output_text: |
| 451 | # If no clear error indicators, assume success |
| 452 | scan_actually_stopped = True |
| 453 | |
| 454 | if scan_actually_stopped: |
| 455 | self.scan_active = False |
| 456 | self.logger.info("Bluetooth scan stopped successfully") |
| 457 | return True, "Bluetooth scan stopped successfully" |
| 458 | else: |
| 459 | # Even if command failed, mark scan as inactive for safety |
| 460 | self.scan_active = False |
| 461 | error_msg = result.stderr.strip() or result.stdout.strip() or 'Failed to stop Bluetooth scan' |
| 462 | self.logger.warning(f"Scan stop command may have failed, but marking as stopped: {error_msg}") |
| 463 | return False, f"Scan stop completed with warning: {error_msg}" |
| 464 | |
| 465 | except subprocess.TimeoutExpired: |
| 466 | # Mark scan as inactive even on timeout |
| 467 | self.scan_active = False |
| 468 | return False, "Scan stop command timed out" |
| 469 | except Exception as e: |
| 470 | # Mark scan as inactive even on error |
| 471 | self.scan_active = False |
| 472 | self.logger.error(f"Error stopping Bluetooth scan: {e}") |
| 473 | return False, f"Error stopping scan: {str(e)}" |
| 474 | |
| 475 | def get_discovered_devices(self, refresh: bool = True) -> Dict[str, Dict[str, Any]]: |
| 476 | """ |
no test coverage detected