
NOISY flag) and again on the server (a good / noisy / poor / no_signal classifier) so motion artifacts and off-body noise never masquerade as a heartbeat.NOISY flag when the trace is junk.{bpm, quality, rr_intervals, waveform, …} to /api/ingest over HTTPS (TLS CA pinned), authenticated by a per-device key. In parallel it publishes BPM over BLE.good/noisy/poor/no_signal. It cross-checks the lead-off flag against the actual waveform (so muscle motion doesn't false-trip "offline") and corroborates BPM against the RR-derived and waveform peak rates (so noise can't invent an impossible rate). Only good windows feed HRV/history./api/live (SSE) for the real-time trace and reads /api/history, /api/events for the charts. A phone can connect straight to the BLE Heart Rate service with any compatible app.esp32dev (WROOM-32) AD8232 ECG module single-lead analog front-end, 3.5 mm electrode jack SSD1306 OLED, 128×32, I²C SH1106 also works (U8g2 has a constructor) ECG electrode pads + 3-lead snap cable RA / LA / RLdocs/hardware/wiring.md, docs/hardware/diy-powerbank.md, and docs/hardware/bench-psu.md.docs/hardware/wiring.md.Wire.begin(23, 22):firmware/monitor/ (Arduino framework, esp32dev).include/ecg.h): derivative → square → moving-window integral, 0.20 s refractory (48–180 bpm). A host unit test (firmware/monitor/test/test_ecg.cpp) exercises T-waves, baseline wander, EMG, mains, and the SNR metric — compile and run on any PC with g++.0x180D / measurement 0x2A37, plus a custom status characteristic (BPM, quality, lead-off, SNR) — coexists with WiFi.OTA_PASS=… pio run -e esp32dev_ota -t upload (mDNS heart-monitor.local) after one USB bootstrap flash.include/ca_cert.h (setCACert).secrets.h (WiFi creds, device key, OTA password) is gitignored — only the .example template is committed.bun:sqlite, TypeScript.src/signal.ts): scale-invariant gating + lead-off / BPM corroboration (see How it works). Only good feeds HRV/history.POST /api/token) for native apps. Multi-user — a primary admin plus extra accounts via an AUTH_USERS env; passwords stored as salted scrypt hashes.vite-plugin-pwa). Views: Live (BPM + scrolling trace), History (samples, HRV, click-to-render any stored waveform, time-in-zone), Events, and a Guide (electrode placement)..env, the SQLite DB) are gitignored and never committed — this repo ships only .example templates.bun:sqlite + Solid PWA), on-device + server signal-quality gating, Pan-Tompkins detector, TLS CA pinning, password-gated OTA, BLE Heart Rate streaming, multi-user dashboard auth. Full detail in docs/roadmap.md.secrets.h.devices).device_id is currently pinned to 1).bun test + firmware host test), SQLite backups, offline alerting, structured logging, CSV/JSON export.snrMin tunable via NVS/BLE instead of recompiling.docs/hardware/ecg-frontend-upgrade.svg).firmware/monitor/ ESP32 firmware: acquisition, detection, OLED, WiFi ingest, BLE, OTA firmware/bringup/ Minimal bring-up sketches for the sensor/display server/ Bun + Hono + bun:sqlite ingest/API/dashboard server frontend/ SolidJS installable PWA (the dashboard UI) docs/hardware/ Wiring tables + schematics (SVG/PNG), battery & supply guides docs/ Design spec, build plan, roadmapPosted Aug 7, 2026
Built a full-stack ESP32 ECG monitor with on-device beat detection, OLED, BLE/Wi-Fi streaming, a Bun API, SQLite history, and a SolidJS PWA.
0
1