Use PressureConverter for Teslemetry TPMS streaming conversion (#181508)

This commit is contained in:
Brett Adams
2026-09-07 10:14:16 +02:00
committed by GitHub
parent f5f2848d94
commit ec82dee53d
2 changed files with 65 additions and 17 deletions
+29 -7
View File
@@ -34,6 +34,7 @@ from homeassistant.core import HomeAssistant
from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback
from homeassistant.helpers.typing import StateType
from homeassistant.util import dt as dt_util
from homeassistant.util.unit_conversion import PressureConverter
from homeassistant.util.variance import ignore_variance
from . import TeslemetryConfigEntry
@@ -50,9 +51,6 @@ from .models import TeslemetryEnergyData, TeslemetryVehicleData
PARALLEL_UPDATES = 0
# Teslemetry streams TPMS pressure in atmospheres; entities are declared in bar.
ATM_TO_BAR = 1.01325
# Tesla only reports the self-driving/mileage-since-reset fields (258-259) on HW4
# vehicles, identified by this driver-assist capability in the vehicle config.
DRIVER_ASSIST_HW4 = "TeslaAP4"
@@ -403,7 +401,13 @@ VEHICLE_DESCRIPTIONS: tuple[TeslemetryVehicleSensorEntityDescription, ...] = (
key="vehicle_state_tpms_pressure_fl",
polling=True,
streaming_listener=lambda vehicle, callback: vehicle.listen_TpmsPressureFl(
lambda x: callback(None) if x is None else callback(x * ATM_TO_BAR)
lambda x: (
callback(None)
if x is None
else callback(
PressureConverter.convert(x, UnitOfPressure.ATM, UnitOfPressure.BAR)
)
)
),
state_class=SensorStateClass.MEASUREMENT,
native_unit_of_measurement=UnitOfPressure.BAR,
@@ -417,7 +421,13 @@ VEHICLE_DESCRIPTIONS: tuple[TeslemetryVehicleSensorEntityDescription, ...] = (
key="vehicle_state_tpms_pressure_fr",
polling=True,
streaming_listener=lambda vehicle, callback: vehicle.listen_TpmsPressureFr(
lambda x: callback(None) if x is None else callback(x * ATM_TO_BAR)
lambda x: (
callback(None)
if x is None
else callback(
PressureConverter.convert(x, UnitOfPressure.ATM, UnitOfPressure.BAR)
)
)
),
state_class=SensorStateClass.MEASUREMENT,
native_unit_of_measurement=UnitOfPressure.BAR,
@@ -431,7 +441,13 @@ VEHICLE_DESCRIPTIONS: tuple[TeslemetryVehicleSensorEntityDescription, ...] = (
key="vehicle_state_tpms_pressure_rl",
polling=True,
streaming_listener=lambda vehicle, callback: vehicle.listen_TpmsPressureRl(
lambda x: callback(None) if x is None else callback(x * ATM_TO_BAR)
lambda x: (
callback(None)
if x is None
else callback(
PressureConverter.convert(x, UnitOfPressure.ATM, UnitOfPressure.BAR)
)
)
),
state_class=SensorStateClass.MEASUREMENT,
native_unit_of_measurement=UnitOfPressure.BAR,
@@ -445,7 +461,13 @@ VEHICLE_DESCRIPTIONS: tuple[TeslemetryVehicleSensorEntityDescription, ...] = (
key="vehicle_state_tpms_pressure_rr",
polling=True,
streaming_listener=lambda vehicle, callback: vehicle.listen_TpmsPressureRr(
lambda x: callback(None) if x is None else callback(x * ATM_TO_BAR)
lambda x: (
callback(None)
if x is None
else callback(
PressureConverter.convert(x, UnitOfPressure.ATM, UnitOfPressure.BAR)
)
)
),
state_class=SensorStateClass.MEASUREMENT,
native_unit_of_measurement=UnitOfPressure.BAR,
+36 -10
View File
@@ -16,11 +16,9 @@ from homeassistant.const import (
STATE_UNKNOWN,
EntityCategory,
Platform,
UnitOfPressure,
)
from homeassistant.core import HomeAssistant
from homeassistant.helpers import entity_registry as er
from homeassistant.util.unit_conversion import PressureConverter
from . import assert_entities, assert_entities_alt, setup_platform
from .const import (
@@ -326,29 +324,25 @@ async def test_hw4_mileage_sensors_gating(
Signal.TPMS_PRESSURE_FL,
"sensor.test_tire_pressure_front_left",
2.7,
# 2.7 atm independently hand-converted to bar (2.7 * 1.01325 = 2.735775)
PressureConverter.convert(2.735775, UnitOfPressure.BAR, UnitOfPressure.PSI),
39.679063381059,
),
(
Signal.TPMS_PRESSURE_FR,
"sensor.test_tire_pressure_front_right",
2.7,
# 2.7 atm independently hand-converted to bar (2.7 * 1.01325 = 2.735775)
PressureConverter.convert(2.735775, UnitOfPressure.BAR, UnitOfPressure.PSI),
39.679063381059,
),
(
Signal.TPMS_PRESSURE_RL,
"sensor.test_tire_pressure_rear_left",
2.7,
# 2.7 atm independently hand-converted to bar (2.7 * 1.01325 = 2.735775)
PressureConverter.convert(2.735775, UnitOfPressure.BAR, UnitOfPressure.PSI),
39.679063381059,
),
(
Signal.TPMS_PRESSURE_RR,
"sensor.test_tire_pressure_rear_right",
2.7,
# 2.7 atm independently hand-converted to bar (2.7 * 1.01325 = 2.735775)
PressureConverter.convert(2.735775, UnitOfPressure.BAR, UnitOfPressure.PSI),
39.679063381059,
),
(
Signal.ISOLATION_RESISTANCE,
@@ -386,6 +380,38 @@ async def test_sensors_streaming_unit_conversion(
assert float(state.state) == pytest.approx(expected_state)
@pytest.mark.usefixtures("entity_registry_enabled_by_default")
async def test_sensors_streaming_tpms_none_clears_state(
hass: HomeAssistant,
mock_vehicle_data: AsyncMock,
mock_add_listener: AsyncMock,
) -> None:
"""A None streamed TPMS pressure must clear the entity, not pass through the converter."""
entity_id = "sensor.test_tire_pressure_front_left"
await setup_platform(hass, [Platform.SENSOR])
vin = VEHICLE_DATA_ALT["response"]["vin"]
mock_add_listener.send(
{
"vin": vin,
"data": {Signal.TPMS_PRESSURE_FL: 2.7},
"createdAt": "2024-10-04T10:45:17.537Z",
}
)
await hass.async_block_till_done()
assert hass.states.get(entity_id).state != STATE_UNKNOWN
mock_add_listener.send(
{
"vin": vin,
"data": {Signal.TPMS_PRESSURE_FL: None},
"createdAt": "2024-10-04T10:45:18.537Z",
}
)
await hass.async_block_till_done()
assert hass.states.get(entity_id).state == STATE_UNKNOWN
@pytest.mark.parametrize(
("key", "signal", "raw_value", "state"),
[