Files
baby-mobile/app

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.

# 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: 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 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).
  • Name shows as "BabyM" (truncated): the 128-bit service UUID fills the 31-byte advertisement, leaving room for only 5 name characters. The browser can't read the full GAP name (that service is blocklisted in Web Bluetooth). Fix it in the firmware by moving the name to the scan response, which has its own 31 bytes: replace Bluefruit.Advertising.addName(); with Bluefruit.ScanResponse.addName();.
  • Reconnecting after a disconnect: a just-disconnected peripheral leaves the link half-open briefly, so the first reconnect could fail until a page refresh. connect() now retries (3×, 600 ms backoff) after an explicit disconnect, which recovers without refreshing. Scanning matches on the service UUID first, so a truncated advertised name no longer breaks the name filter.