# Flipper Blue++ A custom Flipper Zero firmware build that turns the Bluetooth radio from an advertise-only peripheral into a full Bluetooth Low Energy platform, plus a suite of apps that use it. Stock Flipper firmware runs ST's "BLE Light" coprocessor stack, which can only advertise. Flipper Blue++ swaps in ST's **full** BLE stack (observer + central + GATT client), **exports the ST BLE command API to apps** so ordinary `.fap` files can scan, connect and run GATT, and throws in a few related unlocks (selected firmware internals, and the sub-GHz region gate). On top of that firmware it ships ten apps: a BLE scanner/explorer, a HID host, a sensor dashboard, a tracker detector, a GATT fuzzer, a beacon broadcaster, a GATT server, two sub-GHz tools and a battery monitor. Repo: `github.com/andydixon/flipper-bluepp` (the slug drops the `++` because GitHub repo names cannot contain `+`). > **Read this first.** These apps do **not** run on stock Flipper firmware. They > need the firmware `build.sh` produces (full BLE stack + exported command API, > and for the sub-GHz tools the region unlock). Battery Health is the only app > that would also run on stock firmware. Flashing this firmware also installs a > different radio stack; going back to official firmware restores the stock one. --- ## Contents - [Building and installing](#building-and-installing) - [The apps](#the-apps) — detailed per-app docs - [The firmware](#the-firmware) — full stack, exported APIs, sub-GHz unlock - [How the BLE apps work](#how-the-ble-apps-work) - [Limitations](#limitations) - [Troubleshooting](#troubleshooting) - [Repository layout](#repository-layout) --- ## Building and installing Requirements: Linux or macOS with `git`, `python3` and a few GB of disk. The firmware build system downloads its own ARM toolchain. ```sh ./build.sh # clone firmware 1.4.3, apply the patches, build firmware + apps ./build.sh flash # same, then flash over USB (Flipper connected, qFlipper closed) ./build.sh fap # rebuild only the apps (firmware already built once) ``` Environment variables: | Var | Default | Effect | |---|---|---| | `BLE_API` | `hci,gatt` | Which ST command groups to export (`min`, `all`, or any comma list of `hci,gap,gatt,hal,l2cap`). | | `EXPORT_FLASH` | `1` | Export the raw flash / option-byte API (set `0` to omit). | | `SUBGHZ_UNLOCK` | `1` | Remove the sub-GHz region gate (set `0` to keep it). | | `FW_TAG` | `1.4.3` | Firmware tag to clone. | | `FW_DIR` | `./flipperzero-firmware` | Where to clone. | | `JOBS` | `4` | Parallel compile jobs. | The result is a standard update package in `flipperzero-firmware/dist/f7-C/f7-update-local/`, containing the firmware, the **full radio stack**, and every app under `apps/` in its resources. To install without USB flashing, copy that folder to the SD card (e.g. `SD:/update/`) and open it in the Flipper's file browser. The individual `.fap` files are in `flipperzero-firmware/build/f7-firmware-C/.extapps/`; once the firmware is installed, app updates are just a file copy to the SD card. To iterate on an app with `ufbt` instead of the whole firmware tree, point it at the SDK the build emits: ```sh ufbt update --local=flipperzero-firmware/dist/f7-C/flipper-z-f7-sdk-local.zip cd bt_inspector && ufbt # -> dist/bt_inspector.fap ; `ufbt launch` installs it ``` The first build takes 5-15 minutes; later builds are incremental. While any BLE app runs, the Flipper's own advertising is stopped (and any phone link dropped), then restored on exit. Only one app owns the radio at a time. --- ## The apps All ten install to the Flipper's app menu. The BLE apps share one central/GATT-client layer (`libble/`) and follow the same pattern: a live scan list you pick a device from, then a per-app action. On the scan list, **Up/Down** move the selection, **OK** acts on the highlighted device, **Back** exits. ### BT Inspector A full BLE scanner and GATT explorer, in the spirit of BTInspector for iOS. - **Scan list** — every advertiser in range, sorted by RSSI and refreshed every 300 ms, showing name (or "(no name)"), RSSI in dBm with signal bars, address and vendor. Devices unseen for 60 s drop off. - **Device page** (OK on a device) — address and address type, current and best RSSI, packet count, advertising type (and whether it is connectable), and a decode of everything in the advertisement and scan response: - flags; advertised service UUIDs (16/32/128-bit, named when known); service data; Tx power; appearance; - manufacturer data, with decoders for **Apple Continuity** (iBeacon UUID/major/minor/Tx; Proximity Pairing with AirPods/Beats **model name** and **left / right / case battery** and charging state; Nearby Info and Action; Find My; AirDrop; Handoff; AirPlay; tethering), **Microsoft CDP** device type, **Google Fast Pair**, **Eddystone** (UID/URL/TLM, URL expanded), and **Exposure Notification**; - the raw advertisement and scan-response bytes. - **Connect** (OK on a connectable device) — negotiates MTU, discovers all primary services, and lists them. The first entry, **Read device info**, reads every readable characteristic of the Generic Access, Device Information and Battery services at once (name, appearance, model/serial numbers, firmware / hardware / software revisions, manufacturer, PnP ID, battery level). - **Characteristics** — each service opens to its characteristics with property flags: `R`ead, `W`rite, `w`rite-without-response, `N`otify, `I`ndicate, `B`roadcast. - **Characteristic page** — Read (OK), including custom 128-bit characteristics and long values (read-long). Values show as hex plus decoded forms: printable string, u8/i8, u16, u32, and SIG formats (battery %, appearance, preferred connection parameters, PnP ID, heart rate, temperature, humidity, pressure, Tx power, date/time). **Write** (Right) a value as text, hex bytes, or a number; **Notify/Unsub** (Left) subscribes to notifications/indications, locating the CCCD automatically. A timestamped **history** of every value seen for the open characteristic is kept, newest first. - **Log** — everything is written with timestamps to `SD:/apps_data/bt_inspector/bti__