mirror of
https://github.com/home-assistant/core.git
synced 2025-07-16 17:57:11 +00:00
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:
parent
a981117f2d
commit
ee21bc5d7f
@ -59,7 +59,7 @@ CONF_EXPIRE_AFTER = "expire_after"
|
|||||||
|
|
||||||
PLATFORM_SCHEMA_MODERN = MQTT_RO_SCHEMA.extend(
|
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_EXPIRE_AFTER): cv.positive_int,
|
||||||
vol.Optional(CONF_FORCE_UPDATE, default=DEFAULT_FORCE_UPDATE): cv.boolean,
|
vol.Optional(CONF_FORCE_UPDATE, default=DEFAULT_FORCE_UPDATE): cv.boolean,
|
||||||
vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string,
|
vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string,
|
||||||
|
@ -6,7 +6,7 @@ import functools
|
|||||||
import voluptuous as vol
|
import voluptuous as vol
|
||||||
|
|
||||||
from homeassistant.components import button
|
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.config_entries import ConfigEntry
|
||||||
from homeassistant.const import CONF_DEVICE_CLASS, CONF_NAME
|
from homeassistant.const import CONF_DEVICE_CLASS, CONF_NAME
|
||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant
|
||||||
@ -39,7 +39,7 @@ PLATFORM_SCHEMA_MODERN = MQTT_BASE_SCHEMA.extend(
|
|||||||
{
|
{
|
||||||
vol.Optional(CONF_COMMAND_TEMPLATE): cv.template,
|
vol.Optional(CONF_COMMAND_TEMPLATE): cv.template,
|
||||||
vol.Required(CONF_COMMAND_TOPIC): valid_publish_topic,
|
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_NAME, default=DEFAULT_NAME): cv.string,
|
||||||
vol.Optional(CONF_PAYLOAD_PRESS, default=DEFAULT_PAYLOAD_PRESS): cv.string,
|
vol.Optional(CONF_PAYLOAD_PRESS, default=DEFAULT_PAYLOAD_PRESS): cv.string,
|
||||||
vol.Optional(CONF_RETAIN, default=DEFAULT_RETAIN): cv.boolean,
|
vol.Optional(CONF_RETAIN, default=DEFAULT_RETAIN): cv.boolean,
|
||||||
|
@ -161,7 +161,7 @@ def validate_options(config: ConfigType) -> ConfigType:
|
|||||||
_PLATFORM_SCHEMA_BASE = MQTT_BASE_SCHEMA.extend(
|
_PLATFORM_SCHEMA_BASE = MQTT_BASE_SCHEMA.extend(
|
||||||
{
|
{
|
||||||
vol.Optional(CONF_COMMAND_TOPIC): valid_publish_topic,
|
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_GET_POSITION_TOPIC): valid_subscribe_topic,
|
||||||
vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string,
|
vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string,
|
||||||
vol.Optional(CONF_OPTIMISTIC, default=DEFAULT_OPTIMISTIC): cv.boolean,
|
vol.Optional(CONF_OPTIMISTIC, default=DEFAULT_OPTIMISTIC): cv.boolean,
|
||||||
|
@ -86,7 +86,7 @@ def validate_config(config: ConfigType) -> ConfigType:
|
|||||||
_PLATFORM_SCHEMA_BASE = MQTT_RW_SCHEMA.extend(
|
_PLATFORM_SCHEMA_BASE = MQTT_RW_SCHEMA.extend(
|
||||||
{
|
{
|
||||||
vol.Optional(CONF_COMMAND_TEMPLATE): cv.template,
|
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_MAX, default=DEFAULT_MAX_VALUE): vol.Coerce(float),
|
||||||
vol.Optional(CONF_MIN, default=DEFAULT_MIN_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),
|
vol.Optional(CONF_MODE, default=NumberMode.AUTO): vol.Coerce(NumberMode),
|
||||||
|
@ -98,13 +98,13 @@ def validate_options(conf: ConfigType) -> ConfigType:
|
|||||||
|
|
||||||
_PLATFORM_SCHEMA_BASE = MQTT_RO_SCHEMA.extend(
|
_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_EXPIRE_AFTER): cv.positive_int,
|
||||||
vol.Optional(CONF_FORCE_UPDATE, default=DEFAULT_FORCE_UPDATE): cv.boolean,
|
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_TOPIC): valid_subscribe_topic,
|
||||||
vol.Optional(CONF_LAST_RESET_VALUE_TEMPLATE): cv.template,
|
vol.Optional(CONF_LAST_RESET_VALUE_TEMPLATE): cv.template,
|
||||||
vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string,
|
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,
|
vol.Optional(CONF_UNIT_OF_MEASUREMENT): cv.string,
|
||||||
}
|
}
|
||||||
).extend(MQTT_ENTITY_COMMON_SCHEMA.schema)
|
).extend(MQTT_ENTITY_COMMON_SCHEMA.schema)
|
||||||
|
@ -60,7 +60,7 @@ PLATFORM_SCHEMA_MODERN = MQTT_RW_SCHEMA.extend(
|
|||||||
vol.Optional(CONF_STATE_OFF): cv.string,
|
vol.Optional(CONF_STATE_OFF): cv.string,
|
||||||
vol.Optional(CONF_STATE_ON): cv.string,
|
vol.Optional(CONF_STATE_ON): cv.string,
|
||||||
vol.Optional(CONF_VALUE_TEMPLATE): cv.template,
|
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)
|
).extend(MQTT_ENTITY_COMMON_SCHEMA.schema)
|
||||||
|
|
||||||
|
@ -54,7 +54,7 @@ CONF_TITLE = "title"
|
|||||||
PLATFORM_SCHEMA_MODERN = MQTT_RO_SCHEMA.extend(
|
PLATFORM_SCHEMA_MODERN = MQTT_RO_SCHEMA.extend(
|
||||||
{
|
{
|
||||||
vol.Optional(CONF_COMMAND_TOPIC): valid_publish_topic,
|
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_ENTITY_PICTURE): cv.string,
|
||||||
vol.Optional(CONF_LATEST_VERSION_TEMPLATE): cv.template,
|
vol.Optional(CONF_LATEST_VERSION_TEMPLATE): cv.template,
|
||||||
vol.Optional(CONF_LATEST_VERSION_TOPIC): valid_subscribe_topic,
|
vol.Optional(CONF_LATEST_VERSION_TOPIC): valid_subscribe_topic,
|
||||||
|
@ -689,6 +689,11 @@ async def test_valid_device_class(hass, mqtt_mock_entry_with_yaml_config):
|
|||||||
"device_class": "temperature",
|
"device_class": "temperature",
|
||||||
},
|
},
|
||||||
{"name": "Test 2", "state_topic": "test-topic"},
|
{"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"
|
assert state.attributes["device_class"] == "temperature"
|
||||||
state = hass.states.get("sensor.test_2")
|
state = hass.states.get("sensor.test_2")
|
||||||
assert "device_class" not in state.attributes
|
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):
|
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",
|
"state_class": "measurement",
|
||||||
},
|
},
|
||||||
{"name": "Test 2", "state_topic": "test-topic"},
|
{"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"
|
assert state.attributes["state_class"] == "measurement"
|
||||||
state = hass.states.get("sensor.test_2")
|
state = hass.states.get("sensor.test_2")
|
||||||
assert "state_class" not in state.attributes
|
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(
|
async def test_setting_attribute_via_mqtt_json_message(
|
||||||
|
Loading…
x
Reference in New Issue
Block a user