Fix Bluetooth bytes conversion and WiFi monitor mode detection

- Fix "cannot convert 'str' object to bytes" error in BLE identity engine
  by adding robust _convert_to_bytes() helper that handles bytes, hex
  strings, bytearrays, and arrays
- Improve DBus scanner to safely handle various data types for
  manufacturer_data and service_data with proper error handling
- Add monitor mode interface detection in WiFi scanner to provide clear
  error message when quick scan is attempted on monitor mode interface

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Smittix
2026-01-21 23:25:22 +00:00
parent 54a47b03c2
commit f01502ff32
3 changed files with 90 additions and 6 deletions

View File

@@ -1157,6 +1157,30 @@ def reset_identity_engine() -> None:
_identity_engine = DeviceIdentityEngine()
def _convert_to_bytes(value) -> Optional[bytes]:
"""Convert various data types to bytes safely."""
if value is None:
return None
if isinstance(value, bytes):
return value
if isinstance(value, bytearray):
return bytes(value)
if isinstance(value, str):
# Assume hex string
try:
return bytes.fromhex(value)
except ValueError:
# Not a valid hex string, encode as UTF-8
return value.encode('utf-8')
if isinstance(value, (list, tuple)):
# Array of integers (like dbus.Array)
try:
return bytes(value)
except (TypeError, ValueError):
return None
return None
def ingest_ble_dict(data: dict) -> DeviceSession:
"""
Ingest BLE observation from dictionary.
@@ -1173,9 +1197,9 @@ def ingest_ble_dict(data: dict) -> DeviceSession:
adv_type=data.get('adv_type', 'unknown'),
adv_flags=data.get('adv_flags'),
manufacturer_id=data.get('manufacturer_id'),
manufacturer_data=bytes.fromhex(data['manufacturer_data']) if data.get('manufacturer_data') else None,
manufacturer_data=_convert_to_bytes(data.get('manufacturer_data')),
service_uuids=data.get('service_uuids', []),
service_data=bytes.fromhex(data['service_data']) if data.get('service_data') else None,
service_data=_convert_to_bytes(data.get('service_data')),
local_name=data.get('local_name', data.get('name')),
appearance=data.get('appearance'),
packet_length=data.get('packet_length'),