Validate state_class with last_reset_value_template for mqtt sensors (#113099)
This commit is contained in:
parent
012291a1f3
commit
e28d4f0eae
2 changed files with 79 additions and 0 deletions
|
@ -18,6 +18,7 @@ from homeassistant.components.sensor import (
|
||||||
RestoreSensor,
|
RestoreSensor,
|
||||||
SensorDeviceClass,
|
SensorDeviceClass,
|
||||||
SensorExtraStoredData,
|
SensorExtraStoredData,
|
||||||
|
SensorStateClass,
|
||||||
)
|
)
|
||||||
from homeassistant.config_entries import ConfigEntry
|
from homeassistant.config_entries import ConfigEntry
|
||||||
from homeassistant.const import (
|
from homeassistant.const import (
|
||||||
|
@ -84,11 +85,27 @@ _PLATFORM_SCHEMA_BASE = MQTT_RO_SCHEMA.extend(
|
||||||
}
|
}
|
||||||
).extend(MQTT_ENTITY_COMMON_SCHEMA.schema)
|
).extend(MQTT_ENTITY_COMMON_SCHEMA.schema)
|
||||||
|
|
||||||
|
|
||||||
|
def validate_sensor_state_class_config(config: ConfigType) -> ConfigType:
|
||||||
|
"""Validate the sensor state class config."""
|
||||||
|
if (
|
||||||
|
CONF_LAST_RESET_VALUE_TEMPLATE in config
|
||||||
|
and (state_class := config.get(CONF_STATE_CLASS)) != SensorStateClass.TOTAL
|
||||||
|
):
|
||||||
|
raise vol.Invalid(
|
||||||
|
f"The option `{CONF_LAST_RESET_VALUE_TEMPLATE}` cannot be used "
|
||||||
|
f"together with state class `{state_class}`"
|
||||||
|
)
|
||||||
|
|
||||||
|
return config
|
||||||
|
|
||||||
|
|
||||||
PLATFORM_SCHEMA_MODERN = vol.All(
|
PLATFORM_SCHEMA_MODERN = vol.All(
|
||||||
# Deprecated in HA Core 2021.11.0 https://github.com/home-assistant/core/pull/54840
|
# Deprecated in HA Core 2021.11.0 https://github.com/home-assistant/core/pull/54840
|
||||||
# Removed in HA Core 2023.6.0
|
# Removed in HA Core 2023.6.0
|
||||||
cv.removed(CONF_LAST_RESET_TOPIC),
|
cv.removed(CONF_LAST_RESET_TOPIC),
|
||||||
_PLATFORM_SCHEMA_BASE,
|
_PLATFORM_SCHEMA_BASE,
|
||||||
|
validate_sensor_state_class_config,
|
||||||
)
|
)
|
||||||
|
|
||||||
DISCOVERY_SCHEMA = vol.All(
|
DISCOVERY_SCHEMA = vol.All(
|
||||||
|
@ -96,6 +113,7 @@ DISCOVERY_SCHEMA = vol.All(
|
||||||
# Removed in HA Core 2023.6.0
|
# Removed in HA Core 2023.6.0
|
||||||
cv.removed(CONF_LAST_RESET_TOPIC),
|
cv.removed(CONF_LAST_RESET_TOPIC),
|
||||||
_PLATFORM_SCHEMA_BASE.extend({}, extra=vol.REMOVE_EXTRA),
|
_PLATFORM_SCHEMA_BASE.extend({}, extra=vol.REMOVE_EXTRA),
|
||||||
|
validate_sensor_state_class_config,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1449,6 +1449,7 @@ async def test_entity_name(
|
||||||
DEFAULT_CONFIG,
|
DEFAULT_CONFIG,
|
||||||
(
|
(
|
||||||
{
|
{
|
||||||
|
"state_class": "total",
|
||||||
"availability_topic": "availability-topic",
|
"availability_topic": "availability-topic",
|
||||||
"json_attributes_topic": "json-attributes-topic",
|
"json_attributes_topic": "json-attributes-topic",
|
||||||
"value_template": "{{ value_json.state }}",
|
"value_template": "{{ value_json.state }}",
|
||||||
|
@ -1491,6 +1492,7 @@ async def test_skipped_async_ha_write_state(
|
||||||
DEFAULT_CONFIG,
|
DEFAULT_CONFIG,
|
||||||
(
|
(
|
||||||
{
|
{
|
||||||
|
"state_class": "total",
|
||||||
"value_template": "{{ value_json.some_var * 1 }}",
|
"value_template": "{{ value_json.some_var * 1 }}",
|
||||||
"last_reset_value_template": "{{ value_json.some_var * 2 }}",
|
"last_reset_value_template": "{{ value_json.some_var * 2 }}",
|
||||||
},
|
},
|
||||||
|
@ -1510,3 +1512,62 @@ async def test_value_template_fails(
|
||||||
"TypeError: unsupported operand type(s) for *: 'NoneType' and 'int' rendering template"
|
"TypeError: unsupported operand type(s) for *: 'NoneType' and 'int' rendering template"
|
||||||
in caplog.text
|
in caplog.text
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
"hass_config",
|
||||||
|
[
|
||||||
|
help_custom_config(
|
||||||
|
sensor.DOMAIN,
|
||||||
|
DEFAULT_CONFIG,
|
||||||
|
(
|
||||||
|
{
|
||||||
|
"state_class": "total_increasing",
|
||||||
|
"last_reset_value_template": "{{ value_json.last_reset }}",
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
help_custom_config(
|
||||||
|
sensor.DOMAIN,
|
||||||
|
DEFAULT_CONFIG,
|
||||||
|
(
|
||||||
|
{
|
||||||
|
"state_class": "measurement",
|
||||||
|
"last_reset_value_template": "{{ value_json.last_reset }}",
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
help_custom_config(
|
||||||
|
sensor.DOMAIN,
|
||||||
|
DEFAULT_CONFIG,
|
||||||
|
(
|
||||||
|
{
|
||||||
|
"last_reset_value_template": "{{ value_json.last_reset }}",
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
async def test_value_incorrect_state_class_config(
|
||||||
|
hass: HomeAssistant,
|
||||||
|
mqtt_mock_entry: MqttMockHAClientGenerator,
|
||||||
|
caplog: pytest.LogCaptureFixture,
|
||||||
|
hass_config: ConfigType,
|
||||||
|
) -> None:
|
||||||
|
"""Test a sensor config with incorrect state_class config fails from yaml or discovery."""
|
||||||
|
await mqtt_mock_entry()
|
||||||
|
assert (
|
||||||
|
"The option `last_reset_value_template` cannot be used together with state class"
|
||||||
|
in caplog.text
|
||||||
|
)
|
||||||
|
caplog.clear()
|
||||||
|
|
||||||
|
config_payload = hass_config[mqtt.DOMAIN][sensor.DOMAIN][0]
|
||||||
|
async_fire_mqtt_message(
|
||||||
|
hass, "homeassistant/sensor/bla/config", json.dumps(config_payload)
|
||||||
|
)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
assert (
|
||||||
|
"The option `last_reset_value_template` cannot be used together with state class"
|
||||||
|
in caplog.text
|
||||||
|
)
|
||||||
|
|
Loading…
Add table
Reference in a new issue