From ae0db5f0af3d59759ba2c11dda29fe60b327a252 Mon Sep 17 00:00:00 2001 From: Adrian Kumpf Date: Sat, 6 Apr 2019 01:02:25 +0200 Subject: [PATCH] Calculate statistics when closing a trip --- lib/tesla_mate/log.ex | 83 ++++++++++--------- lib/tesla_mate/log/trip.ex | 2 - lib/tesla_mate/vehicles/vehicle.ex | 8 +- .../20190330160000_create_trips.exs | 1 - test/support/mocks/log.ex | 7 +- 5 files changed, 55 insertions(+), 46 deletions(-) diff --git a/lib/tesla_mate/log.ex b/lib/tesla_mate/log.ex index ce8c06ca..faf30ba6 100644 --- a/lib/tesla_mate/log.ex +++ b/lib/tesla_mate/log.ex @@ -95,48 +95,55 @@ defmodule TeslaMate.Log do end def close_trip(trip_id) do - # TODO statistics - attrs = %{} + # TODO + # :start_address + # :end_address - with {:ok, _trip} <- - Trip - |> Repo.get!(trip_id) - |> Trip.changeset(attrs) - |> Repo.update() do - :ok - end + trip = + Trip + |> Repo.get!(trip_id) + |> Repo.preload([:car]) - # statistics = - # Position - # |> select([p], %{ - # outside_temp_avg: fragment("?::float", avg(p.outside_temp)), - # speed_max: max(p.speed), - # speed_min: min(p.speed), - # power_max: max(p.power), - # power_min: min(p.power), - # power_avg: fragment("?::float", avg(p.power)) - # }) - # |> where( - # [p], - # car_id == p.car_id and ^start_position_id <= p.id and p.id <= ^end_position_id - # ) - # |> Repo.one!() - # |> Map.to_list() + stats = + Position + |> where(trip_id: ^trip_id) + |> select([p, c], %{ + end_date: max(p.date), + outside_temp_avg: avg(p.outside_temp), + speed_max: max(p.speed), + power_max: max(p.power), + power_min: min(p.power), + power_avg: avg(p.power), + start_km: min(p.odometer), + end_km: max(p.odometer), + distance: max(p.odometer) - min(p.odometer), + start_range_km: min(p.ideal_battery_range_km), + end_range_km: max(p.ideal_battery_range_km), + duration_min: + fragment( + "(EXTRACT(EPOCH FROM (?::timestamp - ?::timestamp)) / 60)::integer", + max(p.date), + min(p.date) + ) + }) + |> join(:left, [p], c in Car, on: c.id == p.car_id) + |> group_by(:car_id) + |> Repo.one() - # result = - # Trip - # |> where( - # [d], - # car_id == d.car_id and d.start_position_id == ^start_position_id and - # d.end_position_id == ^end_position_id - # ) - # |> update(set: ^statistics) - # |> Repo.update_all([]) + stats = + stats + |> Map.put( + :consumption_kWh, + (stats.end_range_km - stats.start_range_km) * trip.car.efficiency + ) + |> Map.put( + :consumption_kWh_100km, + if(stats.distance > 0, do: stats.consumption_kWh / stats.distance * 100, else: nil) + ) - # case result do - # {0, nil} -> {:erorr, :no_trips_to_be_updated} - # {1, nil} -> :ok - # end + trip + |> Trip.changeset(stats) + |> Repo.update() end alias TeslaMate.Log.{ChargingProcess, Charge} diff --git a/lib/tesla_mate/log/trip.ex b/lib/tesla_mate/log/trip.ex index 06f0caa7..08dcbabe 100644 --- a/lib/tesla_mate/log/trip.ex +++ b/lib/tesla_mate/log/trip.ex @@ -11,7 +11,6 @@ defmodule TeslaMate.Log.Trip do field :outside_temp_avg, :float field :speed_max, :integer - field :speed_min, :integer field :power_max, :float field :power_min, :float @@ -45,7 +44,6 @@ defmodule TeslaMate.Log.Trip do :end_date, :outside_temp_avg, :speed_max, - :speed_min, :power_max, :power_min, :power_avg, diff --git a/lib/tesla_mate/vehicles/vehicle.ex b/lib/tesla_mate/vehicles/vehicle.ex index 16da94bf..1448e162 100644 --- a/lib/tesla_mate/vehicles/vehicle.ex +++ b/lib/tesla_mate/vehicles/vehicle.ex @@ -137,8 +137,7 @@ defmodule TeslaMate.Vehicles.Vehicle do :ok = call(data.deps.log, :start_state, [data.car_id, :online]) - {:next_state, :online, %Data{data | last_used: DateTime.utc_now()}, - {:next_event, :internal, event}} + {:next_state, :online, data, {:next_event, :internal, event}} end ### :online @@ -241,9 +240,10 @@ defmodule TeslaMate.Vehicles.Vehicle do {:keep_state, %Data{data | last_used: DateTime.utc_now()}, schedule_fetch(10)} nil -> - Logger.info("Driving / Ended") + {:ok, %Log.Trip{distance: distance, duration_min: duration}} = + call(data.deps.log, :close_trip, [trip_id]) - :ok = call(data.deps.log, :close_trip, [trip_id]) + Logger.info("Driving / Ended / #{Float.round(distance, 1)} km – #{duration} min") {:next_state, :start, %Data{data | last_used: DateTime.utc_now()}, {:next_event, :internal, {:update, {:online, vehicle_state}}}} diff --git a/priv/repo/migrations/20190330160000_create_trips.exs b/priv/repo/migrations/20190330160000_create_trips.exs index 08aed18c..d8899e5d 100644 --- a/priv/repo/migrations/20190330160000_create_trips.exs +++ b/priv/repo/migrations/20190330160000_create_trips.exs @@ -7,7 +7,6 @@ defmodule TeslaMate.Repo.Migrations.CreateTrips do add(:end_date, :utc_datetime) add(:outside_temp_avg, :float) add(:speed_max, :integer) - add(:speed_min, :integer) add(:power_max, :float) add(:power_min, :float) add(:power_avg, :float) diff --git a/test/support/mocks/log.ex b/test/support/mocks/log.ex index 738e3382..5437f75e 100644 --- a/test/support/mocks/log.ex +++ b/test/support/mocks/log.ex @@ -4,7 +4,7 @@ defmodule LogMock do defstruct [:pid] alias __MODULE__, as: State - alias TeslaMate.Log.Car + alias TeslaMate.Log.{Trip, Car} # API @@ -62,6 +62,11 @@ defmodule LogMock do {:reply, {:ok, 111}, state} end + def handle_call({:close_trip, _trip_id} = action, _from, %State{pid: pid} = state) do + send(pid, action) + {:reply, {:ok, %Trip{}}, state} + end + def handle_call(action, _from, %State{pid: pid} = state) do send(pid, action) {:reply, :ok, state}