This project is a part of sa/acc community: https://discord.gg/ahUpjEpD9c AliRadar is a Windows-first desktop Bluetooth radar that continuously scans for nearby Bluetooth Low Energy (BLE) and Classic Bluetooth devices, stores sightings in SQLite, and presents the results in a live React + Electron dashboard powered by a FastAPI backend.
The project is designed for a USB Bluetooth dongle connected to a Windows 10/11 machine. It discovers nearby devices such as phones, laptops, headphones, speakers, wearables, cars, and tags, then enriches those sightings with manufacturer, device class, estimated distance, live updates, and alert events.
This is a simulated preview based on the current React/Electron layout and styles in the repository, not an actual runtime screenshot.
- Bluetooth scanning pipeline for BLE and Classic Bluetooth discovery, normalization, deduplication, enrichment, presence tracking, and alert evaluation.
- FastAPI backend with REST endpoints, WebSocket broadcasting, Alembic migrations, and SQLite persistence.
- React + Vite frontend embedded in Electron for a desktop-style user experience with device, alert, and status views.
- Windows packaging path using PyInstaller for the backend and Electron Builder for the desktop app installer.
AliRadar/
├── backend/ # FastAPI app, scanners, pipeline, DB, tests
├── frontend/ # React UI + Electron shell
├── data/ # IEEE OUI vendor data
├── scripts/ # Utility scripts such as OUI downloader
├── context.md # Deep project context / architecture notes
├── PLAN.md # Build and implementation plan history
└── README.md # Project documentation
api/: REST and WebSocket server setup, route definitions, broadcast manager.scanner/: BLE scanner, Classic Bluetooth scanner, orchestration manager.pipeline/: raw-event normalization, deduplication, and enrichment wiring.intelligence/: OUI lookup, distance estimation, presence tracking, and alerts logic.storage/: SQLAlchemy models, DB initialization, and query layer.tests/: API and end-to-end pipeline tests.
src/: React application, stores, hooks, and presentational components.electron/: Electron main/preload entry points for desktop packaging.package.json: UI dependencies and desktop build scripts.
- Scanners capture nearby Bluetooth traffic:
- BLE events are received via
bleak.BleakScannerin passive scanning mode. - Classic Bluetooth discovery is executed with
pybluez2inquiries in an executor so it does not block the asyncio loop.
- BLE events are received via
- The pipeline cleans and enriches each event:
- invalid MAC addresses and too-weak RSSI values are discarded.
- similar sightings can be deduplicated into a canonical MAC when fingerprint data matches.
- manufacturer, device class, and estimated distance are added before persistence/broadcasting.
- The scanner manager persists and broadcasts results:
- device metadata is upserted,
- sightings are throttled to reduce redundant writes,
- WebSocket clients receive live device updates,
- alert rules are evaluated per event.
- The desktop UI consumes REST + WebSocket data:
- initial data loads come from the REST API,
- live updates and alert events come over WebSocket,
- the app renders connection state, device counts, and alerts in the Electron window.
- Continuous BLE scanning with passive advertisements.
- Classic Bluetooth discovery support with graceful fallback if
pybluez2is unavailable. - SQLite storage for devices, sightings, alert rules, and alert events.
- REST endpoints for devices, sightings, alert rules/events, and scanner stats.
- WebSocket broadcasting for real-time UI updates.
- Device manufacturer lookup using IEEE OUI data in
data/oui.csv. - Distance estimation from RSSI/TX power and simple proximity zoning.
- Presence and alerting engine for device appearance, linger, and other rules.
- Python
- FastAPI + Uvicorn
- SQLAlchemy + SQLite (
aiosqlite) - Alembic migrations
bleakfor BLE discoverypybluez2for Classic Bluetooth discoverypydantic-settingsfor config loading from.envwhen present.
- React 18
- Vite 5
- Electron 30
- Windows 10 or Windows 11 x64 with Bluetooth hardware available.
- A Bluetooth adapter or USB Bluetooth dongle connected to the machine.
- Administrator privileges on Windows for the backend launcher flow, because
backend/main.pyescalates withShellExecuteWif needed.
- Python 3.11+ recommended.
- Node.js 18+ and npm.
- A machine/environment where Bluetooth libraries can be installed successfully.
- On non-Windows systems, parts of the app may run for development/testing, but the intended deployment target is Windows and Classic Bluetooth support may be unavailable there.
There are two practical ways to use the repository: development mode and Windows packaged app mode.
git clone <your-repo-url>
cd AliRadarCreate a virtual environment and install Python dependencies:
python -m venv .venv
# Windows PowerShell
.\.venv\Scripts\Activate.ps1
# or on bash
source .venv/bin/activate
pip install -r backend/requirements.txtInstall Node dependencies:
cd frontend
npm install
cd ..The repository already includes data/oui.csv, so a separate .env file is not required to start with default settings. If you ever need to refresh vendor mappings, run:
python scripts/download_oui.pyThat script downloads the latest IEEE OUI CSV into data/oui.csv.
From the repository root:
python -m backend.mainThis starts Uvicorn using the host/port from backend/config.py, applies Alembic upgrades on startup, initializes the database, loads the OUI data, and starts the scanner manager.
By default the backend listens on:
http://127.0.0.1:8765- WebSocket:
ws://127.0.0.1:8765/ws
cd frontend
npm run devVite serves the UI during development, and the frontend expects the backend at 127.0.0.1:8765.
cd frontend
npm run electron:devThis runs Vite and Electron together using concurrently.
cd frontend
npm run electron:buildThis performs a Vite production build and then packages the Electron app with Electron Builder.
AliRadar loads settings through pydantic-settings, and it will read a local .env file if you choose to create one. Because sensible defaults are already defined in backend/config.py, a .env file is optional rather than mandatory.
| Variable | Default | Purpose |
|---|---|---|
APP_NAME |
AliRadar |
Application name. |
VERSION |
1.0.0 |
App/API version. |
HOST |
127.0.0.1 |
API bind host. |
PORT |
8765 |
API bind port. |
DB_PATH |
aliradar.db |
SQLite database path. |
OUI_PATH |
../data/oui.csv |
Path to OUI vendor CSV. |
SCAN_INTERVAL_SECONDS |
3.0 |
Delay between Classic Bluetooth scan cycles. |
CLASSIC_INQUIRY_DURATION |
8 |
Classic Bluetooth discovery duration. |
RSSI_PATH_LOSS_EXPONENT |
2.5 |
Distance estimation tuning value. |
TX_POWER_DEFAULT |
-59 |
Fallback TX power for BLE distance estimates. |
RSSI_MINIMUM |
-100 |
Ignore weaker signals than this threshold. |
MAX_DEVICE_AGE_MINUTES |
10 |
How long devices stay active without new sightings. |
ALERT_LINGER_MINUTES |
10 |
Presence duration threshold for linger alerts. |
LOG_LEVEL |
INFO |
Logging verbosity. |
These defaults come directly from backend/config.py.
If you want to override defaults locally, create a .env file in the repository root with values like:
HOST=127.0.0.1
PORT=8765
DB_PATH=aliradar.db
OUI_PATH=../data/oui.csv
SCAN_INTERVAL_SECONDS=3.0
CLASSIC_INQUIRY_DURATION=8
RSSI_MINIMUM=-100
LOG_LEVEL=INFOAgain, this file is optional; the app can run without it because all of these settings already have defaults.
The backend exposes these main routes under /api/v1:
GET /devices— list devices, with filters/sorting.GET /devices/{mac}— fetch one device and its recent sightings.PATCH /devices/{mac}— updateuser_labelandnotes.POST /devices/{mac}/favorite— toggle favorite state.GET /sightings— recent sightings by time window.GET /alerts/rules— list active alert rules.POST /alerts/rules— create a new alert rule.DELETE /alerts/rules/{alert_id}— delete an alert rule.GET /alerts/events— recent alert events.GET /stats— current scanner statistics.
GET /wsupgrades to a WebSocket connection.- Broadcasts include device updates, alert events, and stats updates consumed by the frontend stores/hooks.
AliRadar persists data to SQLite with SQLAlchemy models for:
devicessightingsalertsalert_events
The database file defaults to aliradar.db in the working directory, and migrations are applied on startup with Alembic before scanner initialization.
Run backend tests from the repository root after installing dependencies:
pytest backend/testsThe existing tests cover:
- API JSON serialization/deserialization behavior and validation for alert rule creation.
- pipeline integration for normalization, deduplication, classification, enrichment, and persistence logic.
The backend configures:
- console logging at
INFO - rotating file logging to
aliradar.logatDEBUG - max file size of 5 MB with 3 backups
This is useful when troubleshooting Bluetooth adapter issues or startup failures.
If pybluez2 cannot be imported, the project logs a warning and continues in BLE-only mode.
If both scanners fail to start, ScannerManager raises RuntimeError("No Bluetooth adapters available").
The frontend retries WebSocket connection attempts with exponential backoff up to 10 failed attempts before abandoning the connection.
Refresh data/oui.csv with:
python scripts/download_oui.pyThe OUI lookup is initialized on app startup using settings.OUI_PATH.
A large part of the backend pipeline is implemented and test-covered, while some UI panels still contain placeholder content such as the radar canvas and bottom timeline panel in frontend/src/App.jsx. That means the repository is already useful for backend/device discovery work, but the desktop UI is still evolving.
- Create a feature branch.
- Make your changes.
- Run the tests.
- Open a pull request.
If you are expanding functionality, context.md is the best high-level architecture reference in this repository.