Skip to content

Commit bd96e31

Browse files
committed
Fix compound state tuple handling after dce479c refactoring
The dce479c commit converted :driving, :charging, :updating states to simple atoms but left :asleep, :offline, :suspended as compound tuples, causing Summary.format_state and various handlers to fail. Fixes: - Summary.format_state: Handle compound tuples like {:asleep, interval}, {:offline, interval} - driving: Add handler for {:asleep, _} in :driving state (was only matching {:offline, _}) - driving offline: Fix offline handler to not overwrite {:offline, _} without checking timeout - charging: Convert {:charging, cproc} to simple :charging atom - updating: Convert {:updating, _update_id} to simple :updating atom - :summary call: Include driving_status in attrs map for Summary.into - vehicle_in_service handler: Use :driving instead of {:driving, _, _} All 91 vehicle tests and 333 total tests pass.
1 parent 2e13112 commit bd96e31

2 files changed

Lines changed: 83 additions & 68 deletions

File tree

lib/teslamate/vehicles/vehicle.ex

Lines changed: 77 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -37,15 +37,11 @@ defmodule TeslaMate.Vehicles.Vehicle do
3737
# :confirmed_fake – stream reported power=nil, treating as fake online
3838
# :confirmed_real – stream reported numeric power, treating as real online
3939
pre_online_check: :idle,
40-
# Future fields for extracting DB records from state tuples (not used yet)
41-
# These will allow moving from {:driving, status, %Log.Drive{}} to :driving + data fields
42-
# %Log.Drive{} | nil (will replace drive in {:driving, _, drive})
40+
# DB records for active vehicle states (previously embedded in state tuples)
4341
current_drive: nil,
44-
# %Log.ChargingProcess{} | nil (will replace cproc in {:charging, cproc})
4542
current_charging_process: nil,
46-
# %Log.Update{} | nil (will replace update in {:updating, update})
4743
current_update: nil,
48-
# :available | {:unavailable, n} | {:offline, last} (will replace status in {:driving, status, _})
44+
# Sub-state for driving: :available | {:unavailable, n} | {:offline, last_vehicle}
4945
driving_status: :available
5046
end
5147

@@ -233,7 +229,8 @@ defmodule TeslaMate.Vehicles.Vehicle do
233229
healthy?: healthy?(data.car.id),
234230
elevation: data.elevation,
235231
geofence: data.geofence,
236-
car: data.car
232+
car: data.car,
233+
driving_status: data.driving_status
237234
})
238235

239236
{:keep_state_and_data, {:reply, from, summary}}
@@ -282,15 +279,15 @@ defmodule TeslaMate.Vehicles.Vehicle do
282279
{:keep_state_and_data, {:reply, from, :ok}}
283280
end
284281

285-
def handle_event({:call, from}, :suspend_logging, {:driving, _, _}, _data) do
282+
def handle_event({:call, from}, :suspend_logging, :driving, _data) do
286283
{:keep_state_and_data, {:reply, from, {:error, :vehicle_not_parked}}}
287284
end
288285

289-
def handle_event({:call, from}, :suspend_logging, {:updating, _}, _data) do
286+
def handle_event({:call, from}, :suspend_logging, :updating, _data) do
290287
{:keep_state_and_data, {:reply, from, {:error, :update_in_progress}}}
291288
end
292289

293-
def handle_event({:call, from}, :suspend_logging, {:charging, _}, _data) do
290+
def handle_event({:call, from}, :suspend_logging, :charging, _data) do
294291
{:keep_state_and_data, {:reply, from, {:error, :charging_in_progress}}}
295292
end
296293

@@ -468,7 +465,7 @@ defmodule TeslaMate.Vehicles.Vehicle do
468465
Logger.info("Vehicle is currently in service", car_id: data.car.id)
469466

470467
case state do
471-
{:driving, _, _} when data.current_drive != nil ->
468+
:driving when data.current_drive != nil ->
472469
drive = data.current_drive
473470

474471
{:ok, %Log.Drive{distance: km, duration_min: min}} =
@@ -641,7 +638,7 @@ defmodule TeslaMate.Vehicles.Vehicle do
641638

642639
vehicle = merge(data.last_response, stream_data, time: true)
643640

644-
{:next_state, {:driving, :available, drive},
641+
{:next_state, :driving,
645642
%Data{
646643
data
647644
| last_response: vehicle,
@@ -678,11 +675,11 @@ defmodule TeslaMate.Vehicles.Vehicle do
678675
def handle_event(
679676
:info,
680677
{:stream, %Stream.Data{} = stream_data},
681-
{:driving, status, drv},
682-
%Data{} = data
678+
:driving,
679+
%Data{driving_status: :available, current_drive: drv} = data
683680
) do
684-
case {status, stream_data} do
685-
{:available, %Stream.Data{shift_state: shift_state}} when shift_state in ~w(D N R) ->
681+
case stream_data do
682+
%Stream.Data{shift_state: shift_state} when shift_state in ~w(D N R) ->
686683
{:ok, %{elevation: elevation}} =
687684
call(data.deps.log, :insert_position, [drv, create_position(stream_data, data)])
688685

@@ -692,7 +689,7 @@ defmodule TeslaMate.Vehicles.Vehicle do
692689
{:keep_state, %{data | last_used: now, last_response: vehicle, elevation: elevation},
693690
broadcast_summary()}
694691

695-
{_status, %Stream.Data{}} ->
692+
%Stream.Data{} ->
696693
{:keep_state_and_data, schedule_fetch(0, data)}
697694
end
698695
end
@@ -723,7 +720,7 @@ defmodule TeslaMate.Vehicles.Vehicle do
723720

724721
vehicle = merge(data.last_response, stream_data, time: true)
725722

726-
{:next_state, {:driving, :available, drive},
723+
{:next_state, :driving,
727724
%Data{
728725
data
729726
| last_response: vehicle,
@@ -903,7 +900,8 @@ defmodule TeslaMate.Vehicles.Vehicle do
903900
healthy?: healthy?(data.car.id),
904901
elevation: data.elevation,
905902
geofence: data.geofence,
906-
car: data.car
903+
car: data.car,
904+
driving_status: data.driving_status
907905
})
908906

909907
:ok =
@@ -1053,7 +1051,7 @@ defmodule TeslaMate.Vehicles.Vehicle do
10531051

10541052
:ok = disconnect_stream(data)
10551053

1056-
{:next_state, {:updating, update},
1054+
{:next_state, :updating,
10571055
%{
10581056
data
10591057
| last_state_change: DateTime.utc_now(),
@@ -1067,8 +1065,7 @@ defmodule TeslaMate.Vehicles.Vehicle do
10671065

10681066
{drive, data} = start_drive(create_position(vehicle, data), data)
10691067

1070-
{:next_state, {:driving, :available, drive},
1071-
%{data | current_drive: drive, driving_status: :available},
1068+
{:next_state, :driving, %{data | current_drive: drive, driving_status: :available},
10721069
[
10731070
broadcast_summary(),
10741071
schedule_fetch(driving_interval(), data)
@@ -1099,7 +1096,7 @@ defmodule TeslaMate.Vehicles.Vehicle do
10991096

11001097
:ok = disconnect_stream(data)
11011098

1102-
{:next_state, {:charging, cproc},
1099+
{:next_state, :charging,
11031100
%Data{
11041101
data
11051102
| last_state_change: DateTime.utc_now(),
@@ -1122,22 +1119,33 @@ defmodule TeslaMate.Vehicles.Vehicle do
11221119

11231120
#### :charging
11241121

1125-
def handle_event(:internal, {:update, {:offline, _vehicle}}, {:charging, _}, data) do
1122+
def handle_event(:internal, {:update, {:offline, _vehicle}}, :charging, data) do
11261123
Logger.warning("Vehicle went offline while charging", car_id: data.car.id)
11271124

11281125
{:keep_state_and_data, schedule_fetch(data)}
11291126
end
11301127

1131-
def handle_event(:internal, {:update, {:asleep, _vehicle}} = event, {:charging, cproc}, data) do
1128+
def handle_event(
1129+
:internal,
1130+
{:update, {:asleep, _vehicle}} = event,
1131+
:charging,
1132+
%Data{current_charging_process: cproc} = data
1133+
) do
11321134
Logger.warning("Vehicle went asleep while charging (?)", car_id: data.car.id)
11331135

11341136
{:ok, _} = call(data.deps.log, :complete_charging_process, [cproc])
11351137
Logger.info("Charging / Aborted", car_id: data.car.id)
11361138

1137-
{:next_state, :start, data, {:next_event, :internal, event}}
1139+
{:next_state, :start, %{data | current_charging_process: nil},
1140+
{:next_event, :internal, event}}
11381141
end
11391142

1140-
def handle_event(:internal, {:update, {:online, vehicle}}, {:charging, cproc}, %Data{} = data) do
1143+
def handle_event(
1144+
:internal,
1145+
{:update, {:online, vehicle}},
1146+
:charging,
1147+
%Data{current_charging_process: cproc} = data
1148+
) do
11411149
data = %{data | last_used: DateTime.utc_now()}
11421150

11431151
case vehicle do
@@ -1150,7 +1158,7 @@ defmodule TeslaMate.Vehicles.Vehicle do
11501158
|> Map.get(:charger_power)
11511159
|> determince_interval()
11521160

1153-
{:next_state, {:charging, cproc}, %{data | current_charging_process: cproc},
1161+
{:next_state, :charging, %{data | current_charging_process: cproc},
11541162
[broadcast_summary(), schedule_fetch(interval, data)]}
11551163

11561164
%Vehicle{charge_state: %Charge{charging_state: state}} ->
@@ -1177,44 +1185,44 @@ defmodule TeslaMate.Vehicles.Vehicle do
11771185
def handle_event(
11781186
:internal,
11791187
{:update, {:offline, _}},
1180-
{:driving, :available, drive},
1181-
%Data{} = data
1188+
:driving,
1189+
%Data{driving_status: :available} = data
11821190
) do
11831191
Logger.warning("Vehicle went offline while driving", car_id: data.car.id)
11841192

1185-
{:next_state, {:driving, {:unavailable, 0}, drive},
1193+
{:next_state, :driving,
11861194
%{data | last_used: DateTime.utc_now(), driving_status: {:unavailable, 0}},
11871195
schedule_fetch(5, data)}
11881196
end
11891197

11901198
def handle_event(
11911199
:internal,
11921200
{:update, {:offline, _}},
1193-
{:driving, {:unavailable, n}, drv},
1194-
%Data{} = data
1201+
:driving,
1202+
%Data{driving_status: {:unavailable, n}} = data
11951203
)
11961204
when n < 15 do
1197-
{:next_state, {:driving, {:unavailable, n + 1}, drv},
1205+
{:next_state, :driving,
11981206
%{data | last_used: DateTime.utc_now(), driving_status: {:unavailable, n + 1}},
11991207
schedule_fetch(5, data)}
12001208
end
12011209

12021210
def handle_event(
12031211
:internal,
12041212
{:update, {:offline, _}},
1205-
{:driving, {:unavailable, _n}, drv},
1206-
%Data{} = data
1213+
:driving,
1214+
%Data{driving_status: {:unavailable, _n}} = data
12071215
) do
1208-
{:next_state, {:driving, {:offline, data.last_response}, drv},
1216+
{:next_state, :driving,
12091217
%{data | last_used: DateTime.utc_now(), driving_status: {:offline, data.last_response}},
12101218
[broadcast_summary(), schedule_fetch(30, data)]}
12111219
end
12121220

12131221
def handle_event(
12141222
:internal,
12151223
{:update, {:offline, _}},
1216-
{:driving, {:offline, _last}, nil},
1217-
%Data{} = data
1224+
:driving,
1225+
%Data{driving_status: {:offline, _}, current_drive: nil} = data
12181226
) do
12191227
{:next_state, :start, %Data{data | last_used: DateTime.utc_now(), driving_status: nil},
12201228
schedule_fetch(data)}
@@ -1223,17 +1231,16 @@ defmodule TeslaMate.Vehicles.Vehicle do
12231231
def handle_event(
12241232
:internal,
12251233
{:update, {:offline, _}},
1226-
{:driving, {:offline, last}, drive},
1227-
%Data{} = data
1234+
:driving,
1235+
%Data{driving_status: {:offline, last}, current_drive: drive} = data
12281236
) do
12291237
offline_since = parse_timestamp(last.drive_state.timestamp)
12301238

12311239
case diff_seconds(DateTime.utc_now(), offline_since) / 60 do
12321240
min when min >= @drive_timeout_min ->
12331241
timeout_drive(drive, data)
12341242

1235-
{:next_state, {:driving, {:offline, last}, nil},
1236-
%{data | last_used: DateTime.utc_now(), current_drive: nil},
1243+
{:next_state, :driving, %{data | last_used: DateTime.utc_now(), current_drive: nil},
12371244
[broadcast_summary(), schedule_fetch(30, data)]}
12381245

12391246
_min ->
@@ -1244,8 +1251,8 @@ defmodule TeslaMate.Vehicles.Vehicle do
12441251
def handle_event(
12451252
:internal,
12461253
{:update, {:online, now}},
1247-
{:driving, {:offline, last}, drv},
1248-
%Data{} = data
1254+
:driving,
1255+
%Data{driving_status: {:offline, last}, current_drive: drv} = data
12491256
) do
12501257
offline_start = parse_timestamp(last.drive_state.timestamp)
12511258
offline_end = parse_timestamp(now.drive_state.timestamp)
@@ -1290,15 +1297,20 @@ defmodule TeslaMate.Vehicles.Vehicle do
12901297
{:next_event, :internal, {:update, {:online, now}}}}
12911298

12921299
not is_nil(drv) ->
1293-
{:next_state, {:driving, :available, drv},
1300+
{:next_state, :driving,
12941301
%{data | last_used: DateTime.utc_now(), driving_status: :available},
12951302
{:next_event, :internal, {:update, {:online, now}}}}
12961303
end
12971304
end
12981305

12991306
#### msg: asleep
13001307

1301-
def handle_event(:internal, {:update, {:asleep, _vehicle}}, {:driving, _, drv}, data) do
1308+
def handle_event(
1309+
:internal,
1310+
{:update, {:asleep, _vehicle}},
1311+
:driving,
1312+
%Data{current_drive: drv} = data
1313+
) do
13021314
unless is_nil(drv), do: timeout_drive(drv, data)
13031315
{:next_state, :start, %{data | driving_status: nil}, schedule_fetch(data)}
13041316
end
@@ -1308,21 +1320,20 @@ defmodule TeslaMate.Vehicles.Vehicle do
13081320
def handle_event(
13091321
:internal,
13101322
{:update, {:online, _} = e},
1311-
{:driving, {:unavailable, _}, drv},
1312-
%Data{} = data
1323+
:driving,
1324+
%Data{driving_status: {:unavailable, _}} = data
13131325
) do
13141326
Logger.info("Vehicle is back online", car_id: data.car.id)
13151327

1316-
{:next_state, {:driving, :available, drv},
1317-
%{data | last_used: DateTime.utc_now(), driving_status: :available},
1328+
{:next_state, :driving, %{data | last_used: DateTime.utc_now(), driving_status: :available},
13181329
{:next_event, :internal, {:update, e}}}
13191330
end
13201331

13211332
def handle_event(
13221333
:internal,
13231334
{:update, {:online, vehicle}},
1324-
{:driving, :available, drv},
1325-
%Data{} = data
1335+
:driving,
1336+
%Data{driving_status: :available, current_drive: drv} = data
13261337
) do
13271338
interval = if streaming?(data), do: default_interval(), else: driving_interval()
13281339

@@ -1368,12 +1379,17 @@ defmodule TeslaMate.Vehicles.Vehicle do
13681379

13691380
#### :updating
13701381

1371-
def handle_event(:internal, {:update, {:offline, _}}, {:updating, _update_id}, %Data{} = data) do
1382+
def handle_event(:internal, {:update, {:offline, _}}, :updating, %Data{} = data) do
13721383
Logger.warning("Vehicle went offline while updating", car_id: data.car.id)
13731384
{:keep_state, %{data | last_used: DateTime.utc_now()}, schedule_fetch(data)}
13741385
end
13751386

1376-
def handle_event(:internal, {:update, {:online, vehicle}}, {:updating, update}, data) do
1387+
def handle_event(
1388+
:internal,
1389+
{:update, {:online, vehicle}},
1390+
:updating,
1391+
%Data{current_update: update} = data
1392+
) do
13771393
alias VehicleState.SoftwareUpdate, as: SW
13781394

13791395
case vehicle.vehicle_state do
@@ -1525,13 +1541,13 @@ defmodule TeslaMate.Vehicles.Vehicle do
15251541
:online ->
15261542
true
15271543

1528-
{:driving, _, _} when data.current_drive != nil ->
1544+
:driving when data.current_drive != nil ->
15291545
true
15301546

1531-
{:updating, _} when data.current_update != nil ->
1547+
:updating when data.current_update != nil ->
15321548
true
15331549

1534-
{:charging, _} when data.current_charging_process != nil ->
1550+
:charging when data.current_charging_process != nil ->
15351551
true
15361552

15371553
:start ->
@@ -1557,9 +1573,9 @@ defmodule TeslaMate.Vehicles.Vehicle do
15571573
reachable? =
15581574
case expected_state do
15591575
:online -> true
1560-
{:driving, _, _} when data.current_drive != nil -> true
1561-
{:updating, _} when data.current_update != nil -> true
1562-
{:charging, _} when data.current_charging_process != nil -> true
1576+
:driving when data.current_drive != nil -> true
1577+
:updating when data.current_update != nil -> true
1578+
:charging when data.current_charging_process != nil -> true
15631579
:start -> false
15641580
{:offline, _} -> false
15651581
{:asleep, _} -> false

0 commit comments

Comments
 (0)