Remove deprecated features from MQTT platforms (#32909)
* Remove deprecated features * Lintpull/32997/head
parent
5c1dc60505
commit
e0d2e5dcb0
|
@ -11,7 +11,7 @@ from homeassistant.helpers.dispatcher import async_dispatcher_send
|
|||
from homeassistant.helpers.typing import HomeAssistantType
|
||||
|
||||
from .abbreviations import ABBREVIATIONS, DEVICE_ABBREVIATIONS
|
||||
from .const import ATTR_DISCOVERY_HASH, ATTR_DISCOVERY_TOPIC, CONF_STATE_TOPIC
|
||||
from .const import ATTR_DISCOVERY_HASH, ATTR_DISCOVERY_TOPIC
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
@ -50,15 +50,6 @@ CONFIG_ENTRY_COMPONENTS = [
|
|||
"vacuum",
|
||||
]
|
||||
|
||||
DEPRECATED_PLATFORM_TO_SCHEMA = {
|
||||
"light": {"mqtt_json": "json", "mqtt_template": "template"}
|
||||
}
|
||||
|
||||
# These components require state_topic to be set.
|
||||
# If not specified, infer state_topic from discovery topic.
|
||||
IMPLICIT_STATE_TOPIC_COMPONENTS = ["alarm_control_panel", "binary_sensor", "sensor"]
|
||||
|
||||
|
||||
ALREADY_DISCOVERED = "mqtt_discovered_components"
|
||||
DATA_CONFIG_ENTRY_LOCK = "mqtt_config_entry_lock"
|
||||
CONFIG_ENTRY_IS_SETUP = "mqtt_config_entry_is_setup"
|
||||
|
@ -143,39 +134,8 @@ async def async_start(
|
|||
}
|
||||
setattr(payload, "discovery_data", discovery_data)
|
||||
|
||||
if CONF_PLATFORM in payload and "schema" not in payload:
|
||||
platform = payload[CONF_PLATFORM]
|
||||
if (
|
||||
component in DEPRECATED_PLATFORM_TO_SCHEMA
|
||||
and platform in DEPRECATED_PLATFORM_TO_SCHEMA[component]
|
||||
):
|
||||
schema = DEPRECATED_PLATFORM_TO_SCHEMA[component][platform]
|
||||
payload["schema"] = schema
|
||||
_LOGGER.warning(
|
||||
'"platform": "%s" is deprecated, ' 'replace with "schema":"%s"',
|
||||
platform,
|
||||
schema,
|
||||
)
|
||||
payload[CONF_PLATFORM] = "mqtt"
|
||||
|
||||
if (
|
||||
CONF_STATE_TOPIC not in payload
|
||||
and component in IMPLICIT_STATE_TOPIC_COMPONENTS
|
||||
):
|
||||
# state_topic not specified, infer from discovery topic
|
||||
fmt_node_id = f"{node_id}/" if node_id else ""
|
||||
payload[
|
||||
CONF_STATE_TOPIC
|
||||
] = f"{discovery_topic}/{component}/{fmt_node_id}{object_id}/state"
|
||||
_LOGGER.warning(
|
||||
'implicit %s is deprecated, add "%s":"%s" to '
|
||||
"%s discovery message",
|
||||
CONF_STATE_TOPIC,
|
||||
CONF_STATE_TOPIC,
|
||||
payload[CONF_STATE_TOPIC],
|
||||
topic,
|
||||
)
|
||||
|
||||
if ALREADY_DISCOVERED not in hass.data:
|
||||
hass.data[ALREADY_DISCOVERED] = {}
|
||||
if discovery_hash in hass.data[ALREADY_DISCOVERED]:
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
"""Support for MQTT sensors."""
|
||||
from datetime import timedelta
|
||||
import json
|
||||
import logging
|
||||
from typing import Optional
|
||||
|
||||
|
@ -41,7 +40,6 @@ from .discovery import MQTT_DISCOVERY_NEW, clear_discovery_hash
|
|||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
CONF_EXPIRE_AFTER = "expire_after"
|
||||
CONF_JSON_ATTRS = "json_attributes"
|
||||
|
||||
DEFAULT_NAME = "MQTT Sensor"
|
||||
DEFAULT_FORCE_UPDATE = False
|
||||
|
@ -53,7 +51,6 @@ PLATFORM_SCHEMA = (
|
|||
vol.Optional(CONF_EXPIRE_AFTER): cv.positive_int,
|
||||
vol.Optional(CONF_FORCE_UPDATE, default=DEFAULT_FORCE_UPDATE): cv.boolean,
|
||||
vol.Optional(CONF_ICON): cv.icon,
|
||||
vol.Optional(CONF_JSON_ATTRS, default=[]): cv.ensure_list_csv,
|
||||
vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string,
|
||||
vol.Optional(CONF_UNIQUE_ID): cv.string,
|
||||
vol.Optional(CONF_UNIT_OF_MEASUREMENT): cv.string,
|
||||
|
@ -110,16 +107,9 @@ class MqttSensor(
|
|||
self._state = None
|
||||
self._sub_state = None
|
||||
self._expiration_trigger = None
|
||||
self._attributes = None
|
||||
|
||||
device_config = config.get(CONF_DEVICE)
|
||||
|
||||
if config.get(CONF_JSON_ATTRS):
|
||||
_LOGGER.warning(
|
||||
'configuration variable "json_attributes" is '
|
||||
'deprecated, replace with "json_attributes_topic"'
|
||||
)
|
||||
|
||||
MqttAttributes.__init__(self, config)
|
||||
MqttAvailability.__init__(self, config)
|
||||
MqttDiscoveryUpdate.__init__(self, discovery_data, self.discovery_update)
|
||||
|
@ -165,22 +155,6 @@ class MqttSensor(
|
|||
self.hass, self.value_is_expired, expiration_at
|
||||
)
|
||||
|
||||
json_attributes = set(self._config[CONF_JSON_ATTRS])
|
||||
if json_attributes:
|
||||
self._attributes = {}
|
||||
try:
|
||||
json_dict = json.loads(payload)
|
||||
if isinstance(json_dict, dict):
|
||||
attrs = {
|
||||
k: json_dict[k] for k in json_attributes & json_dict.keys()
|
||||
}
|
||||
self._attributes = attrs
|
||||
else:
|
||||
_LOGGER.warning("JSON result was not a dictionary")
|
||||
except ValueError:
|
||||
_LOGGER.warning("MQTT payload could not be parsed as JSON")
|
||||
_LOGGER.debug("Erroneous JSON: %s", payload)
|
||||
|
||||
if template is not None:
|
||||
payload = template.async_render_with_possible_json_value(
|
||||
payload, self._state
|
||||
|
@ -241,11 +215,6 @@ class MqttSensor(
|
|||
"""Return the state of the entity."""
|
||||
return self._state
|
||||
|
||||
@property
|
||||
def device_state_attributes(self):
|
||||
"""Return the state attributes."""
|
||||
return self._attributes
|
||||
|
||||
@property
|
||||
def unique_id(self):
|
||||
"""Return a unique ID."""
|
||||
|
|
|
@ -117,7 +117,9 @@ async def test_correct_config_discovery(hass, mqtt_mock, caplog):
|
|||
await async_start(hass, "homeassistant", {}, entry)
|
||||
|
||||
async_fire_mqtt_message(
|
||||
hass, "homeassistant/binary_sensor/bla/config", '{ "name": "Beer" }'
|
||||
hass,
|
||||
"homeassistant/binary_sensor/bla/config",
|
||||
'{ "name": "Beer", "state_topic": "test-topic" }',
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
|
@ -199,7 +201,9 @@ async def test_discovery_incl_nodeid(hass, mqtt_mock, caplog):
|
|||
await async_start(hass, "homeassistant", {}, entry)
|
||||
|
||||
async_fire_mqtt_message(
|
||||
hass, "homeassistant/binary_sensor/my_node_id/bla/config", '{ "name": "Beer" }',
|
||||
hass,
|
||||
"homeassistant/binary_sensor/my_node_id/bla/config",
|
||||
'{ "name": "Beer", "state_topic": "test-topic" }',
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
|
@ -217,10 +221,14 @@ async def test_non_duplicate_discovery(hass, mqtt_mock, caplog):
|
|||
await async_start(hass, "homeassistant", {}, entry)
|
||||
|
||||
async_fire_mqtt_message(
|
||||
hass, "homeassistant/binary_sensor/bla/config", '{ "name": "Beer" }'
|
||||
hass,
|
||||
"homeassistant/binary_sensor/bla/config",
|
||||
'{ "name": "Beer", "state_topic": "test-topic" }',
|
||||
)
|
||||
async_fire_mqtt_message(
|
||||
hass, "homeassistant/binary_sensor/bla/config", '{ "name": "Beer" }'
|
||||
hass,
|
||||
"homeassistant/binary_sensor/bla/config",
|
||||
'{ "name": "Beer", "state_topic": "test-topic" }',
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
|
@ -240,7 +248,9 @@ async def test_removal(hass, mqtt_mock, caplog):
|
|||
await async_start(hass, "homeassistant", {}, entry)
|
||||
|
||||
async_fire_mqtt_message(
|
||||
hass, "homeassistant/binary_sensor/bla/config", '{ "name": "Beer" }'
|
||||
hass,
|
||||
"homeassistant/binary_sensor/bla/config",
|
||||
'{ "name": "Beer", "state_topic": "test-topic" }',
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
state = hass.states.get("binary_sensor.beer")
|
||||
|
@ -259,7 +269,9 @@ async def test_rediscover(hass, mqtt_mock, caplog):
|
|||
await async_start(hass, "homeassistant", {}, entry)
|
||||
|
||||
async_fire_mqtt_message(
|
||||
hass, "homeassistant/binary_sensor/bla/config", '{ "name": "Beer" }'
|
||||
hass,
|
||||
"homeassistant/binary_sensor/bla/config",
|
||||
'{ "name": "Beer", "state_topic": "test-topic" }',
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
state = hass.states.get("binary_sensor.beer")
|
||||
|
@ -271,7 +283,9 @@ async def test_rediscover(hass, mqtt_mock, caplog):
|
|||
assert state is None
|
||||
|
||||
async_fire_mqtt_message(
|
||||
hass, "homeassistant/binary_sensor/bla/config", '{ "name": "Beer" }'
|
||||
hass,
|
||||
"homeassistant/binary_sensor/bla/config",
|
||||
'{ "name": "Beer", "state_topic": "test-topic" }',
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
state = hass.states.get("binary_sensor.beer")
|
||||
|
@ -285,7 +299,9 @@ async def test_duplicate_removal(hass, mqtt_mock, caplog):
|
|||
await async_start(hass, "homeassistant", {}, entry)
|
||||
|
||||
async_fire_mqtt_message(
|
||||
hass, "homeassistant/binary_sensor/bla/config", '{ "name": "Beer" }'
|
||||
hass,
|
||||
"homeassistant/binary_sensor/bla/config",
|
||||
'{ "name": "Beer", "state_topic": "test-topic" }',
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
async_fire_mqtt_message(hass, "homeassistant/binary_sensor/bla/config", "")
|
||||
|
@ -431,93 +447,6 @@ async def test_missing_discover_abbreviations(hass, mqtt_mock, caplog):
|
|||
assert not missing
|
||||
|
||||
|
||||
async def test_implicit_state_topic_alarm(hass, mqtt_mock, caplog):
|
||||
"""Test implicit state topic for alarm_control_panel."""
|
||||
entry = MockConfigEntry(domain=mqtt.DOMAIN)
|
||||
|
||||
await async_start(hass, "homeassistant", {}, entry)
|
||||
|
||||
data = (
|
||||
'{ "name": "Test1",'
|
||||
' "command_topic": "homeassistant/alarm_control_panel/bla/cmnd"'
|
||||
"}"
|
||||
)
|
||||
|
||||
async_fire_mqtt_message(hass, "homeassistant/alarm_control_panel/bla/config", data)
|
||||
await hass.async_block_till_done()
|
||||
assert (
|
||||
"implicit state_topic is deprecated, add "
|
||||
'"state_topic":"homeassistant/alarm_control_panel/bla/state"' in caplog.text
|
||||
)
|
||||
|
||||
state = hass.states.get("alarm_control_panel.Test1")
|
||||
assert state is not None
|
||||
assert state.name == "Test1"
|
||||
assert ("alarm_control_panel", "bla") in hass.data[ALREADY_DISCOVERED]
|
||||
assert state.state == "unknown"
|
||||
|
||||
async_fire_mqtt_message(
|
||||
hass, "homeassistant/alarm_control_panel/bla/state", "armed_away"
|
||||
)
|
||||
|
||||
state = hass.states.get("alarm_control_panel.Test1")
|
||||
assert state.state == "armed_away"
|
||||
|
||||
|
||||
async def test_implicit_state_topic_binary_sensor(hass, mqtt_mock, caplog):
|
||||
"""Test implicit state topic for binary_sensor."""
|
||||
entry = MockConfigEntry(domain=mqtt.DOMAIN)
|
||||
|
||||
await async_start(hass, "homeassistant", {}, entry)
|
||||
|
||||
data = '{ "name": "Test1"' "}"
|
||||
|
||||
async_fire_mqtt_message(hass, "homeassistant/binary_sensor/bla/config", data)
|
||||
await hass.async_block_till_done()
|
||||
assert (
|
||||
"implicit state_topic is deprecated, add "
|
||||
'"state_topic":"homeassistant/binary_sensor/bla/state"' in caplog.text
|
||||
)
|
||||
|
||||
state = hass.states.get("binary_sensor.Test1")
|
||||
assert state is not None
|
||||
assert state.name == "Test1"
|
||||
assert ("binary_sensor", "bla") in hass.data[ALREADY_DISCOVERED]
|
||||
assert state.state == "off"
|
||||
|
||||
async_fire_mqtt_message(hass, "homeassistant/binary_sensor/bla/state", "ON")
|
||||
|
||||
state = hass.states.get("binary_sensor.Test1")
|
||||
assert state.state == "on"
|
||||
|
||||
|
||||
async def test_implicit_state_topic_sensor(hass, mqtt_mock, caplog):
|
||||
"""Test implicit state topic for sensor."""
|
||||
entry = MockConfigEntry(domain=mqtt.DOMAIN)
|
||||
|
||||
await async_start(hass, "homeassistant", {}, entry)
|
||||
|
||||
data = '{ "name": "Test1"' "}"
|
||||
|
||||
async_fire_mqtt_message(hass, "homeassistant/sensor/bla/config", data)
|
||||
await hass.async_block_till_done()
|
||||
assert (
|
||||
"implicit state_topic is deprecated, add "
|
||||
'"state_topic":"homeassistant/sensor/bla/state"' in caplog.text
|
||||
)
|
||||
|
||||
state = hass.states.get("sensor.Test1")
|
||||
assert state is not None
|
||||
assert state.name == "Test1"
|
||||
assert ("sensor", "bla") in hass.data[ALREADY_DISCOVERED]
|
||||
assert state.state == "unknown"
|
||||
|
||||
async_fire_mqtt_message(hass, "homeassistant/sensor/bla/state", "1234")
|
||||
|
||||
state = hass.states.get("sensor.Test1")
|
||||
assert state.state == "1234"
|
||||
|
||||
|
||||
async def test_no_implicit_state_topic_switch(hass, mqtt_mock, caplog):
|
||||
"""Test no implicit state topic for switch."""
|
||||
entry = MockConfigEntry(domain=mqtt.DOMAIN)
|
||||
|
@ -552,7 +481,7 @@ async def test_complex_discovery_topic_prefix(hass, mqtt_mock, caplog):
|
|||
async_fire_mqtt_message(
|
||||
hass,
|
||||
("my_home/homeassistant/register/binary_sensor/node1/object1/config"),
|
||||
'{ "name": "Beer" }',
|
||||
'{ "name": "Beer", "state_topic": "test-topic" }',
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
|
|
|
@ -91,8 +91,7 @@ import json
|
|||
from unittest import mock
|
||||
from unittest.mock import patch
|
||||
|
||||
from homeassistant.components import light, mqtt
|
||||
from homeassistant.components.mqtt.discovery import async_start
|
||||
from homeassistant.components import light
|
||||
from homeassistant.const import (
|
||||
ATTR_ASSUMED_STATE,
|
||||
ATTR_SUPPORTED_FEATURES,
|
||||
|
@ -122,7 +121,7 @@ from .common import (
|
|||
help_test_update_with_json_attrs_not_dict,
|
||||
)
|
||||
|
||||
from tests.common import MockConfigEntry, async_fire_mqtt_message, mock_coro
|
||||
from tests.common import async_fire_mqtt_message, mock_coro
|
||||
from tests.components.light import common
|
||||
|
||||
DEFAULT_CONFIG = {
|
||||
|
@ -1061,22 +1060,6 @@ async def test_discovery_removal(hass, mqtt_mock, caplog):
|
|||
await help_test_discovery_removal(hass, mqtt_mock, caplog, light.DOMAIN, data)
|
||||
|
||||
|
||||
async def test_discovery_deprecated(hass, mqtt_mock, caplog):
|
||||
"""Test discovery of mqtt_json light with deprecated platform option."""
|
||||
entry = MockConfigEntry(domain=mqtt.DOMAIN)
|
||||
await async_start(hass, "homeassistant", {"mqtt": {}}, entry)
|
||||
data = (
|
||||
'{ "name": "Beer",'
|
||||
' "platform": "mqtt_json",'
|
||||
' "command_topic": "test_topic"}'
|
||||
)
|
||||
async_fire_mqtt_message(hass, "homeassistant/light/bla/config", data)
|
||||
await hass.async_block_till_done()
|
||||
state = hass.states.get("light.beer")
|
||||
assert state is not None
|
||||
assert state.name == "Beer"
|
||||
|
||||
|
||||
async def test_discovery_update_light(hass, mqtt_mock, caplog):
|
||||
"""Test update of discovered light."""
|
||||
data1 = (
|
||||
|
|
|
@ -28,8 +28,7 @@ If your light doesn't support RGB feature, omit `(red|green|blue)_template`.
|
|||
"""
|
||||
from unittest.mock import patch
|
||||
|
||||
from homeassistant.components import light, mqtt
|
||||
from homeassistant.components.mqtt.discovery import async_start
|
||||
from homeassistant.components import light
|
||||
from homeassistant.const import (
|
||||
ATTR_ASSUMED_STATE,
|
||||
ATTR_SUPPORTED_FEATURES,
|
||||
|
@ -59,12 +58,7 @@ from .common import (
|
|||
help_test_update_with_json_attrs_not_dict,
|
||||
)
|
||||
|
||||
from tests.common import (
|
||||
MockConfigEntry,
|
||||
assert_setup_component,
|
||||
async_fire_mqtt_message,
|
||||
mock_coro,
|
||||
)
|
||||
from tests.common import assert_setup_component, async_fire_mqtt_message, mock_coro
|
||||
from tests.components.light import common
|
||||
|
||||
DEFAULT_CONFIG = {
|
||||
|
@ -883,24 +877,6 @@ async def test_discovery_removal(hass, mqtt_mock, caplog):
|
|||
await help_test_discovery_removal(hass, mqtt_mock, caplog, light.DOMAIN, data)
|
||||
|
||||
|
||||
async def test_discovery_deprecated(hass, mqtt_mock, caplog):
|
||||
"""Test discovery of mqtt template light with deprecated option."""
|
||||
entry = MockConfigEntry(domain=mqtt.DOMAIN)
|
||||
await async_start(hass, "homeassistant", {"mqtt": {}}, entry)
|
||||
data = (
|
||||
'{ "name": "Beer",'
|
||||
' "platform": "mqtt_template",'
|
||||
' "command_topic": "test_topic",'
|
||||
' "command_on_template": "on",'
|
||||
' "command_off_template": "off"}'
|
||||
)
|
||||
async_fire_mqtt_message(hass, "homeassistant/light/bla/config", data)
|
||||
await hass.async_block_till_done()
|
||||
state = hass.states.get("light.beer")
|
||||
assert state is not None
|
||||
assert state.name == "Beer"
|
||||
|
||||
|
||||
async def test_discovery_update_light(hass, mqtt_mock, caplog):
|
||||
"""Test update of discovered light."""
|
||||
data1 = (
|
||||
|
|
|
@ -240,98 +240,6 @@ async def test_custom_availability_payload(hass, mqtt_mock):
|
|||
)
|
||||
|
||||
|
||||
async def test_setting_sensor_attribute_via_legacy_mqtt_json_message(hass, mqtt_mock):
|
||||
"""Test the setting of attribute via MQTT with JSON payload."""
|
||||
assert await async_setup_component(
|
||||
hass,
|
||||
sensor.DOMAIN,
|
||||
{
|
||||
sensor.DOMAIN: {
|
||||
"platform": "mqtt",
|
||||
"name": "test",
|
||||
"state_topic": "test-topic",
|
||||
"unit_of_measurement": "fav unit",
|
||||
"json_attributes_topic": "test-attributes-topic",
|
||||
}
|
||||
},
|
||||
)
|
||||
|
||||
async_fire_mqtt_message(hass, "test-attributes-topic", '{ "val": "100" }')
|
||||
state = hass.states.get("sensor.test")
|
||||
|
||||
assert state.attributes.get("val") == "100"
|
||||
|
||||
|
||||
async def test_update_with_legacy_json_attrs_not_dict(hass, mqtt_mock, caplog):
|
||||
"""Test attributes get extracted from a JSON result."""
|
||||
assert await async_setup_component(
|
||||
hass,
|
||||
sensor.DOMAIN,
|
||||
{
|
||||
sensor.DOMAIN: {
|
||||
"platform": "mqtt",
|
||||
"name": "test",
|
||||
"state_topic": "test-topic",
|
||||
"unit_of_measurement": "fav unit",
|
||||
"json_attributes_topic": "test-attributes-topic",
|
||||
}
|
||||
},
|
||||
)
|
||||
|
||||
async_fire_mqtt_message(hass, "test-attributes-topic", '[ "list", "of", "things"]')
|
||||
state = hass.states.get("sensor.test")
|
||||
|
||||
assert state.attributes.get("val") is None
|
||||
assert "JSON result was not a dictionary" in caplog.text
|
||||
|
||||
|
||||
async def test_update_with_legacy_json_attrs_bad_JSON(hass, mqtt_mock, caplog):
|
||||
"""Test attributes get extracted from a JSON result."""
|
||||
assert await async_setup_component(
|
||||
hass,
|
||||
sensor.DOMAIN,
|
||||
{
|
||||
sensor.DOMAIN: {
|
||||
"platform": "mqtt",
|
||||
"name": "test",
|
||||
"state_topic": "test-topic",
|
||||
"unit_of_measurement": "fav unit",
|
||||
"json_attributes_topic": "test-attributes-topic",
|
||||
}
|
||||
},
|
||||
)
|
||||
|
||||
async_fire_mqtt_message(hass, "test-attributes-topic", "This is not JSON")
|
||||
|
||||
state = hass.states.get("sensor.test")
|
||||
assert state.attributes.get("val") is None
|
||||
assert "Erroneous JSON: This is not JSON" in caplog.text
|
||||
|
||||
|
||||
async def test_update_with_legacy_json_attrs_and_template(hass, mqtt_mock):
|
||||
"""Test attributes get extracted from a JSON result."""
|
||||
assert await async_setup_component(
|
||||
hass,
|
||||
sensor.DOMAIN,
|
||||
{
|
||||
sensor.DOMAIN: {
|
||||
"platform": "mqtt",
|
||||
"name": "test",
|
||||
"state_topic": "test-topic",
|
||||
"unit_of_measurement": "fav unit",
|
||||
"value_template": "{{ value_json.val }}",
|
||||
"json_attributes": "val",
|
||||
}
|
||||
},
|
||||
)
|
||||
|
||||
async_fire_mqtt_message(hass, "test-topic", '{ "val": "100" }')
|
||||
state = hass.states.get("sensor.test")
|
||||
|
||||
assert state.attributes.get("val") == "100"
|
||||
assert state.state == "100"
|
||||
|
||||
|
||||
async def test_invalid_device_class(hass, mqtt_mock):
|
||||
"""Test device_class option with invalid value."""
|
||||
assert await async_setup_component(
|
||||
|
|
Loading…
Reference in New Issue