Sign inSign up

gabrielsv01/bluetooth-api-manager

By gabrielsv01

•Updated 3 days ago

Image
0

2.4K

gabrielsv01/bluetooth-api-manager repository overview

⁠Bluetooth API Manager

A single-container manager for the Bluetooth adapter on your Umbrel host. It discovers devices, lets you watch the data they transmit, and exposes a REST + WebSocket API so other systems can drive the adapter.

⁠Status

PhaseScopeState
0Skeleton: Docker/Umbrel manifests, FastAPI serving the React UI✅ done
1BLE core: device discovery, live GATT data, REST + WebSocket API, web UI✅ done
2Audio streaming over A2DP (file upload + URL)✅ done
3File transfer over OBEX Object Push✅ done
4Observability: levels, /api/stats, adapter info, status bar, Logs tools✅ done

⁠Architecture

One container, front and back separated in code (KISS deploy, DRY logic):

  • backend/ — FastAPI. adapters/bluetooth.py is the single Bluetooth layer (built on bleak, which talks to the host's BlueZ over D-Bus). core/events.py is one event bus that feeds both the WebSocket and the Logs view.
  • frontend/ — React + Vite. Built in a Docker stage and served as static files by FastAPI. Tabs: Devices, Live Data, Logs.

The web UI and any external caller use the same REST API. Interactive docs are at /docs.

⁠Host requirements

Bluetooth lives on the host, not in the container, so this app needs:

  • A working Bluetooth adapter and the BlueZ stack (bluetoothd) on the host.
  • network_mode: host and the system D-Bus socket (both set in docker-compose.yml).
  • privileged: true for HCI scanning / A2DP.

Audio streaming (Phase 2) additionally needs an audio server (PulseAudio/ PipeWire) on the host — many headless Umbrel installs don't have one, so treat it as best-effort.

⁠Key API endpoints

MethodPathPurpose
GET/api/devicesList discovered/connected devices (name, RSSI, …)
POST/api/devices/{addr}/connectConnect to a device
GET/api/devices/{addr}/servicesList GATT services & characteristics
POST/api/devices/{addr}/readRead a characteristic
POST/api/devices/{addr}/writeWrite a characteristic (hex or text)
POST/api/devices/{addr}/notifyEnable/disable notifications
GET/api/audio/sinksList audio output sinks (Bluetooth ones flagged)
POST/api/audio/playPlay an uploaded file or a url to a sink
POST/api/audio/stopStop playback
POST/api/files/sendSend a file to a device over OBEX (multipart)
GET/api/statsObservability snapshot: adapter, counts, audio, event stats
WS/wsLive event stream (devices, GATT data, logs)
⁠Audio & file transfer (Phases 2–3) — host notes
  • Audio (A2DP): the Bluetooth speaker must be exposed as a PulseAudio sink by an audio server on the host. Mount the Pulse socket and set PULSE_SERVER (see the commented lines in docker-compose.yml). Without a host audio server, /api/audio/sinks returns an error (shown in the UI).
  • File transfer (OBEX): the container starts its own session D-Bus + obexd (entrypoint.sh). The target device must be paired and accept incoming files (Object Push).

⁠Local development

# Backend (needs a Linux host with BlueZ for real Bluetooth)
cd code/backend
pip install -r requirements.txt
PORT=5157 STATIC_DIR= python -m uvicorn backend.main:app --reload --port 5157
#   run from the code/ dir so `backend` is importable:  cd code && uvicorn backend.main:app --reload

# Frontend (proxies /api and /ws to the backend)
cd code/frontend
npm install
npm run dev

⁠Build & run the container

cd code
docker build -t gabrielsv01/bluetooth-api-manager:1.0.0 .
# or just: docker compose up --build   (from the app root)

Tag summary

Content type

Image

Digest

sha256:1a3b3dcb0…

Size

257.8 MB

Last updated

3 days ago

docker pull gabrielsv01/bluetooth-api-manager