Inspiration

As college students with questionable meal schedules, the two of us depended heavily on university dining halls to sustain our livelihoods. However, we would often order food or arrive at a dining hall only to see lines snaking around the side of the building.

Packed is designed to fix this issue - if we know dining hall A is, well, packed, the 10-minute walk to dining hall B might seem a bit more appealing.

What it does

Packed is a privacy-preserving campus busyness sensor that helps students avoid packed dining hall lines.

Using ambient Wi‑Fi noise, an ESP32 turns “how 'loud' is this room?” into a 0–100 density score. A campus map then displays a scale of Quiet, Moderate, or Busy so you can decide whether this spot is worth it — or whether the walk to somewhere else would be a better way of spending your time.

Key Features

  • Ambient Wi‑Fi sniffing on an ESP32 — aggregates only, no MAC addresses
  • Empty-room calibration plus an optional subjective density anchor (C, S0–S100 over Serial)
  • On-device density score (0–100) mapped to Quiet / Moderate / Busy
  • Phone-hotspot uplink so the board can post without campus Wi‑Fi
  • Supabase readings table plus a keyed Edge Function for device inserts
  • Next.js campus map (MapLibre / OpenFreeMap) with search, light/dark theme, and a live ESP status blinker
  • Live polling about every 5 seconds from the latest sensor reading, plus a “people over time” chart
  • Honest Live mode today: one real board at Goodwin Hall; other dining pins are Preview, not fake live sensors

How we built it

We started by combining a cheap RF sensor with a simple score and a glanceable map, so you get “should I go now?” without cameras or a campus IT integration.

  • ESP32 firmware (PlatformIO) — Promiscuous sniff in short windows (~15s for judging, 5 min for a real install). Keeps average RSSI and packet count only, then steps a smoothed density accumulator on the device.
  • Empty-room calibration — Three quiet windows become density 0 and persist in NVS. A manual S<number> anchor maps current packet activity to a score you pick, instead of “% change from last window.”
  • Phone hotspot STA — The board joins a hotspot, not campus enterprise Wi‑Fi, then HTTPS POSTs a reading.
  • Supabase — Stores avg_rssi, packet_count, density, and location. Public clients can read; inserts go through an Edge Function that checks a device key. Simulated history lives in a separate sim_readings table so charts don’t mix with ESP32 rows.
  • Next.js + MapLibre — Campus map, status bands, search, collapsible detail docks, and a recommendation strip that refuses to compare halls that don’t have a live sensor.
  • HTML/CSS (Hum tokens, light + dark) — Built for a fast glance on a phone: one live pin, one status, skip the packed line.

System Design

Ambient Wi‑Fi frames
  → ESP32 (promiscuous sniff, calibrate, on-device density)
  → Phone hotspot (STA uplink)
  → Edge Function (device key) → Supabase readings
  → Next.js map polls ~5s → Quiet / Moderate / Busy

Challenges we ran into

We had one radio doing three jobs: promiscuous sniff + Wi‑Fi STA + HTTPS. Uploads would flake unless we paused sniff, posted, then resumed — Serial became the source of truth.

Calibration was the other trap. Rolling window-to-window % change made an empty room look busy. We switched to an empty-room baseline, added a subjective density anchor, and had to rescale saved packet counts when we cut the sniff window from 30s to 15s.

Getting firmware, hotspot, Supabase, and the map to agree on one location ID was a challenge in itself.

Accomplishments that we're proud of

Shipping an end-to-end path in a weekend: sniff → score → store → map.

Keeping the privacy story real — aggregates only, no MACs, no cameras.

Watching density actually move when people crowd the board with phones on, and having Serial match the dashboard.

Staying honest in the UI: coming-soon pins for halls without hardware, and a recommendation that says “only one live sensor” instead of inventing a quieter dining hall.

What we learned

User-first design when the real question is “should I walk over?” not “exactly how many people?”

How to troubleshoot a single ESP32 radio when sniff, connect, and POST all fight each other.

How tricky it is to combine firmware, RF calibration, a backend, and a live map into one smooth demo — and to stay honest about what isn’t live yet.

What's next for Packed

More sensors: Put the same node in a real dining hall and add a second board so Live recommendations compare two places, not one.

Campus as config: Make the 'campus selection' skill more generalized so Virginia Tech could be swapped out for any other school with a profile (map, pins, location IDs) instead of forking the app.

History & “come back around…”: Sparklines from recent readings and a simple slope guess so you know if it’s calming down — still relative busyness, still no tracking.

Built With

Share this project:

Updates

Submission history