From f2769869d6a42fdfd10f0df50acd2bd48e0dcf57 Mon Sep 17 00:00:00 2001 From: Adrian Kumpf Date: Thu, 24 Oct 2019 12:30:29 +0200 Subject: [PATCH] Tweak calculation of charge energy used --- README.md | 10 +- docs/integrations/mqtt.md | 10 +- lib/teslamate/log.ex | 74 +++- test/teslamate/log/log_charging_test.exs | 441 +++++++++++++++++++++++ 4 files changed, 505 insertions(+), 30 deletions(-) diff --git a/README.md b/README.md index 2969a5fb..b9682e81 100644 --- a/README.md +++ b/README.md @@ -10,9 +10,9 @@ A powerful, self-hosted data logger for your Tesla. - Written in [Elixir](https://elixir-lang.org/) -- Data is stored in a Postgres database -- Visualization and data analysis with Grafana -- Vehicle data is published to a local MQTT Broker +- Data is stored in a **Postgres** database +- Visualization and data analysis with **Grafana** +- Vehicle data is published to a local **MQTT** Broker ## Features @@ -22,6 +22,7 @@ A powerful, self-hosted data logger for your Tesla. - Drive and charging reports - Driving efficiency report - Consumption (net / gross) +- Charge energy added vs energy used - Vampire drain - Projected 100% range (battery degradation) - SOC charging stats @@ -30,8 +31,7 @@ A powerful, self-hosted data logger for your Tesla. **General** -- Little to no additional vampire drain: the car will fall asleep after a - certain idle time +- Little to no additional vampire drain: the car will fall asleep after a certain idle time - Automatic address lookup - Locally enriches positions with elevation data - Geo-fencing feature to create custom locations diff --git a/docs/integrations/mqtt.md b/docs/integrations/mqtt.md index 0c353cc6..3268684b 100644 --- a/docs/integrations/mqtt.md +++ b/docs/integrations/mqtt.md @@ -16,27 +16,27 @@ Vehicle data will be published to the following topics (`$car_id` usually starts | `teslamate/cars/$car_id/healthy` | true | Health status of the logger for that vehicle | | `teslamate/cars/$car_id/version` | 2019.32.12.2 58f3b76 | Software Version | | `teslamate/cars/$car_id/update_available` | false | Indicates if a software update is available | -| ------------------------------------------------------ | -------------------- | ------------------------------------------------------------ | +|   |   |   | | `teslamate/cars/$car_id/latitude` | 35.278131 | Last reported car latitude | | `teslamate/cars/$car_id/longitude` | 29.744801 | Last reported car longitude | | `teslamate/cars/$car_id/shift_state` | D | Current/Last Shift State (D/N/R/P) | | `teslamate/cars/$car_id/speed` | 12 | Current Speed in km/h | -| ------------------------------------------------------ | -------------------- | ------------------------------------------------------------ | +|   |   |   | | `teslamate/cars/$car_id/locked` | true | Indicates if the car is locked | | `teslamate/cars/$car_id/sentry_mode` | false | Indicates if Sentry Mode is active | | `teslamate/cars/$car_id/windows_open` | false | Indicates if any of the windows are open | | `teslamate/cars/$car_id/is_user_present` | false | Indicates if a user is present in the vehicle | -| ------------------------------------------------------ | -------------------- | ------------------------------------------------------------ | +|   |   |   | | `teslamate/cars/$car_id/is_climate_on` | true | Indicates if the climate control is on | | `teslamate/cars/$car_id/inside_temp` | 20.8 | Inside Temperature in °C | | `teslamate/cars/$car_id/outside_temp` | 18.4 | Temperature in °C | | `teslamate/cars/$car_id/is_preconditioning` | false | Indicates if the vehicle is being preconditioned | -| ------------------------------------------------------ | -------------------- | ------------------------------------------------------------ | +|   |   |   | | `teslamate/cars/$car_id/odometer` | 1653 | Car odometer in km | | `teslamate/cars/$car_id/est_battery_range_km` | 372.5 | Estimated Range in km | | `teslamate/cars/$car_id/rated_battery_range_km` | 401.63 | Rated Range in km | | `teslamate/cars/$car_id/ideal_battery_range_km` | 335.79 | Ideal Range in km | -| ------------------------------------------------------ | -------------------- | ------------------------------------------------------------ | +|   |   |   | | `teslamate/cars/$car_id/battery_level` | 88 | Battery Level Percentage | | `teslamate/cars/$car_id/plugged_in` | true | If car is currently plugged into a charger | | `teslamate/cars/$car_id/charge_energy_added` | 5.06 | Last added energy in kW | diff --git a/lib/teslamate/log.ex b/lib/teslamate/log.ex index afdae842..cb4cceda 100644 --- a/lib/teslamate/log.ex +++ b/lib/teslamate/log.ex @@ -316,20 +316,40 @@ defmodule TeslaMate.Log do %ChargingProcess{end_date: %DateTime{} = end_date} -> end_date end - stats = - Charge - |> where(charging_process_id: ^charging_process.id) - |> select([c], %{ - charge_energy_added: max(c.charge_energy_added) - min(c.charge_energy_added), - charge_energy_used: - sum( + energy_used = + from c in Charge, + select: %{ + energy_used: c_if is_nil(c.charger_phases) do c.charger_power else c.charger_actual_current * c.charger_voltage * c_if(c.charger_phases == 2, do: 3, else: c.charger_phases) / 1000.0 - end - ) * ^charging_interval / 3600, + end * + fragment( + "EXTRACT(epoch FROM (?))", + c.date - (lag(c.date) |> over(order_by: c.date)) + ) / 3600, + charger_phases: c.charger_phases + }, + where: c.charging_process_id == ^charging_process.id + + charge_energy_used = + from(e in subquery(energy_used), + select: {sum(e.energy_used)}, + where: e.energy_used > 0 + ) + |> Repo.one() + |> case do + {charge_energy_used} -> charge_energy_used + _ -> nil + end + + stats = + Charge + |> where(charging_process_id: ^charging_process.id) + |> select([c], %{ + charge_energy_added: max(c.charge_energy_added) - min(c.charge_energy_added), start_ideal_range_km: min(c.ideal_battery_range_km), end_ideal_range_km: max(c.ideal_battery_range_km), start_rated_range_km: min(c.rated_battery_range_km), @@ -341,6 +361,7 @@ defmodule TeslaMate.Log do }) |> Repo.one() |> Map.put(:end_date, end_date) + |> Map.put(:charge_energy_used, charge_energy_used) |> Map.put(:charge_energy_used_confidence, charge_energy_used_confidence) |> Map.put(:interval_sec, charging_interval) @@ -352,32 +373,43 @@ defmodule TeslaMate.Log do defp calculate_confidence(_process_id, nil), do: nil - defp calculate_confidence(process_id, charging_interval) do + defp calculate_confidence(process_id, interval) when is_number(interval) do {:ok, %{rows: [[confidence]]}} = Repo.query( """ WITH deltas AS ( SELECT - date - lag(date, 1) OVER (ORDER BY date) as delta + date - lag(date, 1) OVER (ORDER BY date) as delta, + charger_phases FROM charges WHERE charging_process_id = $1 ORDER BY date + ), interval_confidence as ( + SELECT + (NULLIF(count(*), 0) / NULLIF((select count(*) from deltas)::numeric, 0))::float as confidence + FROM + deltas + WHERE + delta >= $2 * INTERVAL '1 second' and delta <= ($2 + 1.5) * INTERVAL '1 second' + ), fast_charge_penalty as ( + SELECT + CASE WHEN (NULLIF(count(*), 0) / NULLIF((select count(*) from deltas)::numeric, 0)) > 0.9 THEN 0.10 + ELSE 0.0 + END as penalty + FROM + deltas + WHERE + charger_phases IS NULL ) SELECT - (NULLIF(count(*), 0) / NULLIF((select count(*) from deltas)::numeric, 0))::float as confidence - FROM - deltas - WHERE - delta >= $2 * INTERVAL '1 second' and delta <= ($2 + 1) * INTERVAL '1 second'; + NULLIF(GREATEST((select confidence from interval_confidence) - (select penalty from fast_charge_penalty), 0), 0); """, - [process_id, charging_interval] + [process_id, interval] ) - # TODO reduce range? - confidence end @@ -412,7 +444,9 @@ defmodule TeslaMate.Log do case Repo.one(query) do {factor, n} when n >= threshold and not is_nil(factor) -> - Logger.info("Derived efficiency factor: #{factor} Wh/km (#{n}x confirmed)", car_id: id) + Logger.info("Derived efficiency factor: #{factor * 1000} Wh/km (#{n}x confirmed)", + car_id: id + ) car |> Car.changeset(%{efficiency: factor}) diff --git a/test/teslamate/log/log_charging_test.exs b/test/teslamate/log/log_charging_test.exs index 0301e9b7..eb02e1ff 100644 --- a/test/teslamate/log/log_charging_test.exs +++ b/test/teslamate/log/log_charging_test.exs @@ -562,4 +562,445 @@ defmodule TeslaMate.LogChargingTest do :ok end end + + describe "charge energy used" do + test "calculates the energy used [P]" do + charges = charges_fixture_1() + + assert {:ok, cproc} = log_charging_process(charges) + assert cproc.charge_energy_added == 12.77 + assert cproc.charge_energy_used == 12.455230833333333 + assert cproc.charge_energy_used_confidence == 0.88 + assert cproc.duration_min == 19 + assert cproc.start_ideal_range_km == 235.9 + assert cproc.end_ideal_range_km == 320.5 + end + + test "calculates the energy used [I * U]" do + charges = charges_fixture_2() + + assert {:ok, cproc} = log_charging_process(charges) + assert cproc.charge_energy_added == 1.68 + assert cproc.charge_energy_used == 1.7756899999999984 + assert cproc.charge_energy_used_confidence == 0.9928571428571429 + assert cproc.duration_min == 13 + assert cproc.start_ideal_range_km == 288.9 + assert cproc.end_ideal_range_km == 299.9 + end + + test "handles a bad connection" do + charges = + charges_fixture_1() + |> Enum.with_index() + |> Enum.filter(fn {_, i} -> rem(i, 3) == 0 end) + |> Enum.map(fn {c, _} -> c end) + + assert {:ok, cproc} = log_charging_process(charges) + assert cproc.charge_energy_added == 12.67 + assert cproc.charge_energy_used == 12.45422888888889 + assert cproc.charge_energy_used_confidence == nil + assert cproc.duration_min == 18 + assert cproc.start_ideal_range_km == 235.9 + assert cproc.end_ideal_range_km == 319.8 + end + + test "handles data gaps" do + {c1, c2} = charges_fixture_1() |> Enum.split(100) + + charges = + c1 ++ + Enum.map(c2, fn {date, added, _, _, _, _, _} = data -> + new_date = + date + |> String.split(" ") + |> Enum.join("T") + |> Kernel.<>("Z") + |> DateTime.from_iso8601() + |> elem(1) + |> DateTime.add(2 * 60, :second) + |> DateTime.to_iso8601() + + data + |> put_elem(0, new_date) + |> put_elem(1, added + 1) + end) + + assert {:ok, cproc} = log_charging_process(charges) + assert cproc.charge_energy_added == 13.77 + assert cproc.charge_energy_used == 13.8218975 + assert cproc.charge_energy_used_confidence == 0.875 + assert cproc.duration_min == 21 + end + + defp log_charging_process(charges) do + %Car{id: car_id} = car_fixture() + + {:ok, cproc} = Log.start_charging_process(car_id, @valid_pos_attrs) + + for {date, added, power, range, phases, current, voltage} <- charges do + {:ok, %Charge{}} = + Log.insert_charge(cproc, %{ + date: date, + charge_energy_added: added, + charger_power: power, + ideal_battery_range_km: range, + charger_phases: phases, + charger_actual_current: current, + charger_voltage: voltage + }) + end + + {:ok, %ChargingProcess{}} = Log.complete_charging_process(cproc, charging_interval: 5) + end + + defp charges_fixture_1 do + [ + {"2019-10-24 06:43:48.022", 0, -1, 235.9, nil, 0, 1}, + {"2019-10-24 06:43:53.806", 0, -1, 236.6, nil, 0, 1}, + {"2019-10-24 06:43:59.474", 0, 43, 235.9, nil, 0, 1}, + {"2019-10-24 06:44:05.025", 0, 41, 236.6, nil, 0, 1}, + {"2019-10-24 06:44:10.538", 0.1, 41, 237.3, nil, 0, 1}, + {"2019-10-24 06:44:16.098", 0.1, 40, 237.3, nil, 0, 1}, + {"2019-10-24 06:44:21.755", 0.1, 40, 237.3, nil, 0, 1}, + {"2019-10-24 06:44:27.265", 0.21, 40, 238, nil, 0, 1}, + {"2019-10-24 06:44:32.821", 0.21, 40, 238, nil, 0, 1}, + {"2019-10-24 06:44:38.338", 0.31, 39, 238.7, nil, 0, 1}, + {"2019-10-24 06:44:43.858", 0.42, 40, 239.3, nil, 0, 1}, + {"2019-10-24 06:44:49.63", 0.52, 41, 240, nil, 0, 1}, + {"2019-10-24 06:44:55.11", 0.63, 40, 240.7, nil, 0, 1}, + {"2019-10-24 06:45:00.585", 0.63, 40, 240.7, nil, 0, 1}, + {"2019-10-24 06:45:06.106", 0.63, 40, 240.7, nil, 0, 1}, + {"2019-10-24 06:45:11.625", 0.73, 40, 241.4, nil, 0, 1}, + {"2019-10-24 06:45:17.145", 0.73, 41, 241.4, nil, 0, 1}, + {"2019-10-24 06:45:22.666", 0.84, 41, 242.1, nil, 0, 1}, + {"2019-10-24 06:45:28.33", 1.04, 40, 243.5, nil, 0, 1}, + {"2019-10-24 06:45:33.857", 1.04, 40, 243.5, nil, 0, 1}, + {"2019-10-24 06:45:39.384", 1.05, 40, 243.5, nil, 0, 1}, + {"2019-10-24 06:45:44.899", 1.15, 40, 244.2, nil, 0, 1}, + {"2019-10-24 06:45:50.425", 1.15, 40, 244.1, nil, 0, 1}, + {"2019-10-24 06:45:56.023", 1.26, 41, 244.8, nil, 0, 1}, + {"2019-10-24 06:46:01.543", 1.36, 41, 245.5, nil, 0, 1}, + {"2019-10-24 06:46:07.057", 1.36, 40, 245.5, nil, 0, 1}, + {"2019-10-24 06:46:12.581", 1.57, 40, 245.5, nil, 0, 1}, + {"2019-10-24 06:46:18.06", 1.57, 40, 246.9, nil, 0, 1}, + {"2019-10-24 06:46:23.698", 1.47, 40, 246.2, nil, 0, 1}, + {"2019-10-24 06:46:29.219", 1.68, 40, 247.6, nil, 0, 1}, + {"2019-10-24 06:46:34.736", 1.67, 40, 247.6, nil, 0, 1}, + {"2019-10-24 06:46:40.278", 1.78, 40, 248.3, nil, 0, 1}, + {"2019-10-24 06:46:45.733", 1.88, 41, 248.3, nil, 0, 1}, + {"2019-10-24 06:46:51.181", 1.88, 40, 248.9, nil, 0, 1}, + {"2019-10-24 06:46:56.662", 1.88, 40, 248.9, nil, 0, 1}, + {"2019-10-24 06:47:02.179", 1.99, 40, 249.6, nil, 0, 1}, + {"2019-10-24 06:47:07.67", 1.99, 40, 249.7, nil, 0, 1}, + {"2019-10-24 06:47:13.225", 2.2, 41, 251, nil, 0, 1}, + {"2019-10-24 06:47:18.737", 2.3, 41, 251.7, nil, 0, 1}, + {"2019-10-24 06:47:24.257", 2.3, 40, 251.7, nil, 0, 1}, + {"2019-10-24 06:47:29.802", 2.3, 40, 251.7, nil, 0, 1}, + {"2019-10-24 06:47:35.299", 2.41, 40, 252.4, nil, 0, 1}, + {"2019-10-24 06:47:40.826", 2.41, 40, 252.4, nil, 0, 1}, + {"2019-10-24 06:47:46.337", 2.51, 41, 253.1, nil, 0, 1}, + {"2019-10-24 06:47:51.802", 2.72, 40, 253.1, nil, 0, 1}, + {"2019-10-24 06:47:57.295", 2.72, 40, 254.5, nil, 0, 1}, + {"2019-10-24 06:48:02.766", 2.72, 40, 254.5, nil, 0, 1}, + {"2019-10-24 06:48:08.256", 2.83, 40, 255.2, nil, 0, 1}, + {"2019-10-24 06:48:14.425", 2.83, 40, 255.2, nil, 0, 1}, + {"2019-10-24 06:48:20.012", 2.93, 40, 255.9, nil, 0, 1}, + {"2019-10-24 06:48:25.619", 3.04, 40, 256.5, nil, 0, 1}, + {"2019-10-24 06:48:31.138", 3.04, 40, 256.5, nil, 0, 1}, + {"2019-10-24 06:48:36.657", 3.14, 40, 257.2, nil, 0, 1}, + {"2019-10-24 06:48:42.179", 3.25, 40, 257.9, nil, 0, 1}, + {"2019-10-24 06:48:47.701", 3.25, 41, 257.9, nil, 0, 1}, + {"2019-10-24 06:48:53.3", 3.35, 40, 258.6, nil, 0, 1}, + {"2019-10-24 06:48:58.824", 3.46, 40, 258.6, nil, 0, 1}, + {"2019-10-24 06:49:04.358", 3.46, 40, 259.3, nil, 0, 1}, + {"2019-10-24 06:49:09.938", 3.46, 40, 259.3, nil, 0, 1}, + {"2019-10-24 06:49:15.548", 3.66, 40, 260.7, nil, 0, 1}, + {"2019-10-24 06:49:21.058", 3.66, 40, 260.7, nil, 0, 1}, + {"2019-10-24 06:49:26.531", 3.77, 40, 261.4, nil, 0, 1}, + {"2019-10-24 06:49:32.273", 3.87, 41, 262, nil, 0, 1}, + {"2019-10-24 06:49:37.78", 3.87, 40, 262, nil, 0, 1}, + {"2019-10-24 06:49:43.298", 3.87, 40, 262, nil, 0, 1}, + {"2019-10-24 06:49:48.826", 3.98, 40, 262.7, nil, 0, 1}, + {"2019-10-24 06:49:54.358", 3.98, 40, 262.7, nil, 0, 1}, + {"2019-10-24 06:49:59.961", 4.08, 41, 263.4, nil, 0, 1}, + {"2019-10-24 06:50:05.49", 4.29, 40, 263.4, nil, 0, 1}, + {"2019-10-24 06:50:11.098", 4.29, 40, 264.8, nil, 0, 1}, + {"2019-10-24 06:50:16.591", 4.29, 40, 264.8, nil, 0, 1}, + {"2019-10-24 06:50:22.12", 4.4, 40, 265.5, nil, 0, 1}, + {"2019-10-24 06:50:27.631", 4.4, 40, 265.5, nil, 0, 1}, + {"2019-10-24 06:50:33.227", 4.5, 41, 266.2, nil, 0, 1}, + {"2019-10-24 06:50:38.739", 4.71, 40, 266.2, nil, 0, 1}, + {"2019-10-24 06:50:44.263", 4.71, 40, 267.5, nil, 0, 1}, + {"2019-10-24 06:50:49.949", 4.61, 40, 266.8, nil, 0, 1}, + {"2019-10-24 06:50:55.474", 4.82, 40, 268.2, nil, 0, 1}, + {"2019-10-24 06:51:00.991", 4.82, 41, 268.2, nil, 0, 1}, + {"2019-10-24 06:51:06.501", 4.92, 41, 268.2, nil, 0, 1}, + {"2019-10-24 06:51:12.027", 4.92, 40, 268.9, nil, 0, 1}, + {"2019-10-24 06:51:17.54", 5.03, 40, 269.6, nil, 0, 1}, + {"2019-10-24 06:51:23.071", 5.03, 41, 269.6, nil, 0, 1}, + {"2019-10-24 06:51:28.669", 5.24, 41, 271, nil, 0, 1}, + {"2019-10-24 06:51:34.19", 5.24, 40, 271, nil, 0, 1}, + {"2019-10-24 06:51:39.941", 5.24, 40, 271, nil, 0, 1}, + {"2019-10-24 06:51:45.467", 5.34, 40, 271.7, nil, 0, 1}, + {"2019-10-24 06:51:50.982", 5.44, 40, 272.3, nil, 0, 1}, + {"2019-10-24 06:51:56.503", 5.44, 41, 272.3, nil, 0, 1}, + {"2019-10-24 06:52:02.027", 5.55, 40, 273, nil, 0, 1}, + {"2019-10-24 06:52:07.541", 5.55, 40, 273, nil, 0, 1}, + {"2019-10-24 06:52:13.308", 5.55, 40, 273, nil, 0, 1}, + {"2019-10-24 06:52:18.899", 5.76, 41, 274.4, nil, 0, 1}, + {"2019-10-24 06:52:24.422", 5.86, 41, 275.1, nil, 0, 1}, + {"2019-10-24 06:52:29.94", 5.86, 40, 275.1, nil, 0, 1}, + {"2019-10-24 06:52:35.385", 5.86, 40, 275.1, nil, 0, 1}, + {"2019-10-24 06:52:40.898", 5.97, 40, 275.8, nil, 0, 1}, + {"2019-10-24 06:52:46.42", 5.97, 40, 275.8, nil, 0, 1}, + {"2019-10-24 06:52:52.025", 6.07, 40, 276.5, nil, 0, 1}, + {"2019-10-24 06:52:57.548", 6.28, 41, 277.9, nil, 0, 1}, + {"2019-10-24 06:53:03.22", 6.28, 41, 277.9, nil, 0, 1}, + {"2019-10-24 06:53:08.666", 6.28, 41, 277.9, nil, 0, 1}, + {"2019-10-24 06:53:14.162", 6.39, 41, 278.5, nil, 0, 1}, + {"2019-10-24 06:53:19.61", 6.49, 40, 279.2, nil, 0, 1}, + {"2019-10-24 06:53:25.62", 6.49, 41, 279.2, nil, 0, 1}, + {"2019-10-24 06:53:31.221", 6.59, 41, 279.9, nil, 0, 1}, + {"2019-10-24 06:53:36.662", 6.59, 40, 279.9, nil, 0, 1}, + {"2019-10-24 06:53:42.182", 6.59, 40, 279.9, nil, 0, 1}, + {"2019-10-24 06:53:47.86", 6.8, 40, 280.6, nil, 0, 1}, + {"2019-10-24 06:53:53.378", 6.91, 40, 282, nil, 0, 1}, + {"2019-10-24 06:53:58.91", 6.91, 40, 282, nil, 0, 1}, + {"2019-10-24 06:54:04.497", 6.91, 41, 282, nil, 0, 1}, + {"2019-10-24 06:54:10.034", 7.01, 41, 282.6, nil, 0, 1}, + {"2019-10-24 06:54:15.548", 7.01, 41, 282.6, nil, 0, 1}, + {"2019-10-24 06:54:21.086", 7.12, 41, 283.3, nil, 0, 1}, + {"2019-10-24 06:54:26.578", 7.22, 41, 283.4, nil, 0, 1}, + {"2019-10-24 06:54:32.156", 7.22, 40, 284, nil, 0, 1}, + {"2019-10-24 06:54:37.67", 7.22, 41, 284, nil, 0, 1}, + {"2019-10-24 06:54:43.291", 7.43, 41, 285.4, nil, 0, 1}, + {"2019-10-24 06:54:48.758", 7.54, 41, 286.1, nil, 0, 1}, + {"2019-10-24 06:54:54.25", 7.54, 41, 286.1, nil, 0, 1}, + {"2019-10-24 06:54:59.778", 7.54, 40, 286.1, nil, 0, 1}, + {"2019-10-24 06:55:05.299", 7.64, 41, 286.8, nil, 0, 1}, + {"2019-10-24 06:55:10.901", 7.64, 41, 286.8, nil, 0, 1}, + {"2019-10-24 06:55:16.42", 7.75, 40, 287.5, nil, 0, 1}, + {"2019-10-24 06:55:21.939", 7.75, 41, 287.5, nil, 0, 1}, + {"2019-10-24 06:55:27.461", 7.96, 41, 288.9, nil, 0, 1}, + {"2019-10-24 06:55:32.984", 7.95, 40, 288.8, nil, 0, 1}, + {"2019-10-24 06:55:38.5", 8.06, 41, 289.5, nil, 0, 1}, + {"2019-10-24 06:55:44.024", 8.16, 41, 290.2, nil, 0, 1}, + {"2019-10-24 06:55:49.498", 8.16, 41, 290.2, nil, 0, 1}, + {"2019-10-24 06:55:55.464", 8.16, 40, 290.2, nil, 0, 1}, + {"2019-10-24 06:56:00.982", 8.27, 41, 290.9, nil, 0, 1}, + {"2019-10-24 06:56:06.495", 8.48, 40, 292.3, nil, 0, 1}, + {"2019-10-24 06:56:12.022", 8.48, 41, 292.3, nil, 0, 1}, + {"2019-10-24 06:56:17.563", 8.48, 41, 292.3, nil, 0, 2}, + {"2019-10-24 06:56:23.143", 8.58, 41, 293, nil, 0, 1}, + {"2019-10-24 06:56:28.664", 8.58, 41, 293, nil, 0, 1}, + {"2019-10-24 06:56:34.188", 8.69, 41, 293.7, nil, 0, 1}, + {"2019-10-24 06:56:39.789", 8.69, 41, 293.7, nil, 0, 1}, + {"2019-10-24 06:56:45.305", 8.9, 41, 295, nil, 0, 1}, + {"2019-10-24 06:56:50.821", 8.9, 41, 294.3, nil, 0, 1}, + {"2019-10-24 06:56:56.423", 9, 41, 295.7, nil, 0, 1}, + {"2019-10-24 06:57:02.023", 9.11, 41, 296.4, nil, 0, 1}, + {"2019-10-24 06:57:07.544", 9.11, 41, 296.4, nil, 0, 1}, + {"2019-10-24 06:57:13.059", 9.11, 41, 296.4, nil, 0, 1}, + {"2019-10-24 06:57:18.659", 9.21, 41, 297.1, nil, 0, 1}, + {"2019-10-24 06:57:24.105", 9.42, 41, 297.1, nil, 0, 1}, + {"2019-10-24 06:57:30.26", 9.42, 41, 298.5, nil, 0, 1}, + {"2019-10-24 06:57:35.859", 9.32, 41, 297.8, nil, 0, 1}, + {"2019-10-24 06:57:41.379", 9.53, 41, 299.2, nil, 0, 2}, + {"2019-10-24 06:57:46.898", 9.53, 41, 299.2, nil, 0, 1}, + {"2019-10-24 06:57:52.419", 9.63, 41, 299.9, nil, 0, 2}, + {"2019-10-24 06:57:57.949", 9.63, 41, 299.9, nil, 0, 1}, + {"2019-10-24 06:58:03.545", 9.74, 41, 300.5, nil, 0, 1}, + {"2019-10-24 06:58:09.059", 9.74, 41, 300.6, nil, 0, 2}, + {"2019-10-24 06:58:14.66", 9.94, 41, 301.9, nil, 0, 1}, + {"2019-10-24 06:58:20.102", 9.95, 41, 301.9, nil, 0, 1}, + {"2019-10-24 06:58:25.597", 10.05, 41, 301.9, nil, 0, 1}, + {"2019-10-24 06:58:31.302", 10.05, 41, 302.6, nil, 0, 1}, + {"2019-10-24 06:58:36.823", 10.15, 41, 303.3, nil, 0, 1}, + {"2019-10-24 06:58:42.26", 10.26, 41, 303.3, nil, 0, 1}, + {"2019-10-24 06:58:47.782", 10.26, 41, 304, nil, 0, 1}, + {"2019-10-24 06:58:53.239", 10.26, 41, 304, nil, 0, 2}, + {"2019-10-24 06:58:58.719", 10.47, 41, 305.4, nil, 0, 2}, + {"2019-10-24 06:59:04.252", 10.57, 41, 304.7, nil, 0, 1}, + {"2019-10-24 06:59:09.785", 10.57, 41, 306, nil, 0, 2}, + {"2019-10-24 06:59:15.422", 10.57, 41, 306, nil, 0, 1}, + {"2019-10-24 06:59:20.907", 10.68, 41, 306.7, nil, 0, 1}, + {"2019-10-24 06:59:26.421", 10.78, 41, 306.7, nil, 0, 1}, + {"2019-10-24 06:59:31.939", 10.78, 41, 307.4, nil, 0, 1}, + {"2019-10-24 06:59:37.422", 10.78, 41, 307.4, nil, 0, 1}, + {"2019-10-24 06:59:42.979", 10.89, 41, 307.4, nil, 0, 1}, + {"2019-10-24 06:59:48.59", 10.99, 41, 308.8, nil, 0, 2}, + {"2019-10-24 06:59:54.109", 10.99, 41, 308.8, nil, 0, 1}, + {"2019-10-24 06:59:59.625", 11.1, 41, 309.5, nil, 0, 1}, + {"2019-10-24 07:00:05.3", 11.2, 40, 309.5, nil, 0, 1}, + {"2019-10-24 07:00:10.821", 11.2, 40, 310.2, nil, 0, 1}, + {"2019-10-24 07:00:17.875", 11.31, 41, 310.9, nil, 0, 1}, + {"2019-10-24 07:00:26.183", 11.41, 41, 310.9, nil, 0, 1}, + {"2019-10-24 07:00:32.1", 11.41, 41, 311.6, nil, 0, 2}, + {"2019-10-24 07:00:38.35", 11.41, 40, 311.6, nil, 0, 1}, + {"2019-10-24 07:00:43.818", 11.62, 40, 312.9, nil, 0, 2}, + {"2019-10-24 07:00:49.286", 11.73, 40, 312.9, nil, 0, 1}, + {"2019-10-24 07:00:54.772", 11.73, 40, 313.6, nil, 0, 2}, + {"2019-10-24 07:01:00.459", 11.73, 40, 313.6, nil, 0, 1}, + {"2019-10-24 07:01:05.963", 11.83, 40, 314.3, nil, 0, 1}, + {"2019-10-24 07:01:14.562", 12.04, 40, 315.7, nil, 0, 1}, + {"2019-10-24 07:01:20.426", 11.94, 40, 315, nil, 0, 1}, + {"2019-10-24 07:01:26.025", 12.15, 40, 315, nil, 0, 1}, + {"2019-10-24 07:01:31.633", 12.25, 40, 316.4, nil, 0, 1}, + {"2019-10-24 07:01:37.14", 12.25, 41, 317.1, nil, 0, 1}, + {"2019-10-24 07:01:42.602", 12.25, 41, 317.1, nil, 0, 1}, + {"2019-10-24 07:01:48.099", 12.35, 41, 317.1, nil, 0, 2}, + {"2019-10-24 07:01:53.78", 12.46, 41, 317.7, nil, 0, 2}, + {"2019-10-24 07:01:59.309", 12.56, 40, 318.4, nil, 0, 1}, + {"2019-10-24 07:02:04.822", 12.56, 40, 318.4, nil, 0, 2}, + {"2019-10-24 07:02:10.34", 12.67, 40, 319.1, nil, 0, 1}, + {"2019-10-24 07:02:15.861", 12.67, 40, 319.8, nil, 0, 2}, + {"2019-10-24 07:02:21.326", 12.77, 40, 320.5, nil, 0, 2} + ] + end + + defp charges_fixture_2 do + [ + {"2019-10-19 18:26:44", 0, 0, 288.9, 2, 0, 233}, + {"2019-10-19 18:26:50", 0, 0, 288.9, 2, 2, 234}, + {"2019-10-19 18:26:56", 0, 2, 288.9, 2, 5, 234}, + {"2019-10-19 18:27:02", 0, 4, 288.9, 2, 8, 235}, + {"2019-10-19 18:27:07", 0, 8, 288.9, 2, 12, 230}, + {"2019-10-19 18:27:13", 0, 8, 288.9, 2, 12, 231}, + {"2019-10-19 18:27:18", 0, 8, 288.9, 2, 12, 230}, + {"2019-10-19 18:27:24", 0, 8, 288.9, 2, 12, 230}, + {"2019-10-19 18:27:30", 0, 8, 288.9, 2, 12, 231}, + {"2019-10-19 18:27:35", 0, 8, 288.9, 2, 12, 231}, + {"2019-10-19 18:27:41", 0.1, 8, 289.6, 2, 12, 231}, + {"2019-10-19 18:27:46", 0.1, 8, 289.6, 2, 12, 231}, + {"2019-10-19 18:27:52", 0.1, 8, 289.6, 2, 12, 231}, + {"2019-10-19 18:27:57", 0.1, 8, 289.6, 2, 12, 230}, + {"2019-10-19 18:28:03", 0.1, 8, 289.6, 2, 12, 231}, + {"2019-10-19 18:28:09", 0.1, 8, 289.6, 2, 12, 230}, + {"2019-10-19 18:28:15", 0.1, 8, 289.6, 2, 12, 230}, + {"2019-10-19 18:28:20", 0.1, 8, 289.6, 2, 12, 230}, + {"2019-10-19 18:28:26", 0.1, 8, 289.6, 2, 12, 231}, + {"2019-10-19 18:28:31", 0.1, 8, 289.6, 2, 12, 230}, + {"2019-10-19 18:28:37", 0.21, 8, 290.3, 2, 12, 230}, + {"2019-10-19 18:28:43", 0.21, 8, 290.3, 2, 12, 231}, + {"2019-10-19 18:28:48", 0.21, 8, 290.3, 2, 12, 231}, + {"2019-10-19 18:28:54", 0.21, 8, 290.3, 2, 12, 230}, + {"2019-10-19 18:28:59", 0.21, 8, 290.3, 2, 12, 230}, + {"2019-10-19 18:29:05", 0.21, 8, 290.3, 2, 12, 230}, + {"2019-10-19 18:29:11", 0.21, 8, 290.3, 2, 12, 231}, + {"2019-10-19 18:29:16", 0.21, 8, 290.3, 2, 12, 230}, + {"2019-10-19 18:29:22", 0.21, 8, 290.3, 2, 12, 230}, + {"2019-10-19 18:29:28", 0.21, 8, 290.3, 2, 12, 230}, + {"2019-10-19 18:29:33", 0.42, 8, 291.6, 2, 12, 231}, + {"2019-10-19 18:29:39", 0.42, 8, 291.6, 2, 12, 231}, + {"2019-10-19 18:29:44", 0.42, 8, 291.6, 2, 12, 231}, + {"2019-10-19 18:29:50", 0.42, 8, 291.6, 2, 12, 230}, + {"2019-10-19 18:29:56", 0.42, 8, 291.6, 2, 12, 230}, + {"2019-10-19 18:30:01", 0.42, 8, 291.6, 2, 12, 231}, + {"2019-10-19 18:30:07", 0.42, 8, 291.6, 2, 12, 231}, + {"2019-10-19 18:30:12", 0.42, 8, 291.6, 2, 12, 230}, + {"2019-10-19 18:30:18", 0.31, 8, 290.9, 2, 12, 230}, + {"2019-10-19 18:30:24", 0.31, 8, 290.9, 2, 12, 231}, + {"2019-10-19 18:30:29", 0.31, 8, 290.9, 2, 12, 230}, + {"2019-10-19 18:30:35", 0.52, 8, 292.3, 2, 12, 229}, + {"2019-10-19 18:30:41", 0.52, 8, 292.3, 2, 12, 231}, + {"2019-10-19 18:30:46", 0.52, 8, 292.3, 2, 12, 230}, + {"2019-10-19 18:30:52", 0.52, 8, 292.3, 2, 12, 230}, + {"2019-10-19 18:30:58", 0.52, 8, 292.3, 2, 12, 230}, + {"2019-10-19 18:31:03", 0.52, 8, 292.3, 2, 12, 230}, + {"2019-10-19 18:31:09", 0.52, 8, 292.3, 2, 12, 230}, + {"2019-10-19 18:31:15", 0.52, 8, 292.3, 2, 12, 229}, + {"2019-10-19 18:31:20", 0.52, 8, 292.3, 2, 12, 230}, + {"2019-10-19 18:31:26", 0.52, 8, 292.3, 2, 12, 231}, + {"2019-10-19 18:31:32", 0.63, 8, 293, 2, 12, 229}, + {"2019-10-19 18:31:37", 0.63, 8, 293, 2, 12, 230}, + {"2019-10-19 18:31:43", 0.63, 8, 293, 2, 12, 231}, + {"2019-10-19 18:31:49", 0.63, 8, 293, 2, 12, 231}, + {"2019-10-19 18:31:55", 0.63, 8, 293, 2, 12, 232}, + {"2019-10-19 18:32:00", 0.63, 8, 293, 2, 12, 231}, + {"2019-10-19 18:32:06", 0.63, 8, 293, 2, 12, 230}, + {"2019-10-19 18:32:12", 0.63, 8, 293, 2, 12, 230}, + {"2019-10-19 18:32:17", 0.63, 8, 293, 2, 12, 231}, + {"2019-10-19 18:32:23", 0.63, 8, 293, 2, 12, 231}, + {"2019-10-19 18:32:28", 0.73, 8, 293.7, 2, 12, 230}, + {"2019-10-19 18:32:34", 0.73, 8, 293.7, 2, 12, 231}, + {"2019-10-19 18:32:40", 0.73, 8, 293.7, 2, 12, 231}, + {"2019-10-19 18:32:46", 0.73, 8, 293.7, 2, 12, 231}, + {"2019-10-19 18:32:51", 0.73, 8, 293.7, 2, 12, 230}, + {"2019-10-19 18:32:57", 0.73, 8, 293.7, 2, 12, 231}, + {"2019-10-19 18:33:03", 0.73, 8, 293.7, 2, 12, 231}, + {"2019-10-19 18:33:08", 0.73, 8, 293.7, 2, 12, 231}, + {"2019-10-19 18:33:14", 0.73, 8, 293.7, 2, 12, 230}, + {"2019-10-19 18:33:20", 0.73, 8, 293.7, 2, 12, 231}, + {"2019-10-19 18:33:25", 0.94, 8, 295.1, 2, 12, 231}, + {"2019-10-19 18:33:31", 0.84, 8, 294.4, 2, 12, 231}, + {"2019-10-19 18:33:37", 0.84, 8, 294.4, 2, 12, 231}, + {"2019-10-19 18:33:42", 0.94, 8, 295.1, 2, 12, 231}, + {"2019-10-19 18:33:48", 0.94, 8, 295.1, 2, 12, 231}, + {"2019-10-19 18:33:54", 0.94, 8, 295.1, 2, 12, 231}, + {"2019-10-19 18:33:59", 0.84, 8, 294.4, 2, 12, 231}, + {"2019-10-19 18:34:05", 0.84, 8, 294.4, 2, 12, 231}, + {"2019-10-19 18:34:11", 0.84, 8, 295.8, 2, 12, 230}, + {"2019-10-19 18:34:16", 1.05, 8, 295.8, 2, 12, 230}, + {"2019-10-19 18:34:22", 1.05, 8, 295.8, 2, 12, 230}, + {"2019-10-19 18:34:28", 1.05, 8, 295.8, 2, 12, 231}, + {"2019-10-19 18:34:33", 1.05, 8, 295.8, 2, 12, 230}, + {"2019-10-19 18:34:39", 1.05, 8, 295.8, 2, 12, 231}, + {"2019-10-19 18:34:45", 1.05, 8, 295.8, 2, 12, 231}, + {"2019-10-19 18:34:50", 1.05, 8, 295.8, 2, 12, 232}, + {"2019-10-19 18:34:56", 1.05, 8, 295.8, 2, 12, 231}, + {"2019-10-19 18:35:02", 1.05, 8, 295.8, 2, 12, 231}, + {"2019-10-19 18:35:07", 1.05, 8, 295.8, 2, 12, 231}, + {"2019-10-19 18:35:13", 1.15, 8, 296.4, 2, 12, 230}, + {"2019-10-19 18:35:18", 1.15, 8, 296.4, 2, 12, 230}, + {"2019-10-19 18:35:24", 1.15, 8, 296.4, 2, 12, 231}, + {"2019-10-19 18:35:30", 1.15, 8, 296.4, 2, 12, 231}, + {"2019-10-19 18:35:36", 1.15, 8, 296.4, 2, 12, 230}, + {"2019-10-19 18:35:41", 1.15, 8, 296.4, 2, 12, 230}, + {"2019-10-19 18:35:47", 1.15, 8, 296.4, 2, 12, 231}, + {"2019-10-19 18:35:52", 1.15, 8, 296.4, 2, 12, 233}, + {"2019-10-19 18:35:58", 1.15, 8, 296.4, 2, 12, 232}, + {"2019-10-19 18:36:04", 1.15, 8, 296.4, 2, 12, 232}, + {"2019-10-19 18:36:10", 1.26, 8, 297.1, 2, 12, 231}, + {"2019-10-19 18:36:16", 1.26, 8, 297.1, 2, 12, 231}, + {"2019-10-19 18:36:21", 1.26, 8, 297.1, 2, 12, 231}, + {"2019-10-19 18:36:27", 1.26, 8, 297.1, 2, 12, 231}, + {"2019-10-19 18:36:33", 1.26, 8, 297.1, 2, 12, 232}, + {"2019-10-19 18:36:38", 1.26, 8, 297.1, 2, 12, 231}, + {"2019-10-19 18:36:44", 1.26, 8, 297.1, 2, 12, 231}, + {"2019-10-19 18:36:49", 1.26, 8, 297.1, 2, 12, 231}, + {"2019-10-19 18:36:55", 1.26, 8, 297.1, 2, 12, 230}, + {"2019-10-19 18:37:01", 1.26, 8, 297.1, 2, 12, 231}, + {"2019-10-19 18:37:06", 1.47, 8, 298.5, 2, 12, 231}, + {"2019-10-19 18:37:12", 1.36, 8, 297.8, 2, 12, 231}, + {"2019-10-19 18:37:18", 1.36, 8, 297.8, 2, 12, 230}, + {"2019-10-19 18:37:24", 1.36, 8, 297.8, 2, 12, 231}, + {"2019-10-19 18:37:29", 1.47, 8, 298.5, 2, 12, 231}, + {"2019-10-19 18:37:35", 1.47, 8, 298.5, 2, 12, 231}, + {"2019-10-19 18:37:40", 1.36, 8, 297.8, 2, 12, 230}, + {"2019-10-19 18:37:46", 1.36, 8, 297.8, 2, 12, 231}, + {"2019-10-19 18:37:51", 1.36, 8, 297.8, 2, 12, 231}, + {"2019-10-19 18:37:57", 1.47, 8, 298.5, 2, 12, 231}, + {"2019-10-19 18:38:03", 1.57, 8, 299.2, 2, 12, 229}, + {"2019-10-19 18:38:08", 1.57, 8, 299.2, 2, 12, 231}, + {"2019-10-19 18:38:14", 1.57, 8, 299.2, 2, 12, 231}, + {"2019-10-19 18:38:19", 1.57, 8, 299.2, 2, 12, 231}, + {"2019-10-19 18:38:25", 1.57, 8, 299.2, 2, 12, 232}, + {"2019-10-19 18:38:31", 1.57, 8, 299.2, 2, 12, 232}, + {"2019-10-19 18:38:36", 1.57, 8, 299.2, 2, 12, 231}, + {"2019-10-19 18:38:42", 1.57, 8, 299.2, 2, 12, 232}, + {"2019-10-19 18:38:48", 1.57, 8, 299.2, 2, 12, 233}, + {"2019-10-19 18:38:53", 1.57, 8, 299.2, 2, 12, 231}, + {"2019-10-19 18:38:59", 1.68, 8, 299.9, 2, 12, 231}, + {"2019-10-19 18:39:05", 1.68, 8, 299.9, 2, 12, 232}, + {"2019-10-19 18:39:10", 1.68, 8, 299.9, 2, 12, 231}, + {"2019-10-19 18:39:16", 1.68, 8, 299.9, 2, 12, 230}, + {"2019-10-19 18:39:21", 1.68, 8, 299.9, 2, 12, 232}, + {"2019-10-19 18:39:27", 1.68, 8, 299.9, 2, 12, 231}, + {"2019-10-19 18:39:33", 1.68, 8, 299.9, 2, 12, 230}, + {"2019-10-19 18:39:38", 1.68, 8, 299.9, 2, 12, 231}, + {"2019-10-19 18:39:44", 1.68, 8, 299.9, 2, 12, 232}, + {"2019-10-19 18:39:49", 1.68, 0, 299.9, nil, 0, 64} + ] + end + end end