mirror of
https://github.com/teslamate-org/teslamate.git
synced 2026-01-24 21:06:08 +08:00
158 lines
4.9 KiB
Elixir
158 lines
4.9 KiB
Elixir
defmodule TeslaMateWeb.CarLive.Summary do
|
|
use TeslaMateWeb, :live_view
|
|
|
|
import TeslaMateWeb.Gettext
|
|
|
|
alias TeslaMate.Vehicles.Vehicle.Summary
|
|
alias TeslaMate.Vehicles.Vehicle
|
|
alias TeslaMate.{Vehicles, Convert}
|
|
|
|
on_mount {TeslaMateWeb.InitAssigns, :locale}
|
|
|
|
@impl true
|
|
def mount(_params, %{"summary" => %Summary{car: car} = summary} = session, socket) do
|
|
if connected?(socket) do
|
|
send(self(), :update_duration)
|
|
send(self(), {:status, Vehicle.busy?(car.id)})
|
|
|
|
:ok = Vehicles.subscribe_to_summary(car.id)
|
|
:ok = Vehicles.subscribe_to_fetch(car.id)
|
|
end
|
|
|
|
assigns = %{
|
|
car: car,
|
|
summary: summary,
|
|
fetch_status: Vehicle.busy?(car.id),
|
|
fetch_start: 0,
|
|
fetch_timer: nil,
|
|
settings: session["settings"],
|
|
translate_state: &translate_state/1,
|
|
duration: humanize_duration(summary.since),
|
|
error: nil,
|
|
error_timeout: nil,
|
|
loading: false
|
|
}
|
|
|
|
{:ok, assign(socket, assigns)}
|
|
end
|
|
|
|
@impl true
|
|
def handle_event("suspend_logging", _val, socket) do
|
|
cancel_timer(socket.assigns.error_timeout)
|
|
send(self(), :suspend_logging)
|
|
{:noreply, assign(socket, loading: true)}
|
|
end
|
|
|
|
def handle_event("resume_logging", _val, socket) do
|
|
send(self(), :resume_logging)
|
|
{:noreply, assign(socket, loading: true)}
|
|
end
|
|
|
|
@impl true
|
|
def handle_info(:update_duration, socket) do
|
|
Process.send_after(self(), :update_duration, :timer.seconds(1))
|
|
{:noreply, assign(socket, duration: humanize_duration(socket.assigns.summary.since))}
|
|
end
|
|
|
|
def handle_info(:resume_logging, socket) do
|
|
:ok = Vehicles.resume_logging(socket.assigns.car.id)
|
|
{:noreply, socket}
|
|
end
|
|
|
|
def handle_info(:suspend_logging, socket) do
|
|
assigns =
|
|
case Vehicles.suspend_logging(socket.assigns.car.id) do
|
|
:ok ->
|
|
%{error: nil, error_timeout: nil, loading: false}
|
|
|
|
{:error, reason} ->
|
|
%{
|
|
error: error_to_str(reason),
|
|
error_timeout: Process.send_after(self(), :hide_error, 5_000),
|
|
loading: false
|
|
}
|
|
end
|
|
|
|
{:noreply, assign(socket, assigns)}
|
|
end
|
|
|
|
def handle_info(:hide_error, socket) do
|
|
{:noreply, assign(socket, error: nil, error_timeout: nil)}
|
|
end
|
|
|
|
def handle_info(%Summary{since: since} = summary, socket) do
|
|
{:noreply,
|
|
assign(socket, summary: summary, duration: humanize_duration(since), loading: false)}
|
|
end
|
|
|
|
def handle_info({:status, true}, socket) do
|
|
cancel_timer(socket.assigns.fetch_timer)
|
|
|
|
assigns = %{
|
|
fetch_status: true,
|
|
fetch_start: System.monotonic_time(),
|
|
fetch_timer: nil
|
|
}
|
|
|
|
{:noreply, assign(socket, assigns)}
|
|
end
|
|
|
|
# Note: this must be smaller than the @driving_interval
|
|
@min_spinner_visibility_ms 1000
|
|
|
|
def handle_info({:status, false}, socket) do
|
|
fetch_duration =
|
|
(System.monotonic_time() - socket.assigns.fetch_start) /
|
|
System.convert_time_unit(1, :millisecond, :native)
|
|
|
|
assigns =
|
|
case @min_spinner_visibility_ms - fetch_duration do
|
|
diff when 0 < diff ->
|
|
%{fetch_timer: Process.send_after(self(), :set_status_to_false, round(diff))}
|
|
|
|
_ ->
|
|
%{fetch_status: false}
|
|
end
|
|
|
|
{:noreply, assign(socket, assigns)}
|
|
end
|
|
|
|
def handle_info(:set_status_to_false, socket) do
|
|
{:noreply, assign(socket, fetch_status: false)}
|
|
end
|
|
|
|
defp translate_state(:start), do: ""
|
|
defp translate_state(:driving), do: gettext("driving")
|
|
defp translate_state(:charging), do: gettext("charging")
|
|
defp translate_state(:updating), do: gettext("updating")
|
|
defp translate_state(:suspended), do: gettext("falling asleep")
|
|
defp translate_state(:online), do: gettext("online")
|
|
defp translate_state(:offline), do: gettext("offline")
|
|
defp translate_state(:asleep), do: gettext("asleep")
|
|
defp translate_state(:unavailable), do: gettext("unavailable")
|
|
|
|
defp error_to_str(:unlocked), do: gettext("Car is unlocked")
|
|
defp error_to_str(:doors_open), do: gettext("Doors are open")
|
|
defp error_to_str(:trunk_open), do: gettext("Trunk is open")
|
|
defp error_to_str(:sentry_mode), do: gettext("Sentry mode is enabled")
|
|
defp error_to_str(:preconditioning), do: gettext("Preconditioning")
|
|
defp error_to_str(:user_present), do: gettext("Driver present")
|
|
defp error_to_str(:downloading_update), do: gettext("Downloading update")
|
|
defp error_to_str(:update_in_progress), do: gettext("Update in progress")
|
|
defp error_to_str(:timeout), do: gettext("Timeout")
|
|
defp error_to_str(_other), do: gettext("An error occurred")
|
|
|
|
defp cancel_timer(nil), do: :ok
|
|
defp cancel_timer(ref) when is_reference(ref), do: Process.cancel_timer(ref)
|
|
|
|
defp humanize_duration(nil), do: nil
|
|
|
|
defp humanize_duration(date) do
|
|
case DateTime.utc_now() |> DateTime.diff(date, :second) do
|
|
dur when dur < 5 -> nil
|
|
dur when dur > 60 -> dur |> Convert.sec_to_str() |> Enum.reject(&String.ends_with?(&1, "s"))
|
|
dur -> dur |> Convert.sec_to_str()
|
|
end
|
|
end
|
|
end
|