diff --git a/CHANGELOG.md b/CHANGELOG.md index 37845d4e..b08ea84d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,7 @@ ## [1.10.0-dev] - Unreleased -### Added +### Enhancements - Allow editing of geo-fence positions - Link from Grafana dashboards directly to `/geo-fences` to create or edit a @@ -10,22 +10,28 @@ - Show warning icon if the health check fails for a vehicle - Use the best available SRTM data source which provides global elevation data including 60N and above - -#### New MQTT topics - -- `teslamate/cars/$car_id/healthy`: Reports the health status -- `teslamate/cars/$car_id/windows_open`: reports if the windows are open - -### Changed - - Optimize the comparison of geo fences by moving the lookup into the database - Allow geo-fences to cover multiple addresses and apply them retrospectively - Generally improve error handling and error messages - Improve landscape mode on devices with a notch -- Bump Grafana to v6.4.1 -### Fixed +#### New MQTT topics + +- `teslamate/cars/$car_id/healthy`: Reports the health status of the logger +- `teslamate/cars/$car_id/windows_open` +- `teslamate/cars/$car_id/shift_state` +- `teslamate/cars/$car_id/latitude` +- `teslamate/cars/$car_id/longitude` +- `teslamate/cars/$car_id/odometer` +- `teslamate/cars/$car_id/charge_port_door_open` +- `teslamate/cars/$car_id/charger_actual_current` +- `teslamate/cars/$car_id/charger_phases` +- `teslamate/cars/$car_id/charger_power` +- `teslamate/cars/$car_id/charger_voltage` +- `teslamate/cars/$car_id/time_to_full_charge` + +### Bug Fixes - Automatically restart parts of the application if Tesla decides yet again to change the IDs of some vehicles diff --git a/README.md b/README.md index 98bb8498..d15043a8 100644 --- a/README.md +++ b/README.md @@ -219,11 +219,10 @@ teslamate/cars/$car_id/plugged_in teslamate/cars/$car_id/charge_energy_added teslamate/cars/$car_id/charge_limit_soc teslamate/cars/$car_id/charge_port_door_open -teslamate/cars/$car_id/charge_port_latch_engaged teslamate/cars/$car_id/charger_actual_current teslamate/cars/$car_id/charger_phases teslamate/cars/$car_id/charger_power -teslamate/cars/$car_id/charger_voltag +teslamate/cars/$car_id/charger_voltage teslamate/cars/$car_id/scheduled_charging_start_time teslamate/cars/$car_id/time_to_full_charge ``` diff --git a/lib/teslamate/mqtt/pubsub/vehicle_subscriber.ex b/lib/teslamate/mqtt/pubsub/vehicle_subscriber.ex index 5eea5d0f..522a2c8d 100644 --- a/lib/teslamate/mqtt/pubsub/vehicle_subscriber.ex +++ b/lib/teslamate/mqtt/pubsub/vehicle_subscriber.ex @@ -40,20 +40,22 @@ defmodule TeslaMate.Mqtt.PubSub.VehicleSubscriber do {:noreply, state} end - def handle_info(summary, %State{car_id: car_id} = state) do + def handle_info(summary, state) do summary |> Map.from_struct() |> Stream.filter(fn {key, value} -> - key == :scheduled_charging_start_time or not is_nil(value) + not is_nil(value) or + key in [ + :charge_energy_added, + :charger_actual_current, + :charger_phases, + :charger_power, + :charger_voltage, + :scheduled_charging_start_time, + :time_to_full_charge + ] end) - |> Task.async_stream( - fn {key, value} -> - call(state.deps.publisher, :publish, [ - "teslamate/cars/#{car_id}/#{key}", - to_string(value), - [retain: true, qos: 1] - ]) - end, + |> Task.async_stream(&publish(&1, state), max_concurrency: 10, on_timeout: :kill_task, ordered: false @@ -65,4 +67,15 @@ defmodule TeslaMate.Mqtt.PubSub.VehicleSubscriber do {:noreply, %State{state | last_summary: summary}} end + + defp publish({key, value}, %State{car_id: car_id, deps: deps}) do + call(deps.publisher, :publish, [ + "teslamate/cars/#{car_id}/#{key}", + to_str(value), + [retain: true, qos: 1] + ]) + end + + defp to_str(%DateTime{} = datetime), do: DateTime.to_iso8601(datetime) + defp to_str(value), do: to_string(value) end diff --git a/lib/teslamate/vehicles/vehicle/summary.ex b/lib/teslamate/vehicles/vehicle/summary.ex index 2677f218..6b0ab6d8 100644 --- a/lib/teslamate/vehicles/vehicle/summary.ex +++ b/lib/teslamate/vehicles/vehicle/summary.ex @@ -29,7 +29,6 @@ defmodule TeslaMate.Vehicles.Vehicle.Summary do :odometer, :shift_state, :charge_port_door_open, - :charge_port_latch_engaged, :time_to_full_charge, :charger_phases, :charger_actual_current, diff --git a/test/teslamate/mqtt/pubsub/vehicle_subscriber_test.exs b/test/teslamate/mqtt/pubsub/vehicle_subscriber_test.exs index 4763316c..82b5dbf5 100644 --- a/test/teslamate/mqtt/pubsub/vehicle_subscriber_test.exs +++ b/test/teslamate/mqtt/pubsub/vehicle_subscriber_test.exs @@ -46,15 +46,29 @@ defmodule TeslaMate.Mqtt.PubSub.VehicleSubscriberTest do send(pid, summary) - for {key, val} <- Map.from_struct(summary), not is_nil(val) do + for {key, val} <- Map.from_struct(summary), not is_nil(val) and key != :since do topic = "teslamate/cars/0/#{key}" data = to_string(val) assert_receive {MqttPublisherMock, {:publish, ^topic, ^data, [retain: true, qos: 1]}} end + iso_time = DateTime.to_iso8601(summary.since) + assert_receive {MqttPublisherMock, - {:publish, "teslamate/cars/0/scheduled_charging_start_time", "", - [retain: true, qos: 1]}} + {:publish, "teslamate/cars/0/since", ^iso_time, [retain: true, qos: 1]}} + + for key <- [ + :charge_energy_added, + :charger_actual_current, + :charger_phases, + :charger_power, + :charger_voltage, + :scheduled_charging_start_time, + :time_to_full_charge + ] do + topic = "teslamate/cars/0/#{key}" + assert_receive {MqttPublisherMock, {:publish, ^topic, "", [retain: true, qos: 1]}} + end refute_receive _ end @@ -83,28 +97,17 @@ defmodule TeslaMate.Mqtt.PubSub.VehicleSubscriberTest do send(pid, summary) - for {key, val} <- Map.from_struct(summary), not is_nil(val) do + for {key, val} <- Map.from_struct(summary), + not is_nil(val) and key != :scheduled_charging_start_time do topic = "teslamate/cars/0/#{key}" data = to_string(val) assert_receive {MqttPublisherMock, {:publish, ^topic, ^data, [retain: true, qos: 1]}} end - refute_receive _ - end - - test "send empty string if scheduled_charging_start_time is nil", %{test: name} do - {:ok, pid} = start_subscriber(name, 0) - - assert_receive {VehiclesMock, {:subscribe, 0}} - - summary = %Summary{ - scheduled_charging_start_time: nil - } - - send(pid, summary) + iso_time = DateTime.to_iso8601(summary.scheduled_charging_start_time) assert_receive {MqttPublisherMock, - {:publish, "teslamate/cars/0/scheduled_charging_start_time", "", + {:publish, "teslamate/cars/0/scheduled_charging_start_time", ^iso_time, [retain: true, qos: 1]}} refute_receive _