Inspiration
Every night, restaurants near campus throw away good food while students nearby skip meals. The two sides never find each other in time. The Greek word xenia (ξενία) means hospitality to strangers, and we built a tool around it: Xenia, a way for restaurants to hand off leftover meals and for students to find them live.
What it does
Xenia has two parts.
The Xenia box (hardware). At closing time, restaurant staff wave a hand over the box for every leftover meal. An ultrasonic sensor counts each wave, a buzzer confirms it, and a 7-segment display shows the running count. The box is housed in a Horse enclosure designed in CAD, a hospitality gift in the Greek tradition.
The Xenia web app (xeniasurplus.us). Students see nearby restaurants as islands on a map, with live meal counts. They can:
- see which restaurants have meals now (3 or more is available, 1-2 is low, 0 is none)
- tap Take a meal to claim one and get a pickup code
- install the site on their phone as an app
It works in both directions. When a student claims a meal, the count drops in the database and the number on the box's display drops to match. The box and the app always agree.
How we built it
Arduino box --USB--> bridge.py --HTTPS--> FastAPI (Vultr) --> Tiger Data
^ |
+---------- new count sent back by the bridge ---------------+
- Hardware: Arduino Uno, ultrasonic sensor, buzzer, single 7-segment display, Horse enclosure designed in CAD.
- Bridge: The Arduino has no Wi-Fi, so a small Python script reads its serial output, posts it to our server, and polls for changes to send back (
SET,n). - Server: FastAPI on a Vultr Ubuntu VM, run by systemd and fronted by Caddy with automatic HTTPS.
- Frontend: a single-page progressive web app (installable, with a service worker) in a Greek island theme.
- Safety: device key on sensor writes, atomic meal claims so two students can't take the last meal, a 20-second claim cooldown per visitor, and stale sensor data (older than 15 minutes) shown as "unknown" rather than wrong.
How we used Tiger Data
Every wave is a time-series event, so we used Tiger Data (TimescaleDB) for what it does best:
- a hypertable for sensor readings
- a continuous aggregate (
meals_hourly) that powers each restaurant's history and busy-hour view - compression (after 1 day) and a retention policy (7 days)
- a pooled connection from the API
Challenges we ran into
- Our kit had no weight sensor, so we counted hand waves instead of weighing food.
- Making a Wi-Fi-less Arduino talk to the cloud in both directions.
- Keeping the box, database, and web page in agreement.
- Going live in a weekend: DNS, HTTPS certificates, and locking things down.
Accomplishments that we're proud of
- A full hardware-to-cloud loop that works live: wave, count, phone, claim, display drops.
- A real public site at xeniasurplus.us, installable on a phone.
- A theme that carries the whole product, from the name to the horse.
What we learned
- A time-series database gave us history and trends almost for free.
- Hardware-to-cloud work is mostly serial formats, reconnects, and staleness.
- Safety details matter the moment something is public.
What's next for Xenia
- Gemini photo check: verify the count against a photo of the box automatically (not built yet).
- Standalone boxes: a Wi-Fi board like an ESP32, so no laptop is needed.
- Load cells alongside the hand wave for more accurate counts.
- Pickup and notifications: staff verify pickup codes, and students get alerts from favorite spots.
Built with
arduino c++ python fastapi postgresql tiger-data timescaledb vultr caddy html css javascript pwa cad
Try it: xeniasurplus.us