Skip to content

Commit cdc7516

Browse files
committed
Replace compound state tuples with simple atoms throughout state machine
This is the final step in the state machine simplification. After this commit, the GenState state is always a simple atom (:driving, :charging, :updating, :start, :asleep, :offline, :online, :suspended) instead of compound tuples like {:driving, status, drive}. Changes: - All 12 next_state positions now use simple atoms instead of compound tuples {:driving, :available, drive}, {:driving, {:unavailable, n}, drv}, {:driving, {:offline, last}, drive}, {:charging, cproc}, {:updating, update} - Driving sub-state (available/unavailable/offline) is tracked in data.driving_status instead of the state tuple's second element - DB records (drive, cproc, update) are read from data.current_drive, data.current_charging_process, data.current_update - All driving handlers now match :driving with guards on driving_status: :available, {:unavailable, n}, {:offline, last} - suspend_logging handlers updated to match simple atoms - fetch/can_fall_asleep and fetch/reachable updated to use simple atoms - Summary module updated: format_state/2 now takes driving_status to correctly format :driving/:offline display state - broadcast_summary passes driving_status to Summary.into This change makes the state machine significantly more readable. The 3-element tuple {:driving, status, drive} is now just :driving, with status and drive accessible as data.driving_status and data.current_drive.
1 parent 3fe1151 commit cdc7516

2 files changed

Lines changed: 57 additions & 61 deletions

File tree

lib/teslamate/vehicles/vehicle.ex

Lines changed: 52 additions & 54 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

@@ -282,15 +278,15 @@ defmodule TeslaMate.Vehicles.Vehicle do
282278
{:keep_state_and_data, {:reply, from, :ok}}
283279
end
284280

285-
def handle_event({:call, from}, :suspend_logging, {:driving, _, _}, _data) do
281+
def handle_event({:call, from}, :suspend_logging, :driving, _data) do
286282
{:keep_state_and_data, {:reply, from, {:error, :vehicle_not_parked}}}
287283
end
288284

289-
def handle_event({:call, from}, :suspend_logging, {:updating, _}, _data) do
285+
def handle_event({:call, from}, :suspend_logging, :updating, _data) do
290286
{:keep_state_and_data, {:reply, from, {:error, :update_in_progress}}}
291287
end
292288

293-
def handle_event({:call, from}, :suspend_logging, {:charging, _}, _data) do
289+
def handle_event({:call, from}, :suspend_logging, :charging, _data) do
294290
{:keep_state_and_data, {:reply, from, {:error, :charging_in_progress}}}
295291
end
296292

@@ -641,7 +637,7 @@ defmodule TeslaMate.Vehicles.Vehicle do
641637

642638
vehicle = merge(data.last_response, stream_data, time: true)
643639

644-
{:next_state, {:driving, :available, drive},
640+
{:next_state, :driving,
645641
%Data{
646642
data
647643
| last_response: vehicle,
@@ -678,11 +674,11 @@ defmodule TeslaMate.Vehicles.Vehicle do
678674
def handle_event(
679675
:info,
680676
{:stream, %Stream.Data{} = stream_data},
681-
{:driving, status, drv},
682-
%Data{} = data
677+
:driving,
678+
%Data{driving_status: :available, current_drive: drv} = data
683679
) do
684-
case {status, stream_data} do
685-
{:available, %Stream.Data{shift_state: shift_state}} when shift_state in ~w(D N R) ->
680+
case stream_data do
681+
%Stream.Data{shift_state: shift_state} when shift_state in ~w(D N R) ->
686682
{:ok, %{elevation: elevation}} =
687683
call(data.deps.log, :insert_position, [drv, create_position(stream_data, data)])
688684

@@ -692,7 +688,7 @@ defmodule TeslaMate.Vehicles.Vehicle do
692688
{:keep_state, %{data | last_used: now, last_response: vehicle, elevation: elevation},
693689
broadcast_summary()}
694690

695-
{_status, %Stream.Data{}} ->
691+
%Stream.Data{} ->
696692
{:keep_state_and_data, schedule_fetch(0, data)}
697693
end
698694
end
@@ -723,7 +719,7 @@ defmodule TeslaMate.Vehicles.Vehicle do
723719

724720
vehicle = merge(data.last_response, stream_data, time: true)
725721

726-
{:next_state, {:driving, :available, drive},
722+
{:next_state, :driving,
727723
%Data{
728724
data
729725
| last_response: vehicle,
@@ -903,7 +899,8 @@ defmodule TeslaMate.Vehicles.Vehicle do
903899
healthy?: healthy?(data.car.id),
904900
elevation: data.elevation,
905901
geofence: data.geofence,
906-
car: data.car
902+
car: data.car,
903+
driving_status: data.driving_status
907904
})
908905

909906
:ok =
@@ -1053,7 +1050,7 @@ defmodule TeslaMate.Vehicles.Vehicle do
10531050

10541051
:ok = disconnect_stream(data)
10551052

1056-
{:next_state, {:updating, update},
1053+
{:next_state, :updating,
10571054
%{
10581055
data
10591056
| last_state_change: DateTime.utc_now(),
@@ -1067,8 +1064,7 @@ defmodule TeslaMate.Vehicles.Vehicle do
10671064

10681065
{drive, data} = start_drive(create_position(vehicle, data), data)
10691066

1070-
{:next_state, {:driving, :available, drive},
1071-
%{data | current_drive: drive, driving_status: :available},
1067+
{:next_state, :driving, %{data | current_drive: drive, driving_status: :available},
10721068
[
10731069
broadcast_summary(),
10741070
schedule_fetch(driving_interval(), data)
@@ -1099,7 +1095,7 @@ defmodule TeslaMate.Vehicles.Vehicle do
10991095

11001096
:ok = disconnect_stream(data)
11011097

1102-
{:next_state, {:charging, cproc},
1098+
{:next_state, :charging,
11031099
%Data{
11041100
data
11051101
| last_state_change: DateTime.utc_now(),
@@ -1150,7 +1146,7 @@ defmodule TeslaMate.Vehicles.Vehicle do
11501146
|> Map.get(:charger_power)
11511147
|> determince_interval()
11521148

1153-
{:next_state, {:charging, cproc}, %{data | current_charging_process: cproc},
1149+
{:next_state, :charging, %{data | current_charging_process: cproc},
11541150
[broadcast_summary(), schedule_fetch(interval, data)]}
11551151

11561152
%Vehicle{charge_state: %Charge{charging_state: state}} ->
@@ -1177,44 +1173,44 @@ defmodule TeslaMate.Vehicles.Vehicle do
11771173
def handle_event(
11781174
:internal,
11791175
{:update, {:offline, _}},
1180-
{:driving, :available, drive},
1181-
%Data{} = data
1176+
:driving,
1177+
%Data{driving_status: :available} = data
11821178
) do
11831179
Logger.warning("Vehicle went offline while driving", car_id: data.car.id)
11841180

1185-
{:next_state, {:driving, {:unavailable, 0}, drive},
1181+
{:next_state, :driving,
11861182
%{data | last_used: DateTime.utc_now(), driving_status: {:unavailable, 0}},
11871183
schedule_fetch(5, data)}
11881184
end
11891185

11901186
def handle_event(
11911187
:internal,
11921188
{:update, {:offline, _}},
1193-
{:driving, {:unavailable, n}, drv},
1194-
%Data{} = data
1189+
:driving,
1190+
%Data{driving_status: {:unavailable, n}} = data
11951191
)
11961192
when n < 15 do
1197-
{:next_state, {:driving, {:unavailable, n + 1}, drv},
1193+
{:next_state, :driving,
11981194
%{data | last_used: DateTime.utc_now(), driving_status: {:unavailable, n + 1}},
11991195
schedule_fetch(5, data)}
12001196
end
12011197

12021198
def handle_event(
12031199
:internal,
12041200
{:update, {:offline, _}},
1205-
{:driving, {:unavailable, _n}, drv},
1206-
%Data{} = data
1201+
:driving,
1202+
%Data{driving_status: {:offline, _}} = data
12071203
) do
1208-
{:next_state, {:driving, {:offline, data.last_response}, drv},
1204+
{:next_state, :driving,
12091205
%{data | last_used: DateTime.utc_now(), driving_status: {:offline, data.last_response}},
12101206
[broadcast_summary(), schedule_fetch(30, data)]}
12111207
end
12121208

12131209
def handle_event(
12141210
:internal,
12151211
{:update, {:offline, _}},
1216-
{:driving, {:offline, _last}, nil},
1217-
%Data{} = data
1212+
:driving,
1213+
%Data{driving_status: {:offline, _}, current_drive: nil} = data
12181214
) do
12191215
{:next_state, :start, %Data{data | last_used: DateTime.utc_now(), driving_status: nil},
12201216
schedule_fetch(data)}
@@ -1223,17 +1219,16 @@ defmodule TeslaMate.Vehicles.Vehicle do
12231219
def handle_event(
12241220
:internal,
12251221
{:update, {:offline, _}},
1226-
{:driving, {:offline, last}, drive},
1227-
%Data{} = data
1222+
:driving,
1223+
%Data{driving_status: {:offline, last}, current_drive: drive} = data
12281224
) do
12291225
offline_since = parse_timestamp(last.drive_state.timestamp)
12301226

12311227
case diff_seconds(DateTime.utc_now(), offline_since) / 60 do
12321228
min when min >= @drive_timeout_min ->
12331229
timeout_drive(drive, data)
12341230

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

12391234
_min ->
@@ -1244,8 +1239,8 @@ defmodule TeslaMate.Vehicles.Vehicle do
12441239
def handle_event(
12451240
:internal,
12461241
{:update, {:online, now}},
1247-
{:driving, {:offline, last}, drv},
1248-
%Data{} = data
1242+
:driving,
1243+
%Data{driving_status: {:offline, last}, current_drive: drv} = data
12491244
) do
12501245
offline_start = parse_timestamp(last.drive_state.timestamp)
12511246
offline_end = parse_timestamp(now.drive_state.timestamp)
@@ -1290,16 +1285,20 @@ defmodule TeslaMate.Vehicles.Vehicle do
12901285
{:next_event, :internal, {:update, {:online, now}}}}
12911286

12921287
not is_nil(drv) ->
1293-
{:next_state, {:driving, :available, drv},
1288+
{:next_state, :driving,
12941289
%{data | last_used: DateTime.utc_now(), driving_status: :available},
12951290
{:next_event, :internal, {:update, {:online, now}}}}
12961291
end
12971292
end
12981293

12991294
#### msg: asleep
13001295

1301-
def handle_event(:internal, {:update, {:asleep, _vehicle}}, {:driving, _, drv}, data)
1302-
when data.driving_status != nil and data.driving_status != :available do
1296+
def handle_event(
1297+
:internal,
1298+
{:update, {:asleep, _vehicle}},
1299+
:driving,
1300+
%Data{driving_status: {:offline, _}, current_drive: drv} = data
1301+
) do
13031302
unless is_nil(drv), do: timeout_drive(drv, data)
13041303
{:next_state, :start, %{data | driving_status: nil}, schedule_fetch(data)}
13051304
end
@@ -1309,21 +1308,20 @@ defmodule TeslaMate.Vehicles.Vehicle do
13091308
def handle_event(
13101309
:internal,
13111310
{:update, {:online, _} = e},
1312-
{:driving, {:unavailable, _}, drv},
1313-
%Data{} = data
1311+
:driving,
1312+
%Data{driving_status: {:unavailable, _}} = data
13141313
) do
13151314
Logger.info("Vehicle is back online", car_id: data.car.id)
13161315

1317-
{:next_state, {:driving, :available, drv},
1318-
%{data | last_used: DateTime.utc_now(), driving_status: :available},
1316+
{:next_state, :driving, %{data | last_used: DateTime.utc_now(), driving_status: :available},
13191317
{:next_event, :internal, {:update, e}}}
13201318
end
13211319

13221320
def handle_event(
13231321
:internal,
13241322
{:update, {:online, vehicle}},
1325-
{:driving, :available, drv},
1326-
%Data{} = data
1323+
:driving,
1324+
%Data{driving_status: :available, current_drive: drv} = data
13271325
) do
13281326
interval = if streaming?(data), do: default_interval(), else: driving_interval()
13291327

@@ -1526,13 +1524,13 @@ defmodule TeslaMate.Vehicles.Vehicle do
15261524
:online ->
15271525
true
15281526

1529-
{:driving, _, _} when data.current_drive != nil ->
1527+
:driving when data.current_drive != nil ->
15301528
true
15311529

1532-
{:updating, _} when data.current_update != nil ->
1530+
:updating when data.current_update != nil ->
15331531
true
15341532

1535-
{:charging, _} when data.current_charging_process != nil ->
1533+
:charging when data.current_charging_process != nil ->
15361534
true
15371535

15381536
:start ->
@@ -1558,9 +1556,9 @@ defmodule TeslaMate.Vehicles.Vehicle do
15581556
reachable? =
15591557
case expected_state do
15601558
:online -> true
1561-
{:driving, _, _} when data.current_drive != nil -> true
1562-
{:updating, _} when data.current_update != nil -> true
1563-
{:charging, _} when data.current_charging_process != nil -> true
1559+
:driving when data.current_drive != nil -> true
1560+
:updating when data.current_update != nil -> true
1561+
:charging when data.current_charging_process != nil -> true
15641562
:start -> false
15651563
{:offline, _} -> false
15661564
{:asleep, _} -> false

lib/teslamate/vehicles/vehicle/summary.ex

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -41,12 +41,13 @@ defmodule TeslaMate.Vehicles.Vehicle.Summary do
4141
healthy?: healthy?,
4242
car: car,
4343
elevation: elevation,
44-
geofence: gf
44+
geofence: gf,
45+
driving_status: driving_status
4546
} = attrs
4647

4748
%__MODULE__{
4849
format_vehicle(vehicle)
49-
| state: format_state(state),
50+
| state: format_state(state, driving_status),
5051
since: since,
5152
healthy: healthy?,
5253
elevation: elevation,
@@ -60,11 +61,8 @@ defmodule TeslaMate.Vehicles.Vehicle.Summary do
6061
}
6162
end
6263

63-
defp format_state({:driving, {:offline, _}, _id}), do: :offline
64-
defp format_state({:driving, _state, _id}), do: :driving
65-
defp format_state({state, _, _}) when is_atom(state), do: state
66-
defp format_state({state, _}) when is_atom(state), do: state
67-
defp format_state(state) when is_atom(state), do: state
64+
defp format_state(:driving, {:offline, _}), do: :offline
65+
defp format_state(state, _driving_status) when is_atom(state), do: state
6866

6967
defp get_car_attr(%Car{exterior_color: v}, :exterior_color), do: v
7068
defp get_car_attr(%Car{spoiler_type: v}, :spoiler_type), do: v

0 commit comments

Comments
 (0)