Skip to content

Commit 879ce16

Browse files
author
Magrathean UK
committed
fix(vehicle): refresh geofence from stream positions
The streaming path inserted driving positions without resolving their geofence, leaving the vehicle summary and MQTT geofence values stale when crossing nested geofences between API polls. Resolve the geofence in the same repository checkout as each streamed position and store it before broadcasting the summary. This mirrors the normal API-position path and keeps nested-geofence transitions current.
1 parent 7054517 commit 879ce16

3 files changed

Lines changed: 71 additions & 4 deletions

File tree

lib/teslamate/vehicles/vehicle.ex

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -660,14 +660,26 @@ defmodule TeslaMate.Vehicles.Vehicle do
660660
) do
661661
case {status, stream_data} do
662662
{:available, %Stream.Data{shift_state: shift_state}} when shift_state in ~w(D N R) ->
663-
{:ok, %{elevation: elevation}} =
664-
call(data.deps.log, :insert_position, [drv, create_position(stream_data, data)])
663+
{elevation, geofence} =
664+
Repo.checkout(fn ->
665+
{:ok, %{elevation: elevation} = position} =
666+
call(data.deps.log, :insert_position, [drv, create_position(stream_data, data)])
667+
668+
geofence = call(data.deps.locations, :find_geofence, [position])
669+
{elevation, geofence}
670+
end)
665671

666672
vehicle = merge(data.last_response, stream_data)
667673
now = DateTime.utc_now()
668674

669-
{:keep_state, %{data | last_used: now, last_response: vehicle, elevation: elevation},
670-
broadcast_summary()}
675+
{:keep_state,
676+
%{
677+
data
678+
| last_used: now,
679+
last_response: vehicle,
680+
elevation: elevation,
681+
geofence: geofence
682+
}, broadcast_summary()}
671683

672684
{_status, %Stream.Data{}} ->
673685
{:keep_state_and_data, schedule_fetch(0, data)}

test/support/mocks/locations.ex

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,11 @@ defmodule LocationsMock do
2424
end
2525

2626
@impl true
27+
def handle_call({:find_geofence, %{latitude: 90, longitude: 45.01}}, _from, state) do
28+
geofence = %GeoFence{id: 1, name: "Garage", latitude: 90, longitude: 45.01, radius: 20}
29+
{:reply, geofence, state}
30+
end
31+
2732
def handle_call({:find_geofence, %{latitude: 90, longitude: 45}}, _from, state) do
2833
geofence = %GeoFence{id: 0, name: "South Pole", latitude: 90, longitude: 45, radius: 100}
2934
{:reply, geofence, state}

test/teslamate/vehicles/vehicle/streaming_test.exs

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ defmodule TeslaMate.Vehicles.Vehicle.StreamingTest do
33

44
import ExUnit.CaptureLog
55

6+
alias TeslaMate.Locations.GeoFence
67
alias TeslaMate.Vehicles.Vehicle.Summary
78
alias TeslaMate.Vehicles.Vehicle
89
alias TeslaApi.Stream
@@ -156,6 +157,55 @@ defmodule TeslaMate.Vehicles.Vehicle.StreamingTest do
156157
refute_receive _
157158
end
158159

160+
test "updates the geofence from streaming positions", %{test: name} do
161+
now = DateTime.utc_now()
162+
now_ts = DateTime.to_unix(now, :millisecond)
163+
164+
events = [
165+
{:ok,
166+
online_event(now_ts,
167+
drive_state: %{timestamp: now_ts, latitude: 90, longitude: 45}
168+
)},
169+
fn -> Process.sleep(10_000) end
170+
]
171+
172+
:ok = start_vehicle(name, events)
173+
174+
assert_receive {:start_state, car, :online, date: _}
175+
assert_receive {:insert_position, ^car, %{latitude: 90, longitude: 45}}
176+
assert_receive {ApiMock, {:stream, _eid, func}} when is_function(func)
177+
178+
assert_receive {:pubsub,
179+
{:broadcast, _, _,
180+
%Summary{state: :online, geofence: %GeoFence{name: "South Pole"}}}}
181+
182+
stream(name, %{shift_state: "D", est_lat: 90, est_lng: 45, time: now})
183+
assert_receive {:start_drive, ^car}
184+
assert_receive {:insert_position, drive, %{latitude: 90, longitude: 45}}
185+
186+
assert_receive {:pubsub,
187+
{:broadcast, _, _,
188+
%Summary{state: :driving, geofence: %GeoFence{name: "South Pole"}}}}
189+
190+
stream(name, %{shift_state: "D", est_lat: 90, est_lng: 45.01, time: now})
191+
assert_receive {:insert_position, ^drive, %{latitude: 90, longitude: 45.01}}
192+
193+
assert_receive {:pubsub,
194+
{:broadcast, _, _,
195+
%Summary{state: :driving, geofence: %GeoFence{name: "Garage"}}}}
196+
197+
stream(name, %{shift_state: "D", est_lat: 90, est_lng: 45.1, time: now})
198+
assert_receive {:insert_position, ^drive, %{latitude: 90, longitude: 45.1}}
199+
assert_receive {:pubsub, {:broadcast, _, _, %Summary{state: :driving, geofence: nil}}}
200+
201+
stream(name, %{shift_state: "D", est_lat: 90, est_lng: 45, time: now})
202+
assert_receive {:insert_position, ^drive, %{latitude: 90, longitude: 45}}
203+
204+
assert_receive {:pubsub,
205+
{:broadcast, _, _,
206+
%Summary{state: :driving, geofence: %GeoFence{name: "South Pole"}}}}
207+
end
208+
159209
test "discards fetch result", %{test: name} do
160210
me = self()
161211
now = DateTime.utc_now()

0 commit comments

Comments
 (0)