-
-
Today: summary cards, each dose's status and a timeline of dose windows, Ring events and alerts.
-
Week: a 7-day grid per dose. Days without data show "No data", never a false "missed".
-
Alerts: history of "possibly missed" emails, with a preview and the "Checked in" status.
-
Settings: dose times with simple names, the Ring camera from the real Device List, and the Ring Playground connection.
-
Privacy: no video or images stored, only the time, type and camera of each event, deleted after 30 days.
-
One-time "I checked in" page from the alert email. It does not confirm that medicine was taken.
-
Mobile-first dashboard, with bottom navigation on phones.
-
"Look in now": a real Ring live view (WHEP) in the dashboard. It goes straight from Ring to the browser and is never recorded.
A gentle caregiver app for Amazon Ring: it notices when there has been no activity near the pills during a dose window, and says so softly, never as a fact.
Inspiration
I worked for about 20 years as a pharmacy assistant in community pharmacies in Bucharest, and I saw every day how families worry about whether an older parent takes their medicine.
Many older or vulnerable people live on their own, and their families check on them informally, if at all. Medication time is one of the moments when a quick "is everything okay?" matters most, but most solutions are either full video monitoring (invasive) or medical-alert hardware (expensive). I wanted something in between: a Ring camera that already looks at the place where the pills are kept can tell us whether there was any activity there, without anyone watching video.
The first version of Ring Med Watch (15 Sep 2026) did one thing: no motion at the front door for 12 hours meant one calm email to the caregiver. For this hackathon I turned it into a real caregiver app, built around one honest rule: motion does not prove a pill was taken, so the app never says "taken" or "missed" as a fact. It only ever says "activity seen near the pills (not a confirmation)", "not confirmed" and "possibly missed".
What it does
- Medication time windows. Up to six dose times (for example 08:00 and 20:00), each with an optional name like "Morning pills" (no medicine names), the Ring camera that looks at the pills, and a window around each dose.
- Gentle "possibly missed" alerts. If there is no activity at that camera during a dose window, the caregiver gets one email by Amazon SES. The text is written by Claude on Amazon Bedrock under strict instructions: calm, plain text, never certain, no medical advice, never suggesting a late or double dose, never naming a medicine. If the AI is unavailable, a fixed text with the same meaning is sent.
- "I checked in" link. Every alert ends with a one-time link to a small confirm page (a button, so mail scanners cannot resolve it by accident). It marks the alert as checked in on the dashboard. The token is random, works once, and only its hash is stored.
- At most one alert per dose window per day. The alert is reserved with a conditional write in DynamoDB before the email is sent, so overlapping checks, retries, restarts and redeploys can never send it twice.
- "Look in now" live view. On a "not confirmed" dose, and on Today, one button opens a live view of the chosen Ring camera inside the dashboard, using Ring's WHEP live view API. The video goes straight from Ring to the browser: nothing is recorded or stored, and the page says so. Ring ends the session by itself after 30 to 60 seconds.
- A web dashboard (mobile-first, password protected): Today, Week (days with no data are shown as "No data", never as missed), Alerts (with email preview), Settings and Privacy.
- A short daily summary email at 20:30 Europe/Bucharest, written by Bedrock and sent once a day.
- Privacy by design. No video or images are ever recorded or stored. Only the time, event type and camera of each Ring event are kept, and events and alerts delete themselves after 30 days.
How I built it
Ring APIs called for real from the running service (Google Cloud Run), using the Ring Playground token:
- Device List,
GET /v1/devices, to fill the camera dropdown with the Ring device name. - WHEP live view,
POST /v1/devices/{device_id}/media/streaming/whep/sessions, behind the "Look in now" button. The browser creates a receive-only WebRTC offer, my server relays only the SDP to Ring (with the Playground token, which never reaches the browser) and returns Ring's answer, and the video then flows directly from Ring to the browser. The session is ended with aDELETEon the session URL. I verified it live with the Playground's real Ring live stream. - Event History,
GET /v1/history/devices/{device_id}/events, followinglinks.next, behind a "Fetch Ring events" button. Every Ring event type appears in the timeline; only motion types count for dose checks. - The required
Authorization,User-AgentandHardware_Idheaders on every call. The temporary Playground token (valid 30 minutes) is pasted into Settings and kept only in memory: never stored, shown or logged.
Ring webhook: implemented and verified with signed test payloads. The endpoint POST /webhooks/ring parses Ring's v1.1 payload and verifies the HMAC signature (X-Signature); unsigned or tampered requests get HTTP 401. It is tested with signed test payloads. No real Ring webhook has arrived yet.
AWS: Amazon Bedrock (Claude Haiku 4.5) for the texts, Amazon SES for email, Amazon DynamoDB (one table, on-demand, TTL).
Google Cloud: Cloud Run runs the Node.js / Express app; two Cloud Scheduler jobs call it (dose-window check every 5 minutes, daily summary at 20:30).
Quality: automated tests cover the Ring client against a fake Ring API, webhook signatures, dose windows across time zones and daylight-saving changes, DynamoDB behaviour, alert de-duplication across restarts and overlapping runs, the one-time check-in token, and the exact approved wording of every medicine-related text.
Challenges I ran into
- Never overclaiming. A motion sensor cannot tell whether someone took medicine, so every status and AI instruction is written so the app can only say "activity seen (not a confirmation)", "not confirmed" and "possibly missed", with tests pinning that wording.
- Duplicate alerts. I first recorded an alert after sending the email, so overlapping checks could both send. I moved to reserve-then-send with a conditional DynamoDB write.
- Serverless state. Cloud Run can scale to zero, so events, settings, alerts and the once-a-day marker live in DynamoDB, and a scheduler wakes the service.
- The Ring Playground only creates
on_demandevents (see the honest limits).
Accomplishments that I'm proud of
- A caregiver flow that is genuinely gentle: calm plain-text emails, a check-in link instead of an alarm, and a dashboard that is honest about uncertainty, including "No data" instead of a false "missed".
- Real Ring API calls (Device List, Event History and the WHEP live view) running in production, not only mocks. The live view shows a real Ring stream in the dashboard, with the privacy promise printed right under it.
- Strong guarantees in a small app: one alert per dose window, one-time tokens, a token that never touches disk or logs.
What I learned
- Designing health-adjacent software is mostly designing what it must never say.
- Reserve-then-send is the simplest way to get "at most once" for emails on serverless infrastructure.
- Ring's Partner API is straightforward once the headers, the Event History pagination and the WHEP rules (receive-only transceivers, wait for ICE to finish) are right, and the Playground is a fast way to try the real endpoints.
What's next
Full Ring OAuth account linking; several caregivers and cameras; snooze or skip a dose; real motion events from a real camera; per-day dose schedules.
Honest limits: what is real and what is simulated
- The Ring Playground only creates
on_demandevents (a live view opened with the Motion button), not motion events. In my live test, Device List and Event History worked, and Fetch Ring events added the live view to the timeline as "Live view opened (Ring Playground)", clearly not counted as motion. - The live view was verified with the Ring Playground's live stream (a Ring demo feed from a Playground device), not with a camera in someone's home.
- The motion path is tested with signed webhook test payloads, unit tests against a fake Ring API, and the clearly labelled "Simulate motion (demo)" button, not with a real motion event from a Ring camera. Simulated events carry a "Simulation" badge, and alerts raised from the demo camera say in the email that the data is simulated. No real Ring webhook has arrived yet.
- I have no Ring device at home, so nothing was tested with a camera in someone's home.
- The refresh-token flow for account linking is covered only by unit tests.
- Ring Med Watch is not a medical device. If you are worried about someone's health, contact their doctor or pharmacist; in an emergency, call your local emergency number.
About the demo video
The narration in the demo video uses a synthetic (text-to-speech) voice, not a human voice.
Built with
Amazon Ring Partner API (Device List, Event History, WHEP live view, webhooks v1.1, Playground), Amazon Bedrock (Claude Haiku 4.5), Amazon SES, Amazon DynamoDB, Node.js, Express, WebRTC, Google Cloud Run, Google Cloud Scheduler.
Links
- Code (public, MIT license): https://github.com/iancuileana83-lab/ring-med-watch
- Live app (password protected; /health is public): https://ring-med-watch-30747896454.europe-west4.run.app
Built With
- amazon-bedrock
- amazon-dynamodb
- amazon-ses
- claude-code
- express.js
- google-cloud-run
- google-cloud-scheduler
- node.js
- ring
- webrtc
Log in or sign up for Devpost to join the conversation.