Inspiration
Every home monitoring product on the market alerts you when something happens. A door opens, a camera sees movement, your phone buzzes.
For somebody living alone, the dangerous thing is that nothing happens. A fall at six in the morning produces no door event, no motion, no alert. It produces silence, and silence is exactly what those products are built to ignore.
So I wanted to build the opposite: something that watches for the absence of events rather than their presence.
The problem nobody solves
A silence timer is easy and useless, because the most common reason a house is quiet is that nobody is in it. A system that phones a daughter at work every time her mother goes to the shops gets switched off inside a week.
The real problem is telling two things apart:
Absent. She left. The silence is expected and means nothing.
Unresponsive. She is home and has stopped moving. The silence matters.
At four in the afternoon these look identical: seven hours of nothing. The only thing that separates them is whether a door opened at the start.
What it does
Stillwatch classifies every camera as transit, meaning it watches a way in or out, or interior, meaning it watches inside the home. Then it reads the sequence rather than a threshold. A stretch of interior silence that opens with a door event is somebody leaving. The same stretch with no door event is somebody who stopped.
Around that one judgement:
- It learns each household's own rhythm. When they are normally active, and how long they are normally still, hour by hour. Half an hour at midday and eight hours at midnight, learned from their own weeks rather than configured. This is why it does not ring anybody at two in the morning because a person is asleep.
- It judges the present against that, on a ladder from normal to alert, with away sitting beside the ladder rather than on it.
- It says why, in a sentence, every single time. "Nothing has moved since 10:08, which is 37 min. The longest she normally stays still at that time of day is 23 min." Somebody is being asked to telephone their mother at six in the morning. They are owed the reason.
- It tells the family only when it is worth telling them, through Amazon SNS, in a sentence written by Amazon Bedrock from facts the engine already settled.
- Somebody can answer it. A daughter phones, finds her well, presses one button. The episode ends, everybody else on the list is told who checked, and it stops asking. Movement alone could not have ended it, because somebody can be perfectly fine and still not moving.
- It never looks at anyone. No video is ever requested, stored or analysed. It reads only when a camera saw movement and when it did not. That is the reason a family will put it in a bedroom corridor.
How I built it
The engine is a pure function of the events. The judgement depends on the set of events, not the order they arrived in. Webhooks retry and arrive out of order, so there is a test suite that shuffles a whole day twenty five times and insists the answer is identical, and another that holds the door event back until last and checks an outing does not become an alarm.
Ring's words are translated in exactly one place. The adapter turns Ring's event types into the engine's own, which is why the same engine runs against a feeder and against real hardware without changing. It is written against Ring's own envelope and checked against Ring's live device API.
Event ids come from the event, a hash of the device, the kind and the timestamp, never a counter. Ingestion has to be safe to repeat, and a counter makes two runs produce different ids for the same event.
Five Amazon services, each earning its place:
- Ring Partner API for the events themselves, over a signed webhook with HMAC-SHA256 checking.
- Amazon Bedrock writes the opening sentence of each message. It sits deliberately off the detection path, so if it fails a deterministic sentence goes out instead and nobody is left uninformed by a language model.
- Amazon SNS delivers. Subscribers own their own subscriptions, so Stillwatch holds nobody's address.
- Amazon CloudWatch receives the service's own pulse, published outward on every judgement. An alarm set on missing data is what makes a dead service alarmable, because a dead service and a quiet house produce exactly the same thing: nothing.
- AWS Lambda on Amazon EventBridge asks the site the same question a visitor would, from outside, every five minutes. Everything else that watches Stillwatch shares fate with it. Only an outside request can catch a deployment that is perfectly healthy while the site is unreachable.
The failure semantics are the part I am most careful about. A dead service looks exactly like a quiet house. A page that fails to load looks exactly like a page with nothing to report. Both read as reassurance, which makes them the two most dangerous states this software has. So if the feed dies, the store is unreachable or the judge stops running, it says it cannot tell. Several of the checks exist only to stop a failure being reported as calm.
Challenges
No Ring hardware. Ring is not sold in the country I built this in, so everything was built through the developer tooling alone. That turned out to be the most useful thing I can report back: it is the case the tooling exists to serve and the case it currently serves least well. Two of the eleven entries in my friction log are about nothing else.
The Developers Playground simulates a live view session, with the WHEP and SDP exchange for a video stream, and offers no way to make a motion or doorbell event arrive at a registered webhook. That is the only part of the API this product consumes.
So I built ring-event-simulator, a standalone generator of realistic multi-week household histories, published separately under MIT with its own tests. The event path is then exercised by a feeder that posts to the real endpoint, over HTTPS, with the real signing key, in Ring's own payload shape. Nothing downstream of that endpoint is stubbed: the signature is checked, the envelope is unwrapped by the Ring adapter, written to the store idempotently and judged by the same engine that would judge a real home.
The README states exactly which parts have spoken to Ring's own servers and which have not. Anybody reading the repository should not have to guess.
Telling a learned rhythm from a coincidence. Early versions alarmed on quiet evenings. The fix was to key the tolerated quiet to the hour the silence began rather than to a daily average, which is why a household that settles at 23:00 is given eight hours and the same household at 10:00 is given twenty three minutes.
Accomplishments
- The transit and interior discriminator works, and it is the thing I would defend line by line.
- Twelve test suites and five static checks, covering order independence, replayed deliveries, batch isolation, forged signatures and whether a failure can ever be reported as a quiet house.
- Static checks that compare the two entry points against each other, check every state colour against every surface it lands on, and refuse any inline script the content policy would silently reject.
- An eleven entry friction log and product feedback on every service, each priced by what it actually cost rather than by how much I would like it.
- The simulator is useful to anybody else building against the Ring API without hardware, which is why it is its own repository under its own licence.
What I learned
That the hard part of a monitoring product is not detection, it is knowing what your own silence means. Most of the engineering here is about refusing to report calm when the truth is that nothing is known.
Also that explainability is a product requirement rather than a nice to have. A confidence score from a model nobody can interrogate is not actionable at six in the morning. A sentence naming the room, the time and the normal limit is.
What's next
Households this reads wrongly. The engine assumes one person, so a visitor, a
second occupant or a night shift can look like something they are not. A
failing case written as a scenario is worth more than a fix, because it says
what correct would have been. That is what CONTRIBUTING.md asks for first.
Mini challenge: Open Source
Stillwatch is Apache 2.0 and public at github.com/kadian-arch/stillwatch, with a contributing guide, a code of conduct, issue templates, a pull request template and a private security reporting policy. GitHub reports its community health at 100%.
A second project was published separately during the hackathon: ring-event-simulator, at github.com/kadian-arch/ring-event-simulator, under MIT. It generates realistic multi-week Ring style event streams for one person living alone, so inactivity detection can be built and tested without a house, a camera or API access. It has no dependencies, its own test suite, CI, a changelog and issue templates. It exists because building on the Ring API without hardware is hard, and anybody in that position can use it directly.
The contributing guide names the five things that have to stay true whatever else changes, including that nothing may ever request or store video, and that a failure must report that it cannot tell rather than reporting calm.
Mini challenge: AWS Builder
Five Amazon services, each solving a problem the product actually has.
Ring Partner API for the events, over a signed webhook with HMAC-SHA256 checking and a single adapter translating Ring's event types into the engine's own.
Amazon Bedrock writes the opening sentence of each notification from facts the engine has already settled. It sits off the detection path on purpose, so a model failure degrades the wording and never the judgement.
Amazon SNS delivers to caregivers who own their own subscriptions, so the service holds nobody's address.
Amazon CloudWatch receives the service's own heartbeat, published outward on every judgement. The alarm is set on missing data, which is the setting that makes an absence alarmable, and that matters more here than anywhere: a dead service and a quiet house produce exactly the same thing.
AWS Lambda on an Amazon EventBridge schedule asks the public health endpoint the same question a visitor would, every five minutes, from outside the deployment. Everything else that watches Stillwatch shares fate with it, so only an outside request can catch a deployment that is healthy while the site is unreachable.
docs/PRODUCT_FEEDBACK.md gives the considered view of each one, including onboarding time, what got in the way and what would change the most, plus thirteen specific feature requests priced by what they cost.
Built With
- amazon-bedrock
- amazon-cloudwatch
- amazon-eventbridge
- amazon-sns
- aws-lambda
- css
- flask
- heroku
- hmac
- html
- javascript
- postgresql
- python
- ring-partner-api
- webhooks
Log in or sign up for Devpost to join the conversation.