add app, fix ble, use flash
This commit is contained in:
@@ -0,0 +1,77 @@
|
||||
# BabyMobile Audio Manager (PWA)
|
||||
|
||||
A dependency-free, **client-side** web app that scans for the BabyMobile XIAO
|
||||
(nRF52840) over Bluetooth LE and manages the audio files on it. No backend, no
|
||||
build step, nothing leaves your device — all audio conversion happens in the
|
||||
browser with the Web Audio API.
|
||||
|
||||
Pairs with the firmware in `../baby_mobile_v2/baby_mobile_v2.ino`.
|
||||
|
||||
## What it does
|
||||
|
||||
- **Scan & connect** to the `BabyMobile` BLE peripheral.
|
||||
- **Convert** any browser-decodable file (WAV/MP3/M4A/OGG/FLAC…) to a conformant
|
||||
mono PCM WAV — **8-bit / 8 kHz by default**, with 8/16-bit and 8/16/32 kHz
|
||||
selectable. The full WAV (44-byte header + data) is streamed intact; the
|
||||
firmware self-configures bit depth and sample rate from the header.
|
||||
- **Upload** to any of the 32 track slots, with a live progress bar driven by the
|
||||
device's status-notification byte count.
|
||||
- **Play / stop** any slot.
|
||||
- **Remember** what you uploaded per browser (localStorage), since the firmware
|
||||
exposes no track-listing command over BLE.
|
||||
|
||||
## BLE protocol used
|
||||
|
||||
| | UUID | Use |
|
||||
|---|---|---|
|
||||
| Service | `12340001-…` | advertised |
|
||||
| Cmd (write) | `12340002-…` | `0x02 <slot>` start upload · `0x03` finish · `0x04 <slot>` play · `0x05` stop · `0x06` list · `0x07 <slot>` delete |
|
||||
| Data (write-without-response) | `12340003-…` | raw WAV bytes, chunked to 180 B |
|
||||
| Status (notify) | `12340004-…` | tagged by byte 0: `0x00…` upload byte count (uint32 BE) · `0x80\|idx, bits, kHz, secs` list entry · `0xFF, n` list end · `0xD0, idx, ok` delete reply |
|
||||
|
||||
## Running it
|
||||
|
||||
Web Bluetooth requires a **secure context**: `https://` or `http://localhost`.
|
||||
|
||||
```sh
|
||||
# from this app/ directory — any static server works
|
||||
python -m http.server 8000
|
||||
# then open http://localhost:8000
|
||||
```
|
||||
|
||||
Deploy the folder as-is to any static host (GitHub Pages, Netlify, Cloudflare
|
||||
Pages…) to install it as a PWA from a phone. It's a complete app shell with a
|
||||
service worker, so it also launches offline once cached.
|
||||
|
||||
## Platform support
|
||||
|
||||
| Platform | BLE works? | How |
|
||||
|---|---|---|
|
||||
| Android | ✅ | Chrome or Edge; "Add to Home screen" installs the PWA |
|
||||
| Windows / macOS / Linux | ✅ | Chrome or Edge |
|
||||
| **iPhone / iPad** | ⚠️ via Bluefy | iOS Safari/WebKit has **no** Web Bluetooth |
|
||||
|
||||
### iOS setup (no App Store)
|
||||
|
||||
Apple doesn't ship Web Bluetooth, so a plain Safari PWA can't reach BLE. Use the
|
||||
free **[Bluefy – Web BLE Browser](https://apps.apple.com/app/bluefy-web-ble-browser/id1492822055)**:
|
||||
open this app's URL inside Bluefy and everything works. (Bluefy itself is the
|
||||
only App Store install needed — the app stays a web app.)
|
||||
|
||||
If you later want a true installable iOS app without Bluefy, wrap this same
|
||||
folder in [Capacitor](https://capacitorjs.com/) with `@capacitor-community/bluetooth-le`
|
||||
and reuse `ble.js`'s protocol constants.
|
||||
|
||||
## Notes & limits
|
||||
|
||||
- **Flash size:** the firmware's POC stores tracks in the nRF52840's internal
|
||||
LittleFS, which is small. 8-bit/8 kHz ≈ 8 KB per second of audio — keep clips
|
||||
short. If the device acknowledges fewer bytes than sent, the app warns you
|
||||
(flash likely full).
|
||||
- **Listing & delete are live:** on connect (and after every upload/delete) the
|
||||
app sends `0x06` to read the device's real track table, and `0x07` deletes a
|
||||
slot on the device. Track *titles* aren't stored on the device, so they're
|
||||
remembered locally and shown next to the live entries; an uploaded slot with no
|
||||
local name just shows "Track N".
|
||||
- **MTU:** data is chunked to 180 bytes to stay within a modest negotiated ATT
|
||||
MTU (firmware char max is 240).
|
||||
Reference in New Issue
Block a user