diff --git a/homeassistant/components/mqtt/discovery.py b/homeassistant/components/mqtt/discovery.py index e6350179571..ac20ba7a4a8 100644 --- a/homeassistant/components/mqtt/discovery.py +++ b/homeassistant/components/mqtt/discovery.py @@ -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]: diff --git a/homeassistant/components/mqtt/sensor.py b/homeassistant/components/mqtt/sensor.py index 07910697d21..7be923927ca 100644 --- a/homeassistant/components/mqtt/sensor.py +++ b/homeassistant/components/mqtt/sensor.py @@ -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.""" diff --git a/tests/components/mqtt/test_discovery.py b/tests/components/mqtt/test_discovery.py index 4a28b95e32c..8c925bdf315 100644 --- a/tests/components/mqtt/test_discovery.py +++ b/tests/components/mqtt/test_discovery.py @@ -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() diff --git a/tests/components/mqtt/test_light_json.py b/tests/components/mqtt/test_light_json.py index 6a8bf10dc3d..c07cec47ecc 100644 --- a/tests/components/mqtt/test_light_json.py +++ b/tests/components/mqtt/test_light_json.py @@ -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 = ( diff --git a/tests/components/mqtt/test_light_template.py b/tests/components/mqtt/test_light_template.py index f3965479c14..4f89ca77847 100644 --- a/tests/components/mqtt/test_light_template.py +++ b/tests/components/mqtt/test_light_template.py @@ -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 = ( diff --git a/tests/components/mqtt/test_sensor.py b/tests/components/mqtt/test_sensor.py index 5e472efcc89..0455c5f9c7c 100644 --- a/tests/components/mqtt/test_sensor.py +++ b/tests/components/mqtt/test_sensor.py @@ -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(