Allow MQTT device_class or state_class to be set as None (#85106)

* Allow MQTT device_class to be set as `None`

* Add test

* Also allow sensor state_class to be `None`
This commit is contained in:
Jan Bouwhuis 2023-01-04 15:21:07 +01:00 committed by GitHub
parent a981117f2d
commit ee21bc5d7f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 23 additions and 9 deletions

View file

@ -59,7 +59,7 @@ CONF_EXPIRE_AFTER = "expire_after"
PLATFORM_SCHEMA_MODERN = MQTT_RO_SCHEMA.extend(
{
vol.Optional(CONF_DEVICE_CLASS): DEVICE_CLASSES_SCHEMA,
vol.Optional(CONF_DEVICE_CLASS): vol.Any(DEVICE_CLASSES_SCHEMA, None),
vol.Optional(CONF_EXPIRE_AFTER): cv.positive_int,
vol.Optional(CONF_FORCE_UPDATE, default=DEFAULT_FORCE_UPDATE): cv.boolean,
vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string,

View file

@ -6,7 +6,7 @@ import functools
import voluptuous as vol
from homeassistant.components import button
from homeassistant.components.button import ButtonEntity
from homeassistant.components.button import DEVICE_CLASSES_SCHEMA, ButtonEntity
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import CONF_DEVICE_CLASS, CONF_NAME
from homeassistant.core import HomeAssistant
@ -39,7 +39,7 @@ PLATFORM_SCHEMA_MODERN = MQTT_BASE_SCHEMA.extend(
{
vol.Optional(CONF_COMMAND_TEMPLATE): cv.template,
vol.Required(CONF_COMMAND_TOPIC): valid_publish_topic,
vol.Optional(CONF_DEVICE_CLASS): button.DEVICE_CLASSES_SCHEMA,
vol.Optional(CONF_DEVICE_CLASS): vol.Any(DEVICE_CLASSES_SCHEMA, None),
vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string,
vol.Optional(CONF_PAYLOAD_PRESS, default=DEFAULT_PAYLOAD_PRESS): cv.string,
vol.Optional(CONF_RETAIN, default=DEFAULT_RETAIN): cv.boolean,

View file

@ -161,7 +161,7 @@ def validate_options(config: ConfigType) -> ConfigType:
_PLATFORM_SCHEMA_BASE = MQTT_BASE_SCHEMA.extend(
{
vol.Optional(CONF_COMMAND_TOPIC): valid_publish_topic,
vol.Optional(CONF_DEVICE_CLASS): DEVICE_CLASSES_SCHEMA,
vol.Optional(CONF_DEVICE_CLASS): vol.Any(DEVICE_CLASSES_SCHEMA, None),
vol.Optional(CONF_GET_POSITION_TOPIC): valid_subscribe_topic,
vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string,
vol.Optional(CONF_OPTIMISTIC, default=DEFAULT_OPTIMISTIC): cv.boolean,

View file

@ -86,7 +86,7 @@ def validate_config(config: ConfigType) -> ConfigType:
_PLATFORM_SCHEMA_BASE = MQTT_RW_SCHEMA.extend(
{
vol.Optional(CONF_COMMAND_TEMPLATE): cv.template,
vol.Optional(CONF_DEVICE_CLASS): DEVICE_CLASSES_SCHEMA,
vol.Optional(CONF_DEVICE_CLASS): vol.Any(DEVICE_CLASSES_SCHEMA, None),
vol.Optional(CONF_MAX, default=DEFAULT_MAX_VALUE): vol.Coerce(float),
vol.Optional(CONF_MIN, default=DEFAULT_MIN_VALUE): vol.Coerce(float),
vol.Optional(CONF_MODE, default=NumberMode.AUTO): vol.Coerce(NumberMode),

View file

@ -98,13 +98,13 @@ def validate_options(conf: ConfigType) -> ConfigType:
_PLATFORM_SCHEMA_BASE = MQTT_RO_SCHEMA.extend(
{
vol.Optional(CONF_DEVICE_CLASS): DEVICE_CLASSES_SCHEMA,
vol.Optional(CONF_DEVICE_CLASS): vol.Any(DEVICE_CLASSES_SCHEMA, None),
vol.Optional(CONF_EXPIRE_AFTER): cv.positive_int,
vol.Optional(CONF_FORCE_UPDATE, default=DEFAULT_FORCE_UPDATE): cv.boolean,
vol.Optional(CONF_LAST_RESET_TOPIC): valid_subscribe_topic,
vol.Optional(CONF_LAST_RESET_VALUE_TEMPLATE): cv.template,
vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string,
vol.Optional(CONF_STATE_CLASS): STATE_CLASSES_SCHEMA,
vol.Optional(CONF_STATE_CLASS): vol.Any(STATE_CLASSES_SCHEMA, None),
vol.Optional(CONF_UNIT_OF_MEASUREMENT): cv.string,
}
).extend(MQTT_ENTITY_COMMON_SCHEMA.schema)

View file

@ -60,7 +60,7 @@ PLATFORM_SCHEMA_MODERN = MQTT_RW_SCHEMA.extend(
vol.Optional(CONF_STATE_OFF): cv.string,
vol.Optional(CONF_STATE_ON): cv.string,
vol.Optional(CONF_VALUE_TEMPLATE): cv.template,
vol.Optional(CONF_DEVICE_CLASS): DEVICE_CLASSES_SCHEMA,
vol.Optional(CONF_DEVICE_CLASS): vol.Any(DEVICE_CLASSES_SCHEMA, None),
}
).extend(MQTT_ENTITY_COMMON_SCHEMA.schema)

View file

@ -54,7 +54,7 @@ CONF_TITLE = "title"
PLATFORM_SCHEMA_MODERN = MQTT_RO_SCHEMA.extend(
{
vol.Optional(CONF_COMMAND_TOPIC): valid_publish_topic,
vol.Optional(CONF_DEVICE_CLASS): DEVICE_CLASSES_SCHEMA,
vol.Optional(CONF_DEVICE_CLASS): vol.Any(DEVICE_CLASSES_SCHEMA, None),
vol.Optional(CONF_ENTITY_PICTURE): cv.string,
vol.Optional(CONF_LATEST_VERSION_TEMPLATE): cv.template,
vol.Optional(CONF_LATEST_VERSION_TOPIC): valid_subscribe_topic,

View file

@ -689,6 +689,11 @@ async def test_valid_device_class(hass, mqtt_mock_entry_with_yaml_config):
"device_class": "temperature",
},
{"name": "Test 2", "state_topic": "test-topic"},
{
"name": "Test 3",
"state_topic": "test-topic",
"device_class": None,
},
]
}
},
@ -700,6 +705,8 @@ async def test_valid_device_class(hass, mqtt_mock_entry_with_yaml_config):
assert state.attributes["device_class"] == "temperature"
state = hass.states.get("sensor.test_2")
assert "device_class" not in state.attributes
state = hass.states.get("sensor.test_3")
assert "device_class" not in state.attributes
async def test_invalid_state_class(hass, mqtt_mock_entry_no_yaml_config):
@ -738,6 +745,11 @@ async def test_valid_state_class(hass, mqtt_mock_entry_with_yaml_config):
"state_class": "measurement",
},
{"name": "Test 2", "state_topic": "test-topic"},
{
"name": "Test 3",
"state_topic": "test-topic",
"state_class": None,
},
]
}
},
@ -749,6 +761,8 @@ async def test_valid_state_class(hass, mqtt_mock_entry_with_yaml_config):
assert state.attributes["state_class"] == "measurement"
state = hass.states.get("sensor.test_2")
assert "state_class" not in state.attributes
state = hass.states.get("sensor.test_3")
assert "state_class" not in state.attributes
async def test_setting_attribute_via_mqtt_json_message(