Add additional sensors to Teslemetry (#112555)

* Add more sensors

* Fix coverage

* Dont do this rename yet

* Fix case

* Update snapshot

* Add icons

* Remove unused icons

* Update snapshot

* Remove last_value logic from TimeSensor

* Apply suggestions from code review

Co-authored-by: G Johansson <goran.johansson@shiftit.se>

* Update constant case

* Remove useless test

* Add refresh test back

* Add assertion to post coordinator refresh

---------

Co-authored-by: G Johansson <goran.johansson@shiftit.se>
This commit is contained in:
Brett Adams 2024-03-16 20:54:37 +10:00 committed by GitHub
parent 470ef554d7
commit 219cb7a788
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 1788 additions and 658 deletions

View File

@ -48,6 +48,11 @@ class TeslemetryVehicleEntity(CoordinatorEntity[TeslemetryVehicleDataCoordinator
serial_number=vehicle.vin,
)
@property
def _value(self) -> Any | None:
"""Return a specific value from coordinator data."""
return self.coordinator.data.get(self.key)
async def wake_up_if_asleep(self) -> None:
"""Wake up the vehicle if its asleep."""
async with self._wakelock:

View File

@ -18,6 +18,15 @@
"battery_power": {
"default": "mdi:home-battery"
},
"charge_state_charging_state": {
"default": "mdi:ev-station",
"state": {
"disconnected": "mdi:connection",
"no_power": "mdi:power-plug-off-outline",
"starting": "mdi:play-circle",
"stopped": "mdi:stop-circle"
}
},
"drive_state_active_route_destination": {
"default": "mdi:routes"
},

View File

@ -6,6 +6,7 @@ from collections.abc import Callable
from dataclasses import dataclass
from datetime import datetime, timedelta
from itertools import chain
from typing import cast
from homeassistant.components.sensor import (
SensorDeviceClass,
@ -27,10 +28,11 @@ from homeassistant.const import (
UnitOfTemperature,
UnitOfTime,
)
from homeassistant.core import HomeAssistant, callback
from homeassistant.core import HomeAssistant
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from homeassistant.helpers.typing import StateType
from homeassistant.util import dt as dt_util
from homeassistant.util.variance import ignore_variance
from .const import DOMAIN
from .entity import (
@ -40,13 +42,16 @@ from .entity import (
)
from .models import TeslemetryEnergyData, TeslemetryVehicleData
CHARGE_STATES = {
"Starting": "starting",
"Charging": "charging",
"Stopped": "stopped",
"Complete": "complete",
"Disconnected": "disconnected",
"NoPower": "no_power",
}
@callback
def minutes_to_datetime(value: StateType) -> datetime | None:
"""Convert relative minutes into absolute datetime."""
if isinstance(value, (int, float)) and value > 0:
return dt_util.now() + timedelta(minutes=value)
return None
SHIFT_STATES = {"P": "p", "D": "d", "R": "r", "N": "n"}
@dataclass(frozen=True, kw_only=True)
@ -57,11 +62,24 @@ class TeslemetrySensorEntityDescription(SensorEntityDescription):
VEHICLE_DESCRIPTIONS: tuple[TeslemetrySensorEntityDescription, ...] = (
TeslemetrySensorEntityDescription(
key="charge_state_charging_state",
options=list(CHARGE_STATES.values()),
device_class=SensorDeviceClass.ENUM,
value_fn=lambda value: CHARGE_STATES.get(cast(str, value)),
),
TeslemetrySensorEntityDescription(
key="charge_state_battery_level",
state_class=SensorStateClass.MEASUREMENT,
native_unit_of_measurement=PERCENTAGE,
device_class=SensorDeviceClass.BATTERY,
),
TeslemetrySensorEntityDescription(
key="charge_state_usable_battery_level",
state_class=SensorStateClass.MEASUREMENT,
native_unit_of_measurement=PERCENTAGE,
device_class=SensorDeviceClass.BATTERY,
entity_registry_enabled_default=False,
),
TeslemetrySensorEntityDescription(
key="charge_state_charge_energy_added",
@ -96,13 +114,16 @@ VEHICLE_DESCRIPTIONS: tuple[TeslemetrySensorEntityDescription, ...] = (
native_unit_of_measurement=UnitOfSpeed.MILES_PER_HOUR,
device_class=SensorDeviceClass.SPEED,
entity_category=EntityCategory.DIAGNOSTIC,
),
TeslemetrySensorEntityDescription(
key="charge_state_conn_charge_cable",
entity_category=EntityCategory.DIAGNOSTIC,
entity_registry_enabled_default=False,
),
TeslemetrySensorEntityDescription(
key="charge_state_minutes_to_full_charge",
device_class=SensorDeviceClass.TIMESTAMP,
key="charge_state_fast_charger_type",
entity_category=EntityCategory.DIAGNOSTIC,
value_fn=minutes_to_datetime,
entity_registry_enabled_default=False,
),
TeslemetrySensorEntityDescription(
key="charge_state_battery_range",
@ -111,12 +132,29 @@ VEHICLE_DESCRIPTIONS: tuple[TeslemetrySensorEntityDescription, ...] = (
device_class=SensorDeviceClass.DISTANCE,
suggested_display_precision=1,
),
TeslemetrySensorEntityDescription(
key="charge_state_est_battery_range",
state_class=SensorStateClass.MEASUREMENT,
native_unit_of_measurement=UnitOfLength.MILES,
device_class=SensorDeviceClass.DISTANCE,
suggested_display_precision=1,
entity_registry_enabled_default=False,
),
TeslemetrySensorEntityDescription(
key="charge_state_ideal_battery_range",
state_class=SensorStateClass.MEASUREMENT,
native_unit_of_measurement=UnitOfLength.MILES,
device_class=SensorDeviceClass.DISTANCE,
suggested_display_precision=1,
entity_registry_enabled_default=False,
),
TeslemetrySensorEntityDescription(
key="drive_state_speed",
state_class=SensorStateClass.MEASUREMENT,
native_unit_of_measurement=UnitOfSpeed.MILES_PER_HOUR,
device_class=SensorDeviceClass.SPEED,
entity_registry_enabled_default=False,
value_fn=lambda value: value or 0,
),
TeslemetrySensorEntityDescription(
key="drive_state_power",
@ -125,12 +163,13 @@ VEHICLE_DESCRIPTIONS: tuple[TeslemetrySensorEntityDescription, ...] = (
device_class=SensorDeviceClass.POWER,
entity_category=EntityCategory.DIAGNOSTIC,
entity_registry_enabled_default=False,
value_fn=lambda value: value or 0,
),
TeslemetrySensorEntityDescription(
key="drive_state_shift_state",
options=["p", "d", "r", "n"],
options=list(SHIFT_STATES.values()),
device_class=SensorDeviceClass.ENUM,
value_fn=lambda x: x.lower() if isinstance(x, str) else x,
value_fn=lambda x: SHIFT_STATES.get(str(x), "p"),
entity_registry_enabled_default=False,
),
TeslemetrySensorEntityDescription(
@ -235,14 +274,27 @@ VEHICLE_DESCRIPTIONS: tuple[TeslemetrySensorEntityDescription, ...] = (
native_unit_of_measurement=UnitOfLength.MILES,
device_class=SensorDeviceClass.DISTANCE,
),
TeslemetrySensorEntityDescription(
)
@dataclass(frozen=True, kw_only=True)
class TeslemetryTimeEntityDescription(SensorEntityDescription):
"""Describes Teslemetry Sensor entity."""
variance: int
VEHICLE_TIME_DESCRIPTIONS: tuple[TeslemetryTimeEntityDescription, ...] = (
TeslemetryTimeEntityDescription(
key="charge_state_minutes_to_full_charge",
device_class=SensorDeviceClass.TIMESTAMP,
entity_category=EntityCategory.DIAGNOSTIC,
variance=4,
),
TeslemetryTimeEntityDescription(
key="drive_state_active_route_minutes_to_arrival",
device_class=SensorDeviceClass.TIMESTAMP,
value_fn=minutes_to_datetime,
),
TeslemetrySensorEntityDescription(
key="drive_state_active_route_destination",
entity_category=EntityCategory.DIAGNOSTIC,
variance=1,
),
)
@ -322,6 +374,7 @@ ENERGY_DESCRIPTIONS: tuple[SensorEntityDescription, ...] = (
device_class=SensorDeviceClass.POWER,
entity_registry_enabled_default=False,
),
SensorEntityDescription(key="island_status", device_class=SensorDeviceClass.ENUM),
)
WALL_CONNECTOR_DESCRIPTIONS: tuple[SensorEntityDescription, ...] = (
@ -362,7 +415,12 @@ async def async_setup_entry(
for vehicle in data.vehicles
for description in VEHICLE_DESCRIPTIONS
),
( # Add energy sites
( # Add vehicles time sensors
TeslemetryVehicleTimeSensorEntity(vehicle, description)
for vehicle in data.vehicles
for description in VEHICLE_TIME_DESCRIPTIONS
),
( # Add energy site live
TeslemetryEnergySensorEntity(energysite, description)
for energysite in data.energysites
for description in ENERGY_DESCRIPTIONS
@ -390,17 +448,36 @@ class TeslemetryVehicleSensorEntity(TeslemetryVehicleEntity, SensorEntity):
) -> None:
"""Initialize the sensor."""
super().__init__(vehicle, description.key)
class TeslemetryVehicleTimeSensorEntity(TeslemetryVehicleEntity, SensorEntity):
"""Base class for Teslemetry vehicle metric sensors."""
entity_description: TeslemetryTimeEntityDescription
def __init__(
self,
data: TeslemetryVehicleData,
description: TeslemetryTimeEntityDescription,
) -> None:
"""Initialize the sensor."""
self.entity_description = description
self._get_timestamp = ignore_variance(
func=lambda value: dt_util.now() + timedelta(minutes=value),
ignored_variance=timedelta(minutes=description.variance),
)
super().__init__(data, description.key)
@property
def native_value(self) -> StateType | datetime:
def native_value(self) -> datetime | None:
"""Return the state of the sensor."""
return self.entity_description.value_fn(self.get())
return self._get_timestamp(self._value)
@property
def available(self) -> bool:
"""Return if sensor is available."""
return super().available and self.get() is not None
"""Return the avaliability of the sensor."""
return isinstance(self._value, int | float) and self._value > 0
class TeslemetryEnergySensorEntity(TeslemetryEnergyEntity, SensorEntity):

View File

@ -32,32 +32,85 @@
}
},
"sensor": {
"charge_state_usable_battery_level": {
"name": "Battery level"
"battery_power": {
"name": "Battery power"
},
"charge_state_battery_range": {
"name": "Battery range"
},
"charge_state_est_battery_range": {
"name": "Estimate battery range"
},
"charge_state_ideal_battery_range": {
"name": "Ideal battery range"
},
"charge_state_charge_energy_added": {
"name": "Charge energy added"
},
"charge_state_charge_rate": {
"name": "Charge rate"
},
"charge_state_charger_actual_current": {
"name": "Charger current"
},
"charge_state_charger_power": {
"name": "Charger power"
},
"charge_state_charger_voltage": {
"name": "Charger voltage"
},
"charge_state_charger_actual_current": {
"name": "Charger current"
"charge_state_conn_charge_cable": {
"name": "Charge cable"
},
"charge_state_charge_rate": {
"name": "Charge rate"
"charge_state_fast_charger_type": {
"name": "Fast charger type"
},
"charge_state_battery_range": {
"name": "Battery range"
"charge_state_charging_state": {
"name": "Charging",
"state": {
"starting": "Starting",
"charging": "Charging",
"disconnected": "Disconnected",
"stopped": "Stopped",
"complete": "Complete",
"no_power": "No power"
}
},
"charge_state_minutes_to_full_charge": {
"name": "Time to full charge"
},
"drive_state_speed": {
"name": "Speed"
"charge_state_battery_level": {
"name": "Battery level"
},
"charge_state_usable_battery_level": {
"name": "Usable battery level"
},
"climate_state_driver_temp_setting": {
"name": "Driver temperature setting"
},
"climate_state_inside_temp": {
"name": "Inside temperature"
},
"climate_state_outside_temp": {
"name": "Outside temperature"
},
"climate_state_passenger_temp_setting": {
"name": "Passenger temperature setting"
},
"drive_state_active_route_destination": {
"name": "Destination"
},
"drive_state_active_route_energy_at_arrival": {
"name": "State of charge at arrival"
},
"drive_state_active_route_miles_to_arrival": {
"name": "Distance to arrival"
},
"drive_state_active_route_minutes_to_arrival": {
"name": "Time to arrival"
},
"drive_state_active_route_traffic_minutes_delay": {
"name": "Traffic delay"
},
"drive_state_power": {
"name": "Power"
@ -65,12 +118,39 @@
"drive_state_shift_state": {
"name": "Shift state",
"state": {
"p": "Park",
"d": "Drive",
"r": "Reverse",
"n": "Neutral"
"n": "Neutral",
"p": "Park",
"r": "Reverse"
}
},
"drive_state_speed": {
"name": "Speed"
},
"energy_left": {
"name": "Energy left"
},
"generator_power": {
"name": "Generator power"
},
"grid_power": {
"name": "Grid power"
},
"grid_services_power": {
"name": "Grid services power"
},
"load_power": {
"name": "Load power"
},
"percentage_charged": {
"name": "Percentage charged"
},
"solar_power": {
"name": "Solar power"
},
"total_pack_energy": {
"name": "Total pack energy"
},
"vehicle_state_odometer": {
"name": "Odometer"
},
@ -86,62 +166,8 @@
"vehicle_state_tpms_pressure_rr": {
"name": "Tire pressure rear right"
},
"climate_state_inside_temp": {
"name": "Inside temperature"
},
"climate_state_outside_temp": {
"name": "Outside temperature"
},
"climate_state_driver_temp_setting": {
"name": "Driver temperature setting"
},
"climate_state_passenger_temp_setting": {
"name": "Passenger temperature setting"
},
"drive_state_active_route_traffic_minutes_delay": {
"name": "Traffic delay"
},
"drive_state_active_route_energy_at_arrival": {
"name": "State of charge at arrival"
},
"drive_state_active_route_miles_to_arrival": {
"name": "Distance to arrival"
},
"drive_state_active_route_minutes_to_arrival": {
"name": "Time to arrival"
},
"drive_state_active_route_destination": {
"name": "Destination"
},
"solar_power": {
"name": "Solar power"
},
"energy_left": {
"name": "Energy left"
},
"total_pack_energy": {
"name": "Total pack energy"
},
"percentage_charged": {
"name": "Percentage charged"
},
"battery_power": {
"name": "Battery power"
},
"load_power": {
"name": "Load power"
},
"grid_power": {
"name": "Grid power"
},
"grid_services_power": {
"name": "Grid services power"
},
"generator_power": {
"name": "Generator power"
},
"wall_connector_state": {
"name": "State code"
"vin": {
"name": "Vehicle"
},
"wall_connector_fault_state": {
"name": "Fault state code"
@ -149,8 +175,8 @@
"wall_connector_power": {
"name": "Power"
},
"vin": {
"name": "Vehicle"
"wall_connector_state": {
"name": "State code"
}
}
}

View File

@ -48,3 +48,18 @@ def assert_entities(
assert entity_entry == snapshot(name=f"{entity_entry.entity_id}-entry")
assert (state := hass.states.get(entity_entry.entity_id))
assert state == snapshot(name=f"{entity_entry.entity_id}-state")
def assert_entities_alt(
hass: HomeAssistant,
entry_id: str,
entity_registry: er.EntityRegistry,
snapshot: SnapshotAssertion,
) -> None:
"""Test that all entities match their alt snapshot."""
entity_entries = er.async_entries_for_config_entry(entity_registry, entry_id)
assert entity_entries
for entity_entry in entity_entries:
assert (state := hass.states.get(entity_entry.entity_id))
assert state == snapshot(name=f"{entity_entry.entity_id}-statealt")

View File

@ -12,6 +12,7 @@ WAKE_UP_ASLEEP = {"response": {"state": TeslemetryState.ASLEEP}, "error": None}
PRODUCTS = load_json_object_fixture("products.json", DOMAIN)
VEHICLE_DATA = load_json_object_fixture("vehicle_data.json", DOMAIN)
VEHICLE_DATA_ALT = load_json_object_fixture("vehicle_data_alt.json", DOMAIN)
LIVE_STATUS = load_json_object_fixture("live_status.json", DOMAIN)
RESPONSE_OK = {"response": {}, "error": None}

View File

@ -0,0 +1,279 @@
{
"response": {
"id": 1234,
"user_id": 1234,
"vehicle_id": 1234,
"vin": "VINVINVIN",
"color": null,
"access_type": "OWNER",
"granular_access": {
"hide_private": false
},
"tokens": ["abc", "def"],
"state": "online",
"in_service": false,
"id_s": "1234",
"calendar_enabled": true,
"api_version": 71,
"backseat_token": null,
"backseat_token_updated_at": null,
"ble_autopair_enrolled": false,
"charge_state": {
"battery_heater_on": false,
"battery_level": 77,
"battery_range": 266.87,
"charge_amps": 16,
"charge_current_request": 16,
"charge_current_request_max": 16,
"charge_enable_request": true,
"charge_energy_added": 0,
"charge_limit_soc": 80,
"charge_limit_soc_max": 100,
"charge_limit_soc_min": 50,
"charge_limit_soc_std": 80,
"charge_miles_added_ideal": 0,
"charge_miles_added_rated": 0,
"charge_port_cold_weather_mode": false,
"charge_port_color": "<invalid>",
"charge_port_door_open": true,
"charge_port_latch": "Engaged",
"charge_rate": 0,
"charger_actual_current": 0,
"charger_phases": null,
"charger_pilot_current": 16,
"charger_power": 0,
"charger_voltage": 2,
"charging_state": "Stopped",
"conn_charge_cable": "IEC",
"est_battery_range": 275.04,
"fast_charger_brand": "<invalid>",
"fast_charger_present": false,
"fast_charger_type": "ACSingleWireCAN",
"ideal_battery_range": 266.87,
"max_range_charge_counter": 0,
"minutes_to_full_charge": "bad value",
"not_enough_power_to_heat": null,
"off_peak_charging_enabled": false,
"off_peak_charging_times": "all_week",
"off_peak_hours_end_time": 900,
"preconditioning_enabled": false,
"preconditioning_times": "all_week",
"scheduled_charging_mode": "Off",
"scheduled_charging_pending": false,
"scheduled_charging_start_time": null,
"scheduled_charging_start_time_app": 600,
"scheduled_departure_time": 1704837600,
"scheduled_departure_time_minutes": 480,
"supercharger_session_trip_planner": false,
"time_to_full_charge": null,
"timestamp": null,
"trip_charging": false,
"usable_battery_level": 77,
"user_charge_enable_request": null
},
"climate_state": {
"allow_cabin_overheat_protection": true,
"auto_seat_climate_left": false,
"auto_seat_climate_right": false,
"auto_steering_wheel_heat": false,
"battery_heater": false,
"battery_heater_no_power": null,
"cabin_overheat_protection": "Off",
"cabin_overheat_protection_actively_cooling": false,
"climate_keeper_mode": "off",
"cop_activation_temperature": "High",
"defrost_mode": 0,
"driver_temp_setting": 22,
"fan_status": 0,
"hvac_auto_request": "On",
"inside_temp": 29.8,
"is_auto_conditioning_on": false,
"is_climate_on": false,
"is_front_defroster_on": false,
"is_preconditioning": false,
"is_rear_defroster_on": false,
"left_temp_direction": 251,
"max_avail_temp": 28,
"min_avail_temp": 15,
"outside_temp": 30,
"passenger_temp_setting": 22,
"remote_heater_control_enabled": false,
"right_temp_direction": 251,
"seat_heater_left": 0,
"seat_heater_rear_center": 0,
"seat_heater_rear_left": 0,
"seat_heater_rear_right": 0,
"seat_heater_right": 0,
"side_mirror_heaters": false,
"steering_wheel_heat_level": 0,
"steering_wheel_heater": false,
"supports_fan_only_cabin_overheat_protection": true,
"timestamp": 1705707520649,
"wiper_blade_heater": false
},
"drive_state": {
"active_route_latitude": 30.2226265,
"active_route_longitude": -97.6236871,
"active_route_miles_to_arrival": 0,
"active_route_minutes_to_arrival": 0,
"active_route_traffic_minutes_delay": 0,
"gps_as_of": 1701129612,
"heading": 185,
"latitude": -30.222626,
"longitude": -97.6236871,
"native_latitude": -30.222626,
"native_location_supported": 1,
"native_longitude": -97.6236871,
"native_type": "wgs",
"power": -7,
"shift_state": null,
"speed": null,
"timestamp": 1705707520649
},
"gui_settings": {
"gui_24_hour_time": false,
"gui_charge_rate_units": "kW",
"gui_distance_units": "km/hr",
"gui_range_display": "Rated",
"gui_temperature_units": "C",
"gui_tirepressure_units": "Psi",
"show_range_units": false,
"timestamp": 1705707520649
},
"vehicle_config": {
"aux_park_lamps": "Eu",
"badge_version": 1,
"can_accept_navigation_requests": true,
"can_actuate_trunks": true,
"car_special_type": "base",
"car_type": "model3",
"charge_port_type": "CCS",
"cop_user_set_temp_supported": false,
"dashcam_clip_save_supported": true,
"default_charge_to_max": false,
"driver_assist": "TeslaAP3",
"ece_restrictions": false,
"efficiency_package": "M32021",
"eu_vehicle": true,
"exterior_color": "DeepBlue",
"exterior_trim": "Black",
"exterior_trim_override": "",
"has_air_suspension": false,
"has_ludicrous_mode": false,
"has_seat_cooling": false,
"headlamp_type": "Global",
"interior_trim_type": "White2",
"key_version": 2,
"motorized_charge_port": true,
"paint_color_override": "0,9,25,0.7,0.04",
"performance_package": "Base",
"plg": true,
"pws": true,
"rear_drive_unit": "PM216MOSFET",
"rear_seat_heaters": 1,
"rear_seat_type": 0,
"rhd": true,
"roof_color": "RoofColorGlass",
"seat_type": null,
"spoiler_type": "None",
"sun_roof_installed": null,
"supports_qr_pairing": false,
"third_row_seats": "None",
"timestamp": 1705707520649,
"trim_badging": "74d",
"use_range_badging": true,
"utc_offset": 36000,
"webcam_selfie_supported": true,
"webcam_supported": true,
"wheel_type": "Pinwheel18CapKit"
},
"vehicle_state": {
"api_version": 71,
"autopark_state_v2": "unavailable",
"calendar_supported": true,
"car_version": "2023.44.30.8 06f534d46010",
"center_display_state": 0,
"dashcam_clip_save_available": true,
"dashcam_state": "Recording",
"df": 0,
"dr": 0,
"fd_window": 0,
"feature_bitmask": "fbdffbff,187f",
"fp_window": 0,
"ft": 0,
"is_user_present": false,
"locked": false,
"media_info": {
"audio_volume": 2.6667,
"audio_volume_increment": 0.333333,
"audio_volume_max": 10.333333,
"media_playback_status": "Stopped",
"now_playing_album": "",
"now_playing_artist": "",
"now_playing_duration": 0,
"now_playing_elapsed": 0,
"now_playing_source": "Spotify",
"now_playing_station": "",
"now_playing_title": ""
},
"media_state": {
"remote_control_enabled": true
},
"notifications_supported": true,
"odometer": 6481.019282,
"parsed_calendar_supported": true,
"pf": 0,
"pr": 0,
"rd_window": 0,
"remote_start": false,
"remote_start_enabled": true,
"remote_start_supported": true,
"rp_window": 0,
"rt": 0,
"santa_mode": 0,
"sentry_mode": false,
"sentry_mode_available": true,
"service_mode": false,
"service_mode_plus": false,
"software_update": {
"download_perc": 0,
"expected_duration_sec": 2700,
"install_perc": 1,
"status": "",
"version": " "
},
"speed_limit_mode": {
"active": false,
"current_limit_mph": 69,
"max_limit_mph": 120,
"min_limit_mph": 50,
"pin_code_set": true
},
"timestamp": 1705707520649,
"tpms_hard_warning_fl": false,
"tpms_hard_warning_fr": false,
"tpms_hard_warning_rl": false,
"tpms_hard_warning_rr": false,
"tpms_last_seen_pressure_time_fl": 1705700812,
"tpms_last_seen_pressure_time_fr": 1705700793,
"tpms_last_seen_pressure_time_rl": 1705700794,
"tpms_last_seen_pressure_time_rr": 1705700823,
"tpms_pressure_fl": 2.775,
"tpms_pressure_fr": 2.8,
"tpms_pressure_rl": 2.775,
"tpms_pressure_rr": 2.775,
"tpms_rcp_front_value": 2.9,
"tpms_rcp_rear_value": 2.9,
"tpms_soft_warning_fl": false,
"tpms_soft_warning_fr": false,
"tpms_soft_warning_rl": false,
"tpms_soft_warning_rr": false,
"valet_mode": false,
"valet_pin_needed": false,
"vehicle_name": "Test",
"vehicle_self_test_progress": 0,
"vehicle_self_test_requested": false,
"webcam_available": true
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -1,14 +1,19 @@
"""Test the Teslemetry sensor platform."""
from datetime import timedelta
from freezegun.api import FrozenDateTimeFactory
import pytest
from syrupy import SnapshotAssertion
from homeassistant.components.teslemetry.coordinator import SYNC_INTERVAL
from homeassistant.const import Platform
from homeassistant.core import HomeAssistant
from homeassistant.helpers import entity_registry as er
from . import assert_entities, setup_platform
from . import assert_entities, assert_entities_alt, setup_platform
from .const import VEHICLE_DATA_ALT
from tests.common import async_fire_time_changed
@pytest.mark.usefixtures("entity_registry_enabled_by_default")
@ -17,6 +22,7 @@ async def test_sensors(
snapshot: SnapshotAssertion,
entity_registry: er.EntityRegistry,
freezer: FrozenDateTimeFactory,
mock_vehicle_data,
) -> None:
"""Tests that the sensor entities are correct."""
@ -25,3 +31,11 @@ async def test_sensors(
entry = await setup_platform(hass, [Platform.SENSOR])
assert_entities(hass, entry.entry_id, entity_registry, snapshot)
# Coordinator refresh
mock_vehicle_data.return_value = VEHICLE_DATA_ALT
freezer.tick(timedelta(seconds=SYNC_INTERVAL))
async_fire_time_changed(hass)
await hass.async_block_till_done()
assert_entities_alt(hass, entry.entry_id, entity_registry, snapshot)