Add barometer as an entity that iPhone/some iPads expose#4491
Add barometer as an entity that iPhone/some iPads expose#4491teancom wants to merge 7 commits intohome-assistant:mainfrom
Conversation
Uses CMAltimeter to read barometric pressure from the iPhone's built-in barometer chip and exposes it as a Home Assistant pressure sensor entity. The sensor converts from CMAltimeter's kilopascals to hPa for HA's pressure device class. Reuses the existing Motion & Fitness permission. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Tests cover authorization, availability, and error handling paths, verifies kPa-to-hPa conversion and rounding, and confirms that CMAltimeter updates are stopped after a single reading. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
This PR adds support for barometric pressure sensing to the Home Assistant iOS app by introducing a new BarometerSensor that leverages the device's built-in barometer via CoreMotion's CMAltimeter API. The sensor converts pressure readings from kilopascals to hectopascals (hPa) and reports them through the existing webhook sensor infrastructure.
Changes:
- Introduces a new
BarometerSensorclass that provides pressure readings from the device's barometer - Adds a
Barometerenvironment wrapper in AppEnvironment that abstracts the CoreMotion CMAltimeter API - Extends
WebhookSensorIdenum with a newpressurecase - Includes comprehensive test coverage for authorization, availability, data validation, and pressure conversion logic
- Updates Xcode project configuration to include the new sensor files in appropriate build phases
Reviewed changes
Copilot reviewed 6 out of 6 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
| Sources/Shared/API/Webhook/Sensors/BarometerSensor.swift | New sensor implementation that retrieves pressure data and converts it from kPa to hPa with 2 decimal place rounding |
| Sources/Shared/Environment/Environment.swift | Added Barometer struct wrapping CMAltimeter and registered BarometerSensor in the sensor container |
| Sources/Shared/API/Webhook/WebhookSensorId.swift | Added new pressure case to the sensor ID enum |
| Tests/Shared/Sensors/BarometerSensor.test.swift | Comprehensive test suite covering error conditions, data conversion, and proper cleanup |
| Tests/App/Webhook/WebhookSensorIdTests.swift | Updated test case count to 22 and added pressure sensor ID verification |
| HomeAssistant.xcodeproj/project.pbxproj | Added file references and build phase entries for both implementation and test files |
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #4491 +/- ##
=======================================
Coverage ? 42.71%
=======================================
Files ? 275
Lines ? 16277
Branches ? 0
=======================================
Hits ? 6953
Misses ? 9324
Partials ? 0 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
|
How's the permission request flow? I see it has "unauthorized" as one of the possible state |
I took the same approach as PedometerSensor and ActivitySensor, which are also bundled into the Motion & Fitness permission but otherwise are silently skipped in the list of available sensors. I figured this was enough of a niche thing that it shouldn't be something that pops up and requests the user grant permission how we do for Bluetooth, Notifications, or Camera (etc). |
Instead of only reading pressure during periodic sensor update cycles, keep CMAltimeter running and signal for updates when pressure changes by >= 0.1 hPa. Uses BaseSensorUpdateSignaler to automatically stop observation when the sensor is disabled. The signaler caches the latest CMAltitudeData so that sensors() uses the cached reading when the signaler is active, avoiding a one-shot read that would conflict with the signaler's continuous stream. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
startRelativeAltitudeUpdates is a streaming API, so an in-flight callback could arrive after stopUpdates(). Add a resolved flag to ensure only the first callback resolves the promise. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Move resolved guard before stopUpdates() so late in-flight callbacks become no-ops and cannot stop a subsequently started signaler stream - Add NSLock to protect latestData against data races between the altimeter callback queue and the thread reading from sensors() - Make both OperationQueues serial to eliminate concurrent callback concerns - Replace try? hang() with XCTAssertNoThrow in test to surface unexpected failures Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
BaseSensorUpdateSignaler.init registers as a SensorContainer observer, which can trigger observe() before the test's explicit call. This caused the handler capture variable to be overwritten non-deterministically. Fix: collect all registered handlers in an array and use the most recent one, making the test resilient to observer-driven re-registration. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Summary
I was reading this article https://www.howtogeek.com/your-phone-has-a-powerful-weather-instrument-hidden-inside/ - and it seemed neat! And adding support was actually pretty simple. Mostly just the one file plus tests and a little scattering of changes to the Xcode project file.
Screenshots
Link to pull request in Documentation repository
Documentation: home-assistant/companion.home-assistant#1309
Any other notes
Nothing bigger, just thought it would be neat.