mirror of
https://github.com/home-assistant/iOS.git
synced 2026-07-02 14:29:42 -05:00
Fix passive zone lookup in zone-only location privacy mode (#4385)
## Bug When the **Location Sent** setting is set to **Zone Only**, automations that trigger on entering a passive zone stop working while the same automations work correctly with **Exact** location. ### Root cause In zone-only mode, `SubmitLocation` derives the current zone by GPS lookup via `RLMZone.zone(of:in:)` rather than using the zone associated with the incoming region event (the event zone may be the one being *exited*, so a fresh lookup is needed). That lookup filtered using `trackablePredicate`: ```swift .init(format: "TrackingEnabled == true && isPassive == false") ``` The `isPassive == false` condition meant that when the device was inside a passive zone, the lookup returned `nil`, causing the payload to report `not_home` to Home Assistant instead of the passive zone so no automation triggered. In **Exact** mode this doesn't occur because raw GPS coordinates are sent and Home Assistant resolves the zone server-side, where passive zones are handled correctly. Note that passive zones *are* monitored for region enter/exit events by the iOS app (`ZoneManager` filters only on `TrackingEnabled`, not `isPassive`), so the region event does fire, the zone is simply lost during the zone-only lookup step. ## Fix Remove `isPassive == false` from the filter in `RLMZone.zone(of:in:)`, replacing `trackablePredicate` with a `TrackingEnabled == true`-only filter. This method performs a GPS-to-zone lookup and has no reason to exclude passive zones. `trackablePredicate` is left unchanged and continues to be used correctly in `GeocoderSensor`.
This commit is contained in:
@@ -251,7 +251,7 @@ public final class RLMZone: Object, UpdatableModel {
|
||||
Current.realm()
|
||||
.objects(Self.self)
|
||||
.filter("%K == %@", #keyPath(serverIdentifier), server.identifier.rawValue)
|
||||
.filter(trackablePredicate)
|
||||
.filter("TrackingEnabled == true")
|
||||
.filter { $0.circularRegion.containsWithAccuracy(location) }
|
||||
.sorted { zoneA, zoneB in
|
||||
// match the smaller zone over the larger
|
||||
|
||||
@@ -130,6 +130,25 @@ class RealmZoneTests: XCTestCase {
|
||||
$0.Longitude = -122.41263128786335
|
||||
$0.Radius = 90.0
|
||||
},
|
||||
with(RLMZone()) {
|
||||
$0.entityId = "zone_passive"
|
||||
$0.serverIdentifier = "fake1"
|
||||
// fort mason, sf
|
||||
$0.Latitude = 37.80535
|
||||
$0.Longitude = -122.43194
|
||||
$0.Radius = 100.0
|
||||
$0.isPassive = true
|
||||
$0.TrackingEnabled = true
|
||||
},
|
||||
with(RLMZone()) {
|
||||
$0.entityId = "zone_disabled"
|
||||
$0.serverIdentifier = "fake1"
|
||||
// crissy field, sf
|
||||
$0.Latitude = 37.80290
|
||||
$0.Longitude = -122.45290
|
||||
$0.Radius = 100.0
|
||||
$0.TrackingEnabled = false
|
||||
},
|
||||
]
|
||||
|
||||
try realm.write {
|
||||
@@ -162,5 +181,17 @@ class RealmZoneTests: XCTestCase {
|
||||
in: server2
|
||||
)
|
||||
XCTAssertEqual(inside3?.entityId, "zone3")
|
||||
|
||||
let insidePassive = RLMZone.zone(
|
||||
of: CLLocation(latitude: 37.80535, longitude: -122.43194),
|
||||
in: server1
|
||||
)
|
||||
XCTAssertEqual(insidePassive?.entityId, "zone_passive", "passive zone with TrackingEnabled should be returned")
|
||||
|
||||
let insideDisabled = RLMZone.zone(
|
||||
of: CLLocation(latitude: 37.80290, longitude: -122.45290),
|
||||
in: server1
|
||||
)
|
||||
XCTAssertNil(insideDisabled, "zone with TrackingEnabled = false should be excluded")
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user