An offline-first, mesh-networked wearable for unhoused individuals — built for survival and housing dignity.
No internet. No router. No cell service. A low-cost ESP32-C3 smart-watch shows nearby shelter/resource availability over a self-healing ESP-NOW mesh, counts steps, detects falls, fires an SOS at the press of a button, and lets the wearer tap an iPhone to share a digital food-stamp credential over NFC — while spending most of its life in deep sleep to last on a tiny battery.
Hackathon project · Milpitas Hacks 2026
People living unsheltered often can't find which nearby shelter has an open bed or a meal right now, and have no reliable way to call for help in an emergency. Cellular coverage, data plans, and accounts are all barriers. HAVEN removes them: the network is the devices themselves. Shelters run beacons that broadcast live availability; cheap repeaters extend the range; the person wears a watch that listens, displays, and can call for help — with no infrastructure beyond the mesh.
[Shelter A] [Street corner] [Person] [iPhone]
Anchor Beacon ──ESP-NOW──▶ Repeater ──ESP-NOW──▶ Watch ◀──NFC──▶ taps to read
broadcasts beds/food floods frames shows resources, food-stamp token
+ ACKs SOS (TTL-bounded) SOS + fall alert
▲ │
└──────────────── authenticated SOS ──────────────────┘
(HMAC-signed)
Three firmware roles are built from one source tree (see platformio.ini):
| Role | Build env | Power | Job |
|---|---|---|---|
| Watch (wearable node) | node — src/main.cpp |
LiPo, deep-sleep | Shows resources, counts steps, fall+SOS, laptop host mode |
| Anchor Beacon | beacon — src/beacon.cpp |
Wall/USB | Broadcasts resources, ACKs SOS, escalates falls |
| Repeater | repeater — src/repeater.cpp |
Wall/USB/solar | Verifies + re-floods frames to extend range |
A laptop host tool (host/haven_host.py) connects to a
watch in host mode over BLE or WiFi for telemetry and configuration.
- NFC digital food stamps — the PN532 emulates an NFC Forum Type-4 tag; an iPhone taps the watch to read a signed food-stamp token (HMAC-signed Universal Link). Apple blocks third-party card emulation on the phone, so the watch is the tag and the phone is the reader.
- AI resource assistant (
web/) — the tap opens a mobile web app that verifies the token's HMAC and runs a multilingual, voice resource finder (shelters/meals/clinics, where the EBT balance works) on a free, open LLM (Ollama / MiniMax M2 / Groq / Gemini). The key (if any) + PSK stay server-side. - ESP-NOW mesh — connectionless broadcast; msg-id dedup + TTL flooding via repeaters; no pairing, no router.
- Authenticated frames — every payload is wrapped in an HMAC-SHA256 tag (shared PSK, mbedTLS) so forged beacons and spoofed/replayed SOS are dropped.
- SOS — hold the button (panic hold) → broadcast → two-way ACK → haptic confirmation. Payload carries reason, steps, battery, last beacon.
- Fall detection — MPU-6050 motion interrupt wakes the C3; software confirms
the free-fall→impact signature and starts a 10-second cancellable auto-SOS
(
reason:"fall",needs:"medical"). - Step counting — software pedometer. Accurate while awake/charging; approximate on battery (sampled in motion-triggered bursts — the MPU-6050 has no hardware pedometer).
- OLED text display — 0.96" SSD1306: nearest shelter, beds, steps, battery, SOS status, food-stamp balance.
- Hybrid power — deep-sleep on battery (timer + button + motion wake); fully awake with live screen + accurate steps + ready NFC while charging.
- Laptop host mode — double-press to expose BLE GATT + WiFi SoftAP/TCP
for live telemetry and JSON config (
sleep_min,privacy,fs_balance). - Privacy-preserving rotating node id — deliberate anti-tracking design for a vulnerable population; toggleable.
- Battery monitoring, graceful degradation (a missing sensor never bricks the watch), and no infinite loops — every error path sleeps.
Button map: hold = SOS · single tap = present food stamp · double tap = host mode.
include/
haven_mesh.h shared protocol: version, msg-id, TTL, dedup helpers
haven_frame.h HMAC-SHA256 authenticated framing (mbedTLS) + shared PSK
haven_imu.h MPU-6050 driver (raw Wire): software steps + fall + motion-wake
haven_nfc.h PN532 driver (raw Wire): Type-4 NDEF tag emulation for iPhone
haven_display.h text display abstraction: SSD1306 OLED / Serial / E-Ink
haven_host.h laptop host mode: NimBLE GATT + WiFi SoftAP/TCP
src/
main.cpp WATCH (ESP32-C3) — wake modes, SOS, fall, NFC, host, sleep
beacon.cpp ANCHOR BEACON (ESP32) — broadcast resources, ACK SOS
repeater.cpp REPEATER (ESP32) — verify → TTL-- → re-flood
host/
haven_host.py laptop companion (BLE + WiFi telemetry/config)
requirements.txt bleak (BLE mode only)
README.md host usage
web/ phone NFC resource assistant (food-stamp tap target)
server.py Flask: HMAC token verify + free-LLM streaming proxy
templates/ mobile web app (balance, chat, voice, multilingual)
resources.json the places the assistant may recommend
Dockerfile container image for the web app
docker-compose.yml web + local Ollama, one command
README.md web app setup + deploy
Makefile shortcuts: build / flash / host / web / docker
platformio.ini three build envs (watch=C3, beacon/repeater=ESP32)
HARDWARE.md full BOM, wiring diagrams, demo script, roadmap
PROJECT_HISTORY.md handoff/state doc — read this to resume cold
README.md this file
HAVEN has four runnable pieces: the firmware (watch / beacon / repeater), the laptop host tool, and the web AI assistant. You don't need all of them — pick what you want to demo.
Shortcut: a root
Makefilewraps everything —makelists targets, e.g.make build,make node,make host,make web,make web-docker. The step-by-step commands below are what those targets run.
- PlatformIO (
pip install platformio) — builds/flashes firmware. First build auto-downloads the ESP32 toolchains. - Python 3.9+ — for the host tool and web app.
- One free LLM backend for the web app — see step 4 (Ollama needs no key).
- Boards (optional, for real hardware): a Seeed XIAO ESP32-C3 (watch) and one or two classic ESP32 devkits (beacon/repeater). The firmware builds without any board attached.
Keep identical across every device:
ESPNOW_CHANNELandHAVEN_PSK(include/haven_mesh.h/include/haven_frame.h). The web app'sHAVEN_PSKmust match too, or food-stamp tokens won't verify.
The watch is the XIAO ESP32-C3; beacon and repeater are classic ESP32.
# Just build (no board needed — proves it compiles):
pio run -e node # watch
pio run -e beacon # shelter beacon
pio run -e repeater # range extender
# Build + flash + watch serial (board plugged in):
pio run -e node -t upload && pio device monitor -e node
pio run -e beacon -t upload && pio device monitor -e beacon
pio run -e repeater -t upload && pio device monitor -e repeaterWatch feature flags live in [env:node].build_flags of platformio.ini:
ENABLE_IMU, ENABLE_NFC, DISPLAY_OLED, ENABLE_BLE_HOST, ENABLE_WIFI_HOST,
and HAVEN_FS_HOST (the domain the NFC tap opens — point it at your web app).
Flash a beacon + a node, open both serial monitors. The watch wakes, hears
the beacon, and shows resources + step count on the OLED. Hold the button
for an SOS → the beacon prints the alert and ACKs → the watch buzzes. Drop a
repeater between them to extend range. (No boards? Read the serial logs in the
monitor; full script in HARDWARE.md.)
Pair a laptop with a watch in host mode (double-tap the button) for live telemetry + config over BLE or WiFi:
cd host
python3 -m venv .venv && source .venv/bin/activate
pip install -r requirements.txt # bleak (BLE only)
python haven_host.py ble # scan + stream telemetry
python haven_host.py wifi --set sleep_min=5 # after joining the watch's WiFi AP
python haven_host.py wifi --set fs_balance=7500 # set the food-stamp balance ($75.00)Details: host/README.md.
The phone NFC tap opens this. It uses any OpenAI-compatible free backend — Ollama (local, no account), Groq, or Gemini (free keys):
# Easiest: Ollama — fully local & free
# install from https://ollama.com, then:
ollama run llama3.2
cd web
python3 -m venv .venv && source .venv/bin/activate
pip install -r requirements.txt # flask + requests (no paid SDK)
export HAVEN_PSK='HAVEN-Mesh-PSK-CHANGE-ME!!!!!!!!' # must match firmware
python server.py # http://localhost:8000Prefer a cloud free tier? set LLM_BASE_URL / LLM_API_KEY / LLM_MODEL for
MiniMax M2 (via OpenRouter), Groq, or Gemini — examples in
web/README.md. Generate a test token URL and the full flow
(balance → multilingual voice chat) is in that doc.
One-command Docker (brings up the app + a local Ollama model):
make web-docker # or: cd web && docker compose --profile local up --build
# cloud LLM instead: put LLM_* in web/.env, then make web-docker-cloudTo connect the real watch, deploy the web app over HTTPS (e.g. ngrok http 8000)
and build the watch with -D HAVEN_FS_HOST='"your-host"'.
Full parts list, wiring diagrams, and the step-by-step demo are in HARDWARE.md.
- Mesh frames are authenticated with HMAC-SHA256 over a shared pre-shared key
(
include/haven_frame.h). Anyone without the key cannot forge resource updates or SOS messages. The committed PSK is a placeholder — generate and provision a real key before any deployment, and don't commit it. - Food-stamp token is an HMAC-signed Universal Link (same PSK); the iPhone / merchant verifies the signature and redeems the balance server-side. The watch only presents the token (read-only NDEF) — it never deducts locally.
- Host channel (laptop ↔ watch) is BLE-proximity / WPA2-protected, separate
from the mesh, so the host tool needs no mesh key. Change the SoftAP password
(
havenmesh123) before deployment. - Known gap: replay-hardening (a monotonic counter inside the signed payload) is on the roadmap — today the msg-id dedup only covers recent ids.
Early prototype firmware. All build targets compile clean on Espressif32 7.0.1 (ArduinoJson 6.21.6, NimBLE 1.4.3):
| Env | Board | Result | Flash |
|---|---|---|---|
node (watch) |
Seeed XIAO ESP32-C3 | ✅ | 32.5% (huge_app) |
beacon |
classic ESP32 | ✅ | 56.7% |
repeater |
classic ESP32 | ✅ | 56.3% |
The C3 watch image links the deep-sleep GPIO-wake path, the MPU-6050 driver, the PN532 NDEF tag-emulation, the SSD1306 OLED, NimBLE, and the HMAC mesh — together.
Not yet hardware-verified, and two parts specifically need bench work:
- PN532 Type-4 tag emulation vs a real iPhone (APDU/timing is iOS- and
board-sensitive — see
include/haven_nfc.h). - MPU-6050 thresholds — software step peak + free-fall/impact levels
(
include/haven_imu.h), and the C3 deep-sleep GPIO wake on real silicon.
Run the bench-test checklist before trusting it on hardware.
See HARDWARE.md → Roadmap for what's next.
This README is the canonical overview and is kept in sync with the project.
When roles, files, build flags, features, or the security model change, update
this file (and HARDWARE.md / host/README.md) in the same change.