""" Bluetooth-specific constants for the unified scanner. """ from __future__ import annotations # ============================================================================= # SCANNER SETTINGS # ============================================================================= # Default scan duration in seconds DEFAULT_SCAN_DURATION = 10 # Maximum concurrent observations per device before pruning MAX_RSSI_SAMPLES = 300 # Device expiration time (seconds since last seen) DEVICE_STALE_TIMEOUT = 300 # 5 minutes # Observation history retention (seconds) OBSERVATION_HISTORY_RETENTION = 3600 # 1 hour # ============================================================================= # RSSI THRESHOLDS FOR RANGE BANDS # ============================================================================= # RSSI ranges for distance estimation (dBm) RSSI_VERY_CLOSE = -40 # >= -40 dBm RSSI_CLOSE = -55 # -40 to -55 dBm RSSI_NEARBY = -70 # -55 to -70 dBm RSSI_FAR = -85 # -70 to -85 dBm # Minimum confidence levels for each range band CONFIDENCE_VERY_CLOSE = 0.7 CONFIDENCE_CLOSE = 0.6 CONFIDENCE_NEARBY = 0.5 CONFIDENCE_FAR = 0.4 # ============================================================================= # HEURISTIC THRESHOLDS # ============================================================================= # Persistent detection: minimum seen count in analysis window PERSISTENT_MIN_SEEN_COUNT = 10 PERSISTENT_WINDOW_SECONDS = 300 # 5 minutes # Beacon-like detection: maximum advertisement interval variance (ratio) BEACON_INTERVAL_MAX_VARIANCE = 0.10 # 10% # Strong + Stable detection thresholds STRONG_RSSI_THRESHOLD = -50 # dBm STABLE_VARIANCE_THRESHOLD = 5 # dBm variance # New device window (seconds since baseline set) NEW_DEVICE_WINDOW = 60 # ============================================================================= # DBUS SETTINGS (BlueZ) # ============================================================================= # BlueZ DBus service names BLUEZ_SERVICE = "org.bluez" BLUEZ_ADAPTER_INTERFACE = "org.bluez.Adapter1" BLUEZ_DEVICE_INTERFACE = "org.bluez.Device1" DBUS_PROPERTIES_INTERFACE = "org.freedesktop.DBus.Properties" DBUS_OBJECT_MANAGER_INTERFACE = "org.freedesktop.DBus.ObjectManager" # DBus paths BLUEZ_PATH = "/org/bluez" # Discovery filter settings DISCOVERY_FILTER_TRANSPORT = "auto" # 'bredr', 'le', or 'auto' DISCOVERY_FILTER_RSSI = -100 # Minimum RSSI for discovery DISCOVERY_FILTER_DUPLICATE_DATA = True # ============================================================================= # FALLBACK SCANNER SETTINGS # ============================================================================= # bleak scan timeout BLEAK_SCAN_TIMEOUT = 10.0 # hcitool command timeout HCITOOL_TIMEOUT = 15.0 # bluetoothctl command timeout BLUETOOTHCTL_TIMEOUT = 10.0 # btmgmt command timeout BTMGMT_TIMEOUT = 10.0 # Generic subprocess timeout (short operations) SUBPROCESS_TIMEOUT_SHORT = 5.0 # ============================================================================= # ADDRESS TYPE CLASSIFICATIONS # ============================================================================= ADDRESS_TYPE_PUBLIC = "public" ADDRESS_TYPE_RANDOM = "random" ADDRESS_TYPE_RANDOM_STATIC = "random_static" ADDRESS_TYPE_RPA = "rpa" # Resolvable Private Address ADDRESS_TYPE_NRPA = "nrpa" # Non-Resolvable Private Address ADDRESS_TYPE_UUID = "uuid" # CoreBluetooth platform UUID (macOS, no real MAC available) # ============================================================================= # PROTOCOL TYPES # ============================================================================= PROTOCOL_BLE = "ble" PROTOCOL_CLASSIC = "classic" PROTOCOL_AUTO = "auto" # ============================================================================= # RANGE BAND NAMES # ============================================================================= RANGE_VERY_CLOSE = "very_close" RANGE_CLOSE = "close" RANGE_NEARBY = "nearby" RANGE_FAR = "far" RANGE_UNKNOWN = "unknown" # ============================================================================= # PROXIMITY BANDS (new visualization system) # ============================================================================= PROXIMITY_IMMEDIATE = "immediate" # < 1m PROXIMITY_NEAR = "near" # 1-3m PROXIMITY_FAR = "far" # 3-10m PROXIMITY_UNKNOWN = "unknown" # RSSI thresholds for proximity band classification (dBm) PROXIMITY_RSSI_IMMEDIATE = -40 # >= -40 dBm -> immediate PROXIMITY_RSSI_NEAR = -55 # >= -55 dBm -> near PROXIMITY_RSSI_FAR = -75 # >= -75 dBm -> far # ============================================================================= # DISTANCE ESTIMATION SETTINGS # ============================================================================= # Path-loss exponent for indoor environments (typical range: 2-4) DISTANCE_PATH_LOSS_EXPONENT = 2.5 # Reference RSSI at 1 meter (typical BLE value) DISTANCE_RSSI_AT_1M = -59 # EMA smoothing alpha (higher = more responsive, lower = smoother) DISTANCE_EMA_ALPHA = 0.3 # Variance thresholds for confidence scoring (dBm^2) DISTANCE_LOW_VARIANCE = 25.0 # High confidence DISTANCE_HIGH_VARIANCE = 100.0 # Low confidence # ============================================================================= # RING BUFFER SETTINGS # ============================================================================= # Observation retention period (minutes) RING_BUFFER_RETENTION_MINUTES = 30 # Minimum interval between observations per device (seconds) RING_BUFFER_MIN_INTERVAL_SECONDS = 2.0 # Maximum observations stored per device RING_BUFFER_MAX_OBSERVATIONS = 1000 # ============================================================================= # HEATMAP SETTINGS # ============================================================================= # Default time window for heatmap (minutes) HEATMAP_DEFAULT_WINDOW_MINUTES = 10 # Default bucket size for downsampling (seconds) HEATMAP_DEFAULT_BUCKET_SECONDS = 10 # Maximum devices to show in heatmap HEATMAP_MAX_DEVICES = 50 # ============================================================================= # COMMON MANUFACTURER IDS (OUI -> Name mapping for common vendors) # ============================================================================= MANUFACTURER_NAMES = { 0x004C: "Apple, Inc.", 0x0006: "Microsoft", 0x000F: "Broadcom", 0x0075: "Samsung Electronics", 0x00E0: "Google", 0x0157: "Xiaomi", 0x0310: "Bose Corporation", 0x0059: "Nordic Semiconductor", 0x0046: "Sony Corporation", 0x0002: "Intel Corporation", 0x0087: "Garmin International", 0x00D2: "Fitbit", 0x0154: "Huawei Technologies", 0x038F: "Tile, Inc.", 0x0301: "Jabra", 0x01DA: "Anker Innovations", } # ============================================================================= # BLUETOOTH CLASS OF DEVICE DECODING # ============================================================================= # Major device classes (bits 12-8 of CoD) MAJOR_DEVICE_CLASSES = { 0x00: "Miscellaneous", 0x01: "Computer", 0x02: "Phone", 0x03: "LAN/Network Access Point", 0x04: "Audio/Video", 0x05: "Peripheral", 0x06: "Imaging", 0x07: "Wearable", 0x08: "Toy", 0x09: "Health", 0x1F: "Uncategorized", } # Minor device classes for Audio/Video (0x04) MINOR_AUDIO_VIDEO = { 0x00: "Uncategorized", 0x01: "Wearable Headset", 0x02: "Hands-free Device", 0x04: "Microphone", 0x05: "Loudspeaker", 0x06: "Headphones", 0x07: "Portable Audio", 0x08: "Car Audio", 0x09: "Set-top Box", 0x0A: "HiFi Audio Device", 0x0B: "VCR", 0x0C: "Video Camera", 0x0D: "Camcorder", 0x0E: "Video Monitor", 0x0F: "Video Display and Loudspeaker", 0x10: "Video Conferencing", 0x12: "Gaming/Toy", } # Minor device classes for Phone (0x02) MINOR_PHONE = { 0x00: "Uncategorized", 0x01: "Cellular", 0x02: "Cordless", 0x03: "Smartphone", 0x04: "Wired Modem", 0x05: "ISDN Access Point", } # Minor device classes for Computer (0x01) MINOR_COMPUTER = { 0x00: "Uncategorized", 0x01: "Desktop Workstation", 0x02: "Server-class Computer", 0x03: "Laptop", 0x04: "Handheld PC/PDA", 0x05: "Palm-size PC/PDA", 0x06: "Wearable Computer", 0x07: "Tablet", } # Minor device classes for Peripheral (0x05) MINOR_PERIPHERAL = { 0x00: "Not Keyboard/Pointing Device", 0x01: "Keyboard", 0x02: "Pointing Device", 0x03: "Combo Keyboard/Pointing Device", } # Minor device classes for Wearable (0x07) MINOR_WEARABLE = { 0x01: "Wristwatch", 0x02: "Pager", 0x03: "Jacket", 0x04: "Helmet", 0x05: "Glasses", } # ============================================================================= # BLE APPEARANCE CODES (GAP Appearance values) # ============================================================================= BLE_APPEARANCE_NAMES: dict[int, str] = { 0: "Unknown", 64: "Phone", 128: "Computer", 192: "Watch", 193: "Sports Watch", 256: "Clock", 320: "Display", 384: "Remote Control", 448: "Eye Glasses", 512: "Tag", 576: "Keyring", 640: "Media Player", 704: "Barcode Scanner", 768: "Thermometer", 832: "Heart Rate Sensor", 896: "Blood Pressure", 960: "HID", 961: "Keyboard", 962: "Mouse", 963: "Joystick", 964: "Gamepad", 965: "Digitizer Tablet", 966: "Card Reader", 967: "Digital Pen", 968: "Barcode Scanner (HID)", 1024: "Glucose Monitor", 1088: "Running Speed Sensor", 1152: "Cycling", 1216: "Control Device", 1280: "Network Device", 1344: "Sensor", 1408: "Light Fixture", 1472: "Fan", 1536: "HVAC", 1600: "Access Control", 1664: "Motorized Device", 1728: "Power Device", 1792: "Light Source", 3136: "Pulse Oximeter", 3200: "Weight Scale", 3264: "Personal Mobility", 5184: "Outdoor Sports Activity", } def get_appearance_name(code: int | None) -> str | None: """Look up a human-readable name for a BLE appearance code.""" if code is None: return None return BLE_APPEARANCE_NAMES.get(code)