Inspiration

It started with frustration. Sitting at a library computer, trying to book a study room for a group project, every single room showed as reserved. But walking through the building, half of them were completely empty. Chairs pushed in, lights off, nobody there. The reservations were just ghost bookings left behind by students who had long since gone home.

I asked around and found out this is a universal problem. At almost every university, students book rooms, use them for 20 minutes, and the 2-hour reservation sits there blocking everyone else. Universities have tried policy-based solutions, fines, reservation limits, honor systems, and none of them work reliably.

I wanted to build something that just knew whether a room was actually occupied, and acted on that automatically. No app. No check-in button. No relying on students to cancel their bookings. Hardware that watches the room and does the right thing on its own.


What it does

RoomGuard is a small autonomous device placed in a study room that continuously monitors whether the room is actually occupied, and automatically flags the reservation for release if nobody has been detected for 15 minutes.

It uses dual sensor logic to determine occupancy:

  • An HC-SR04 ultrasonic sensor measures the distance to the nearest object. If something is within 50cm, someone is sitting at the desk.
  • An MPU-6050 accelerometer/gyroscope detects vibration and micro-movement on the desk surface, typing, writing, a bag being set down.

If either sensor triggers, the room is marked occupied. Both must be quiet for 15 minutes before the auto-release fires. This dual approach dramatically reduces false positives.

Every reading is sent to a cloud backend every 2 seconds and logged to a PostgreSQL database. A live web dashboard at roomguard.vercel.app shows the current room status, raw sensor readings, a history log, and a warning banner when auto-release triggers. No app download required, works from any browser, on any device.


How I built it

Hardware. The brain is an ESP32-S3 microcontroller, chosen for its built-in WiFi. I wired the HC-SR04 to the TRIG and ECHO GPIO pins, and connected the MPU-6050 over I2C (SDA/SCL). The firmware is written in Arduino C++. Every 2 seconds it reads both sensors, runs occupancy logic locally, and POSTs the result as JSON to my API over WiFi.

Backend. The API is a Next.js 15 App Router route handler deployed on Vercel. It accepts sensor data from the ESP32, runs the 15-minute auto-release logic using in-memory room state, and persists every event to PostgreSQL on Neon. The GET endpoint returns current room state plus the last 20 events.

Frontend. The dashboard is a React/TypeScript page polling /api/sensor every 2 seconds. It shows a color-coded status indicator, raw sensor readings, an empty-room timer, and a scrollable event log. The landing page uses Framer Motion for scroll-triggered animations and features a floating live sensor card that pulls real data. The entire stack is deployed on Vercel.


Challenges I ran into

Hardware from zero. I have never touched hardware before this hackathon. Learning to wire sensors, read datasheets, understand I2C, debug floating GPIO pins, and get reliable ultrasonic readings, all within 36 hours, was the steepest learning curve i've ever faced.

Sensor noise and false positives. The HC-SR04 returns wildly incorrect readings when aimed at certain surfaces or angles. I implemented smoothing and threshold tuning to get stable detection. The MPU-6050 was similarly sensitive, an air conditioning vent was enough to trigger it. Calibrating sensitivity without making the sensor useless took significant iteration.

WiFi reliability. The ESP32 would occasionally drop its WiFi connection and fail to reconnect without a full reboot. I implemented automatic reconnection logic in the firmware loop to recover gracefully.

TypeScript strictness in production. Vercel builds with strict TypeScript mode. The Framer Motion animation variants used inferred types that worked locally but failed in production, ease: [0.22, 1, 0.36, 1] was inferred as number[] instead of a 4-tuple, and type: "spring" was inferred as string instead of a literal. Both required as const assertions to resolve.


Accomplishments that I'm proud of

I'm most proud of the fact that it actually works. A physical device, wired by hand, reads real sensor data, posts it to a cloud API over WiFi, persists it to a database, and renders it live on a dashboard, all within 36 hours, starting from zero hardware knowledge.

I'm also proud of the cost story: the entire hardware bill is under $8 per room. Enterprise room management systems that do the same thing cost $50,000 or more. RoomGuard proves the problem is solvable at a price point any university could actually deploy.


What I learned

I learned that hardware is humbling. A software bug gives you a stack trace. A hardware bug gives you a reading of 0cm and no idea why. I learned to read datasheets, think about voltage levels, and debug by elimination rather than by error message.

I also learned how much you can build with Next.js and a small PostgreSQL database when the schema is simple and the API is purpose-built. The entire backend is under 80 lines of code.


What's next for RoomGuard

  • Real reservation system integration, Connect the auto-release flag to university booking APIs (EMS, 25Live, Outlook) so cancellations actually happen in the system students use.
  • Multi-room deployment, Each ESP32 registers with a room ID, and the dashboard shows an entire building's worth of rooms in real time.
  • PIR sensor addition, A passive infrared sensor would handle edge cases like a very still person reading quietly.
  • Analytics dashboard, Surface insights from accumulated data: peak hours, average session length, ghost reservation frequency by room.
  • Battery power, Move from USB to a LiPo battery with ESP32 deep sleep, making the device fully wireless and easier to deploy anywhere.

Built With

Share this project:

Updates