Explain why the In Bed health sensor can be unavailable - #5655
Conversation
Nothing writes `HKCategoryValueSleepAnalysis.inBed` samples on its own: Apple Watch records the sleep stages but not time in bed, and the iPhone only writes it once "Track Time in Bed with iPhone" is on. Without such a sample the night isn't tracked for that stage, so `health_sleep_in_bed` reports `unavailable` while the other sleep sensors report a duration, which reads like a bug from the sensor list. Give a metric an optional footer, shown under its row in the Apple Health sensor list, and use it on In Bed to say where its samples have to come from. The footer is a case rather than a string so the metric catalog stays plain data and the wording resolves in the user's language.
There was a problem hiding this comment.
🟢 Approval recommended
The change is small and well-scoped, adds localized user guidance for the one affected metric, and includes a targeted unit test for the new catalog behavior.
Pull request overview
This PR clarifies why the Apple Health “In Bed” sleep sensor may remain unavailable by introducing an optional, localized per-metric footer that can be rendered under that sensor row in the Health sensor list.
Changes:
- Added
HealthKitMetric.footer(optional) plus aHealthKitMetricFooterenum that resolves localized explanatory text at read time. - Updated the sleep metric catalog so only
health_sleep_in_bedcarries a.timeInBedSourcefooter, with a unit test asserting no other metric has a footer. - Updated the Health sensor settings row UI to render the footer text under the toggle when present, and added the English localization key + SwiftGen accessor.
File summaries
| File | Description |
|---|---|
| Tests/Shared/Sensors/HealthKitMetricCatalog.test.swift | Adds a test ensuring only the “In Bed” metric has a footer. |
| Sources/Shared/Resources/Swiftgen/Strings.swift | SwiftGen accessor update for the new localized footer string. |
| Sources/Shared/API/Webhook/Sensors/Health/HealthKitMetricFooter.swift | Introduces the footer enum and localization resolution (footer.text). |
| Sources/Shared/API/Webhook/Sensors/Health/HealthKitMetric+Sleep.swift | Adds footer support to the sleep metric factory and assigns it to “In Bed”. |
| Sources/Shared/API/Webhook/Sensors/Health/HealthKitMetric.swift | Adds the footer property to the shared metric model with a defaulted initializer parameter. |
| Sources/App/Settings/Sensors/Health/HealthSensorRow.swift | Renders the optional footer under the metric’s toggle row in the settings list. |
| Sources/App/Resources/en.lproj/Localizable.strings | Adds the English copy for the “In Bed” footer. |
Review details
- Files reviewed: 7/7 changed files
- Comments generated: 0
- Review effort level: Lite
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #5655 +/- ##
==========================================
- Coverage 35.29% 35.28% -0.02%
==========================================
Files 1013 1014 +1
Lines 73124 73136 +12
==========================================
- Hits 25812 25808 -4
- Misses 47312 47328 +16
☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
AI Policy
Select exactly one option that describes AI usage in this contribution:
Summary
The In Bed sleep sensor reports
unavailablewhenever nothing writesinBedsamples to Apple Health. Apple Watch records the sleep stages but not time in bed, so on a Watch-only setup this one sensor looks broken while the other sleep sensors report a duration.A metric can now carry an optional footer, shown under its row in the Apple Health sensor list. In Bed uses it to say where its samples have to come from: turn on "Track Time in Bed with iPhone" in Health > Sleep > Options, or use a sleep tracking app that records it.
Screenshots
Link to pull request in Documentation repository
Documentation: home-assistant/companion.home-assistant#
Any other notes
The footer is an enum case rather than a stored string, so the metric catalog stays plain data and the wording resolves in the user's current language.