This is a submission for the Presage SmartSpectra SDK Challenge
What I Built
Every night I ask the same question: am I ready to sleep, or do I need a bit more time to get there? For me a good night starts with the state of mind I go to bed in. Sleep trackers tell me how I slept after the fact. I wanted a simple check-in before bed, while I could still try a wind-down routine. So I built Nidra to compare an evening pulse-and-HRV reading with my own recent evenings. It's an experiment, not a prediction of how I'll sleep.
Nidra is an Android app. You stand your phone up in room light, close your eyes, and for 75–90 seconds the camera reads your pulse and heart rate variability. You get one number, Sleep Readiness, 0 to 100%, and one thing to try tonight. Then you check again and see before and after.
In the morning you drag the same scale to say how rested you feel. Over the week, the history puts your evening number next to your mornings, so you can see whether it's worth listening to.
No wearable, no account, no server of Nidra's own. A phone you already own, and your eyes closed.
Demo
The voice-over uses an AI clone of my own voice. What the video shows, recorded hand-held on my phone with the waits sped up: a real check with eyes closed and the moon filling as readings arrive, the score and "See why", tonight's suggestion, the three themes and the privacy note in Settings, then a second check in the Diya theme, where Rotate turns the camera picture upright, and a different suggestion when Calm comes out lower.
Code
rahulrao85
/
nidra
Sleep Readiness in 75 seconds: a camera check before bed using the Presage SmartSpectra SDK (Android, Kotlin)
Nidra
Most sleep trackers tell you how you slept once the night is over. Nidra asks a different question: how ready are you for sleep right now, while you can still do something about it?
Nidra is an Android app. Put your phone on a stand, close your eyes for 75–90 seconds, and the camera reads your pulse and heart rate variability. You get one number, Sleep Readiness from 0 to 100%, and one thing to try tonight.
Built for the Presage SmartSpectra SDK Challenge on DEV.
Nidra is a wellness estimate, not a medical device. It doesn't diagnose or treat anything, and it shouldn't guide health decisions.
The routine
- Check, 75–90 seconds. It runs at least 75 seconds and up to 90 while it waits for an HRV reading. A tone tells you to close your eyes. At the end, one beep means it scored; three low beeps and…
Kotlin and Jetpack Compose, com.presagetech:smartspectra 3.4.0 from Maven Central, MIT licence. The README has setup steps: add your own free Presage API key to local.properties and run on a physical Android phone. There is also a simulated mode that runs every screen without a camera or a key, and 14 unit tests for the scoring, all passing on 13-Nov-2026.
The whole SDK integration is one file: SdkVitalsSource.kt.
How It Responds to Human Signals
| SmartSpectra signal | What Nidra does with it |
|---|---|
Pulse rate (cardio.pulseRateList) |
The Body slider: tonight's pulse against your own usual evening |
HRV: RMSSD and Baevsky stress index (cardio.hrvList) |
The Calm slider, 60% of the score |
Confidence values and ValidationStatus
|
Decide whether to show a number at all |
SDK hint text |
Shown on screen so you can fix your framing |
| Blinking and face landmarks | Reduced on arrival to "eyes closed %" and a blink count, recorded but not scored. The points are dropped. |
- While you sit: the main slider and the moon move as readings arrive. That live number is only the pulse part, measured against your pulse earlier in the same check; the final score adds HRV. Tones mean you never have to open your eyes: a beep to start, one beep when it has scored, three low beeps and a buzz when it couldn't.
- The score: Sleep Readiness is an experimental personal comparison, not a probability, a medical measure or a forecast of your sleep. Body (40%) and Calm (60%) combine into one number, rounded to the nearest 5%; the 40/60 weights are provisional. Both compare you with your own past evenings (the median of up to 14), not a population norm, so 50% means "your usual evening". Your first check has nothing to compare with, so it starts at 50%.
- The suggestion: whichever slider is lower picks it. Lower Body: three minutes of guided slow breathing, paced towards 6 breaths a minute. Lower Calm: five minutes writing tomorrow's to-do list.
- When it won't answer: Nidra withholds the score when pulse or HRV confidence is below threshold (40 for pulse, 50 for HRV), or when fewer than 70% of the sampled seconds had an accepted view. Brief invalid frames, like a second with no face, are tolerated.
What testing on a real phone taught me
All of this came from checks on my own phone (a Samsung Galaxy M35, which isn't on Presage's tested list).
- One minute isn't enough. Pulse was confident from about 16 seconds, but HRV first appeared at 69 seconds in my runs. So the check runs at least 75 seconds, and up to 90 while it waits for HRV. Other phones may differ.
- Breathing didn't make it. I planned a Breath slider. On a stand, in room light, breathing rate swung from 4.6 to 75 a minute with confidence never above 43. I'd rather drop a signal than show a number I don't trust, so breathing is a guided exercise that Nidra paces but doesn't measure.
- Closing your eyes looks like looking away. My first properly eyes-closed checks gave no score. The log showed pulse confidence 100 and HRV confidence 95, but the SDK marked the face "not forward" for 61 of 75 seconds. Closed eyes read as not facing the camera. Nidra now accepts that one status, while pulse and HRV confidence still have to pass.
- Is it repeatable? Calm is 60% of the score, and my early HRV readings on this one phone were 21, 21, 46 and 74 ms across four separate runs. So I ran three checks in a row on 14-Nov-2026: two with the phone on a stand, then one hand-held, the way most people would actually do it:
| Check | Phone | Pulse (bpm) | Pulse confidence | RMSSD (ms) | Stress index | HRV confidence | Eyes closed | Score |
|---|---|---|---|---|---|---|---|---|
| 1 | Stand | 83 | 97% | 76 | 1.5 | 71% | 53% | 80% |
| 2 | Stand | 79 | 99% | 19 | 2.0 | 88% | 5% | 45% |
| 3 | Hand-held | 80 | 44% | 43 | 0.9 | 63% | 13% | 75% |
Pulse held steady: 79 to 83 bpm across all three, even hand-held. HRV did not: RMSSD swung from 19 to 76 ms within two minutes, and because Calm is 60% of the score, the score swung from 80% to 45% with it. So one reading isn't something to trust on its own. That's why Nidra compares you with your own median of past evenings and asks for a re-check, and why I'd read it as "roughly where am I tonight", not a precise number.
The hand-held check still gave a score, but pulse confidence fell from about 98% to 44% and the camera flagged movement. Holding the phone also means watching the screen, so your eyes stay open (13% closed here). The phone-on-a-stand design with start and end tones exists for exactly that reason.
Prize Categories
Best Thoughtful Real-World Use. A lot of people go to bed wired and only find out once they're lying awake. Nidra is built for that moment: one number, a dark screen by default, tones so your eyes stay closed, a check short enough to actually do every night, and a refusal to score when the camera can't be trusted. Consent comes first, Nidra keeps its data on the phone, and the consent screen says plainly what the Presage SDK may send (details below).
Most Creative or Delightful Use. The same number drives three bedtime themes: Moonlight, where the moon fills from crescent to full; Diya, where a lamp flame grows and steadies as you settle; and Plain, for people who only want the number. The check asks you to close your eyes, so tones, not the screen, tell you when to start and stop.
Consent and Data Handling
- Consent: the first screen explains what the camera does and what is kept, and nothing runs until you agree. Android then asks for camera permission. The camera runs only during a check, shows a "Camera on" label, and stops when the check ends, when you tap Cancel, or when you leave the app. It's for checking yourself, never someone else.
- Processing: the SDK measures on the phone. Nidra doesn't store camera frames or images, and SmartSpectra image output is switched off.
- Storage: no video, photos, face images or face landmarks are kept. For each check Nidra saves a few numbers in the app's private storage: pulse, RMSSD, stress index, the confidence values, eyes-closed %, blink count and the score. It also keeps your morning ratings and to-do list.
- Sharing: Nidra itself has no account, no analytics and no backend, and Android backup is off. The SDK contacts Presage to validate the API key and record usage.
- AI services: Nidra uses none; the score and suggestions come from fixed rules. Presage says some vital metrics may be sent to its AI insights service. Nidra doesn't request, use or show those insights. I haven't verified whether SDK 3.4.0 sends vitals to that service with Nidra's settings. During my checks the app did make regular small network requests, so treat pulse and HRV as potentially shared with Presage until that's confirmed.
-
SDK telemetry: the optional telemetry is off, with
enableTelemetry = false. - Retention and deletion: data stays on the phone until you delete it or uninstall. Settings has one button that deletes everything.
Nidra is a wellness estimate, not a medical device. It makes no diagnosis or treatment claims and doesn't guide health decisions. One evening reading can't predict a night's sleep, which is why it's called readiness, why it's treated as an experiment, and why the history puts your mornings next to it.
I built Nidra with help from Claude Code. The testing, the decisions about what to drop, and the evenings in front of the camera were mine.
Top comments (0)