Improve MQTT test coverage and remove dead code (#33584)
* Improve MQTT tests and remove dead code * Remove useless test. * Add more test
This commit is contained in:
parent
a813847f6e
commit
4e6fd19624
12 changed files with 761 additions and 125 deletions
|
@ -31,7 +31,6 @@ from homeassistant.const import (
|
||||||
STATE_UNKNOWN,
|
STATE_UNKNOWN,
|
||||||
)
|
)
|
||||||
from homeassistant.core import callback
|
from homeassistant.core import callback
|
||||||
from homeassistant.exceptions import TemplateError
|
|
||||||
import homeassistant.helpers.config_validation as cv
|
import homeassistant.helpers.config_validation as cv
|
||||||
from homeassistant.helpers.dispatcher import async_dispatcher_connect
|
from homeassistant.helpers.dispatcher import async_dispatcher_connect
|
||||||
from homeassistant.helpers.typing import ConfigType, HomeAssistantType
|
from homeassistant.helpers.typing import ConfigType, HomeAssistantType
|
||||||
|
@ -531,9 +530,6 @@ class MqttCover(
|
||||||
|
|
||||||
async def async_set_cover_tilt_position(self, **kwargs):
|
async def async_set_cover_tilt_position(self, **kwargs):
|
||||||
"""Move the cover tilt to a specific position."""
|
"""Move the cover tilt to a specific position."""
|
||||||
if ATTR_TILT_POSITION not in kwargs:
|
|
||||||
return
|
|
||||||
|
|
||||||
position = float(kwargs[ATTR_TILT_POSITION])
|
position = float(kwargs[ATTR_TILT_POSITION])
|
||||||
|
|
||||||
# The position needs to be between min and max
|
# The position needs to be between min and max
|
||||||
|
@ -550,36 +546,31 @@ class MqttCover(
|
||||||
async def async_set_cover_position(self, **kwargs):
|
async def async_set_cover_position(self, **kwargs):
|
||||||
"""Move the cover to a specific position."""
|
"""Move the cover to a specific position."""
|
||||||
set_position_template = self._config.get(CONF_SET_POSITION_TEMPLATE)
|
set_position_template = self._config.get(CONF_SET_POSITION_TEMPLATE)
|
||||||
if ATTR_POSITION in kwargs:
|
position = kwargs[ATTR_POSITION]
|
||||||
position = kwargs[ATTR_POSITION]
|
percentage_position = position
|
||||||
percentage_position = position
|
if set_position_template is not None:
|
||||||
if set_position_template is not None:
|
position = set_position_template.async_render(**kwargs)
|
||||||
try:
|
elif (
|
||||||
position = set_position_template.async_render(**kwargs)
|
self._config[CONF_POSITION_OPEN] != 100
|
||||||
except TemplateError as ex:
|
and self._config[CONF_POSITION_CLOSED] != 0
|
||||||
_LOGGER.error(ex)
|
):
|
||||||
self._state = None
|
position = self.find_in_range_from_percent(position, COVER_PAYLOAD)
|
||||||
elif (
|
|
||||||
self._config[CONF_POSITION_OPEN] != 100
|
|
||||||
and self._config[CONF_POSITION_CLOSED] != 0
|
|
||||||
):
|
|
||||||
position = self.find_in_range_from_percent(position, COVER_PAYLOAD)
|
|
||||||
|
|
||||||
mqtt.async_publish(
|
mqtt.async_publish(
|
||||||
self.hass,
|
self.hass,
|
||||||
self._config.get(CONF_SET_POSITION_TOPIC),
|
self._config.get(CONF_SET_POSITION_TOPIC),
|
||||||
position,
|
position,
|
||||||
self._config[CONF_QOS],
|
self._config[CONF_QOS],
|
||||||
self._config[CONF_RETAIN],
|
self._config[CONF_RETAIN],
|
||||||
|
)
|
||||||
|
if self._optimistic:
|
||||||
|
self._state = (
|
||||||
|
STATE_CLOSED
|
||||||
|
if percentage_position == self._config[CONF_POSITION_CLOSED]
|
||||||
|
else STATE_OPEN
|
||||||
)
|
)
|
||||||
if self._optimistic:
|
self._position = percentage_position
|
||||||
self._state = (
|
self.async_write_ha_state()
|
||||||
STATE_CLOSED
|
|
||||||
if percentage_position == self._config[CONF_POSITION_CLOSED]
|
|
||||||
else STATE_OPEN
|
|
||||||
)
|
|
||||||
self._position = percentage_position
|
|
||||||
self.async_write_ha_state()
|
|
||||||
|
|
||||||
async def async_toggle_tilt(self, **kwargs):
|
async def async_toggle_tilt(self, **kwargs):
|
||||||
"""Toggle the entity."""
|
"""Toggle the entity."""
|
||||||
|
|
|
@ -6,7 +6,6 @@ import re
|
||||||
|
|
||||||
from homeassistant.components import mqtt
|
from homeassistant.components import mqtt
|
||||||
from homeassistant.const import CONF_DEVICE, CONF_PLATFORM
|
from homeassistant.const import CONF_DEVICE, CONF_PLATFORM
|
||||||
from homeassistant.helpers.discovery import async_load_platform
|
|
||||||
from homeassistant.helpers.dispatcher import async_dispatcher_send
|
from homeassistant.helpers.dispatcher import async_dispatcher_send
|
||||||
from homeassistant.helpers.typing import HomeAssistantType
|
from homeassistant.helpers.typing import HomeAssistantType
|
||||||
|
|
||||||
|
@ -35,21 +34,6 @@ SUPPORTED_COMPONENTS = [
|
||||||
"vacuum",
|
"vacuum",
|
||||||
]
|
]
|
||||||
|
|
||||||
CONFIG_ENTRY_COMPONENTS = [
|
|
||||||
"alarm_control_panel",
|
|
||||||
"binary_sensor",
|
|
||||||
"camera",
|
|
||||||
"climate",
|
|
||||||
"cover",
|
|
||||||
"device_automation",
|
|
||||||
"fan",
|
|
||||||
"light",
|
|
||||||
"lock",
|
|
||||||
"sensor",
|
|
||||||
"switch",
|
|
||||||
"vacuum",
|
|
||||||
]
|
|
||||||
|
|
||||||
ALREADY_DISCOVERED = "mqtt_discovered_components"
|
ALREADY_DISCOVERED = "mqtt_discovered_components"
|
||||||
DATA_CONFIG_ENTRY_LOCK = "mqtt_config_entry_lock"
|
DATA_CONFIG_ENTRY_LOCK = "mqtt_config_entry_lock"
|
||||||
CONFIG_ENTRY_IS_SETUP = "mqtt_config_entry_is_setup"
|
CONFIG_ENTRY_IS_SETUP = "mqtt_config_entry_is_setup"
|
||||||
|
@ -159,10 +143,6 @@ async def async_start(
|
||||||
_LOGGER.info("Found new component: %s %s", component, discovery_id)
|
_LOGGER.info("Found new component: %s %s", component, discovery_id)
|
||||||
hass.data[ALREADY_DISCOVERED][discovery_hash] = None
|
hass.data[ALREADY_DISCOVERED][discovery_hash] = None
|
||||||
|
|
||||||
if component not in CONFIG_ENTRY_COMPONENTS:
|
|
||||||
await async_load_platform(hass, component, "mqtt", payload, hass_config)
|
|
||||||
return
|
|
||||||
|
|
||||||
config_entries_key = f"{component}.mqtt"
|
config_entries_key = f"{component}.mqtt"
|
||||||
async with hass.data[DATA_CONFIG_ENTRY_LOCK]:
|
async with hass.data[DATA_CONFIG_ENTRY_LOCK]:
|
||||||
if config_entries_key not in hass.data[CONFIG_ENTRY_IS_SETUP]:
|
if config_entries_key not in hass.data[CONFIG_ENTRY_IS_SETUP]:
|
||||||
|
|
|
@ -401,9 +401,6 @@ class MqttFan(
|
||||||
|
|
||||||
This method is a coroutine.
|
This method is a coroutine.
|
||||||
"""
|
"""
|
||||||
if self._topic[CONF_SPEED_COMMAND_TOPIC] is None:
|
|
||||||
return
|
|
||||||
|
|
||||||
if speed == SPEED_LOW:
|
if speed == SPEED_LOW:
|
||||||
mqtt_payload = self._payload["SPEED_LOW"]
|
mqtt_payload = self._payload["SPEED_LOW"]
|
||||||
elif speed == SPEED_MEDIUM:
|
elif speed == SPEED_MEDIUM:
|
||||||
|
@ -432,9 +429,6 @@ class MqttFan(
|
||||||
|
|
||||||
This method is a coroutine.
|
This method is a coroutine.
|
||||||
"""
|
"""
|
||||||
if self._topic[CONF_OSCILLATION_COMMAND_TOPIC] is None:
|
|
||||||
return
|
|
||||||
|
|
||||||
if oscillating is False:
|
if oscillating is False:
|
||||||
payload = self._payload["OSCILLATE_OFF_PAYLOAD"]
|
payload = self._payload["OSCILLATE_OFF_PAYLOAD"]
|
||||||
else:
|
else:
|
||||||
|
|
|
@ -410,24 +410,26 @@ class MqttVacuum(
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def fan_speed_list(self):
|
def fan_speed_list(self):
|
||||||
"""Return the status of the vacuum."""
|
"""Return the status of the vacuum.
|
||||||
if self.supported_features & SUPPORT_FAN_SPEED == 0:
|
|
||||||
return []
|
No need to check SUPPORT_FAN_SPEED, this won't be called if fan_speed is None.
|
||||||
|
"""
|
||||||
return self._fan_speed_list
|
return self._fan_speed_list
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def battery_level(self):
|
def battery_level(self):
|
||||||
"""Return the status of the vacuum."""
|
"""Return the status of the vacuum."""
|
||||||
if self.supported_features & SUPPORT_BATTERY == 0:
|
if self.supported_features & SUPPORT_BATTERY == 0:
|
||||||
return
|
return None
|
||||||
|
|
||||||
return max(0, min(100, self._battery_level))
|
return max(0, min(100, self._battery_level))
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def battery_icon(self):
|
def battery_icon(self):
|
||||||
"""Return the battery icon for the vacuum cleaner."""
|
"""Return the battery icon for the vacuum cleaner.
|
||||||
if self.supported_features & SUPPORT_BATTERY == 0:
|
|
||||||
return
|
No need to check SUPPORT_BATTERY, this won't be called if battery_level is None.
|
||||||
|
"""
|
||||||
|
|
||||||
return icon_for_battery_level(
|
return icon_for_battery_level(
|
||||||
battery_level=self.battery_level, charging=self._charging
|
battery_level=self.battery_level, charging=self._charging
|
||||||
|
|
|
@ -282,9 +282,10 @@ class MqttStateVacuum(
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def fan_speed_list(self):
|
def fan_speed_list(self):
|
||||||
"""Return fan speed list of the vacuum."""
|
"""Return fan speed list of the vacuum.
|
||||||
if self.supported_features & SUPPORT_FAN_SPEED == 0:
|
|
||||||
return None
|
No need to check SUPPORT_FAN_SPEED, this won't be called if fan_speed is None.
|
||||||
|
"""
|
||||||
return self._fan_speed_list
|
return self._fan_speed_list
|
||||||
|
|
||||||
@property
|
@property
|
||||||
|
|
|
@ -42,7 +42,8 @@ from tests.common import (
|
||||||
)
|
)
|
||||||
from tests.components.alarm_control_panel import common
|
from tests.components.alarm_control_panel import common
|
||||||
|
|
||||||
CODE = "HELLO_CODE"
|
CODE_NUMBER = "1234"
|
||||||
|
CODE_TEXT = "HELLO_CODE"
|
||||||
|
|
||||||
DEFAULT_CONFIG = {
|
DEFAULT_CONFIG = {
|
||||||
alarm_control_panel.DOMAIN: {
|
alarm_control_panel.DOMAIN: {
|
||||||
|
@ -341,6 +342,34 @@ async def test_update_state_via_state_topic_template(hass, mqtt_mock):
|
||||||
assert state.state == STATE_ALARM_ARMED_AWAY
|
assert state.state == STATE_ALARM_ARMED_AWAY
|
||||||
|
|
||||||
|
|
||||||
|
async def test_attributes_code_number(hass, mqtt_mock):
|
||||||
|
"""Test attributes which are not supported by the vacuum."""
|
||||||
|
config = copy.deepcopy(DEFAULT_CONFIG)
|
||||||
|
config[alarm_control_panel.DOMAIN]["code"] = CODE_NUMBER
|
||||||
|
|
||||||
|
assert await async_setup_component(hass, alarm_control_panel.DOMAIN, config)
|
||||||
|
|
||||||
|
state = hass.states.get("alarm_control_panel.test")
|
||||||
|
assert (
|
||||||
|
state.attributes.get(alarm_control_panel.ATTR_CODE_FORMAT)
|
||||||
|
== alarm_control_panel.FORMAT_NUMBER
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
async def test_attributes_code_text(hass, mqtt_mock):
|
||||||
|
"""Test attributes which are not supported by the vacuum."""
|
||||||
|
config = copy.deepcopy(DEFAULT_CONFIG)
|
||||||
|
config[alarm_control_panel.DOMAIN]["code"] = CODE_TEXT
|
||||||
|
|
||||||
|
assert await async_setup_component(hass, alarm_control_panel.DOMAIN, config)
|
||||||
|
|
||||||
|
state = hass.states.get("alarm_control_panel.test")
|
||||||
|
assert (
|
||||||
|
state.attributes.get(alarm_control_panel.ATTR_CODE_FORMAT)
|
||||||
|
== alarm_control_panel.FORMAT_TEXT
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
async def test_availability_without_topic(hass, mqtt_mock):
|
async def test_availability_without_topic(hass, mqtt_mock):
|
||||||
"""Test availability without defined availability topic."""
|
"""Test availability without defined availability topic."""
|
||||||
await help_test_availability_without_topic(
|
await help_test_availability_without_topic(
|
||||||
|
|
|
@ -534,6 +534,22 @@ async def test_set_hold(hass, mqtt_mock):
|
||||||
assert state.attributes.get("preset_mode") is None
|
assert state.attributes.get("preset_mode") is None
|
||||||
|
|
||||||
|
|
||||||
|
async def test_set_preset_mode_twice(hass, mqtt_mock):
|
||||||
|
"""Test setting of the same mode twice only publishes once."""
|
||||||
|
assert await async_setup_component(hass, CLIMATE_DOMAIN, DEFAULT_CONFIG)
|
||||||
|
|
||||||
|
state = hass.states.get(ENTITY_CLIMATE)
|
||||||
|
assert state.attributes.get("preset_mode") is None
|
||||||
|
await common.async_set_preset_mode(hass, "hold-on", ENTITY_CLIMATE)
|
||||||
|
mqtt_mock.async_publish.assert_called_once_with("hold-topic", "hold-on", 0, False)
|
||||||
|
mqtt_mock.async_publish.reset_mock()
|
||||||
|
state = hass.states.get(ENTITY_CLIMATE)
|
||||||
|
assert state.attributes.get("preset_mode") == "hold-on"
|
||||||
|
|
||||||
|
await common.async_set_preset_mode(hass, "hold-on", ENTITY_CLIMATE)
|
||||||
|
mqtt_mock.async_publish.assert_not_called()
|
||||||
|
|
||||||
|
|
||||||
async def test_set_aux_pessimistic(hass, mqtt_mock):
|
async def test_set_aux_pessimistic(hass, mqtt_mock):
|
||||||
"""Test setting of the aux heating in pessimistic mode."""
|
"""Test setting of the aux heating in pessimistic mode."""
|
||||||
config = copy.deepcopy(DEFAULT_CONFIG)
|
config = copy.deepcopy(DEFAULT_CONFIG)
|
||||||
|
|
|
@ -1,6 +1,11 @@
|
||||||
"""The tests for the MQTT cover platform."""
|
"""The tests for the MQTT cover platform."""
|
||||||
from homeassistant.components import cover
|
from homeassistant.components import cover
|
||||||
from homeassistant.components.cover import ATTR_POSITION, ATTR_TILT_POSITION
|
from homeassistant.components.cover import (
|
||||||
|
ATTR_CURRENT_POSITION,
|
||||||
|
ATTR_CURRENT_TILT_POSITION,
|
||||||
|
ATTR_POSITION,
|
||||||
|
ATTR_TILT_POSITION,
|
||||||
|
)
|
||||||
from homeassistant.components.mqtt.cover import MqttCover
|
from homeassistant.components.mqtt.cover import MqttCover
|
||||||
from homeassistant.const import (
|
from homeassistant.const import (
|
||||||
ATTR_ASSUMED_STATE,
|
ATTR_ASSUMED_STATE,
|
||||||
|
@ -335,6 +340,68 @@ async def test_optimistic_state_change(hass, mqtt_mock):
|
||||||
assert state.state == STATE_CLOSED
|
assert state.state == STATE_CLOSED
|
||||||
|
|
||||||
|
|
||||||
|
async def test_optimistic_state_change_with_position(hass, mqtt_mock):
|
||||||
|
"""Test changing state optimistically."""
|
||||||
|
assert await async_setup_component(
|
||||||
|
hass,
|
||||||
|
cover.DOMAIN,
|
||||||
|
{
|
||||||
|
cover.DOMAIN: {
|
||||||
|
"platform": "mqtt",
|
||||||
|
"name": "test",
|
||||||
|
"optimistic": True,
|
||||||
|
"command_topic": "command-topic",
|
||||||
|
"position_topic": "position-topic",
|
||||||
|
"qos": 0,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
state = hass.states.get("cover.test")
|
||||||
|
assert state.state == STATE_UNKNOWN
|
||||||
|
assert state.attributes.get(ATTR_ASSUMED_STATE)
|
||||||
|
assert state.attributes.get(ATTR_CURRENT_POSITION) is None
|
||||||
|
|
||||||
|
await hass.services.async_call(
|
||||||
|
cover.DOMAIN, SERVICE_OPEN_COVER, {ATTR_ENTITY_ID: "cover.test"}, blocking=True
|
||||||
|
)
|
||||||
|
|
||||||
|
mqtt_mock.async_publish.assert_called_once_with("command-topic", "OPEN", 0, False)
|
||||||
|
mqtt_mock.async_publish.reset_mock()
|
||||||
|
state = hass.states.get("cover.test")
|
||||||
|
assert state.state == STATE_OPEN
|
||||||
|
assert state.attributes.get(ATTR_CURRENT_POSITION) == 100
|
||||||
|
|
||||||
|
await hass.services.async_call(
|
||||||
|
cover.DOMAIN, SERVICE_CLOSE_COVER, {ATTR_ENTITY_ID: "cover.test"}, blocking=True
|
||||||
|
)
|
||||||
|
|
||||||
|
mqtt_mock.async_publish.assert_called_once_with("command-topic", "CLOSE", 0, False)
|
||||||
|
mqtt_mock.async_publish.reset_mock()
|
||||||
|
state = hass.states.get("cover.test")
|
||||||
|
assert STATE_CLOSED == state.state
|
||||||
|
assert state.attributes.get(ATTR_CURRENT_POSITION) == 0
|
||||||
|
|
||||||
|
await hass.services.async_call(
|
||||||
|
cover.DOMAIN, SERVICE_TOGGLE, {ATTR_ENTITY_ID: "cover.test"}, blocking=True
|
||||||
|
)
|
||||||
|
|
||||||
|
mqtt_mock.async_publish.assert_called_once_with("command-topic", "OPEN", 0, False)
|
||||||
|
mqtt_mock.async_publish.reset_mock()
|
||||||
|
state = hass.states.get("cover.test")
|
||||||
|
assert STATE_OPEN == state.state
|
||||||
|
assert state.attributes.get(ATTR_CURRENT_POSITION) == 100
|
||||||
|
|
||||||
|
await hass.services.async_call(
|
||||||
|
cover.DOMAIN, SERVICE_TOGGLE, {ATTR_ENTITY_ID: "cover.test"}, blocking=True
|
||||||
|
)
|
||||||
|
|
||||||
|
mqtt_mock.async_publish.assert_called_once_with("command-topic", "CLOSE", 0, False)
|
||||||
|
state = hass.states.get("cover.test")
|
||||||
|
assert state.state == STATE_CLOSED
|
||||||
|
assert state.attributes.get(ATTR_CURRENT_POSITION) == 0
|
||||||
|
|
||||||
|
|
||||||
async def test_send_open_cover_command(hass, mqtt_mock):
|
async def test_send_open_cover_command(hass, mqtt_mock):
|
||||||
"""Test the sending of open_cover."""
|
"""Test the sending of open_cover."""
|
||||||
assert await async_setup_component(
|
assert await async_setup_component(
|
||||||
|
@ -440,31 +507,31 @@ async def test_current_cover_position(hass, mqtt_mock):
|
||||||
)
|
)
|
||||||
|
|
||||||
state_attributes_dict = hass.states.get("cover.test").attributes
|
state_attributes_dict = hass.states.get("cover.test").attributes
|
||||||
assert not ("current_position" in state_attributes_dict)
|
assert not (ATTR_CURRENT_POSITION in state_attributes_dict)
|
||||||
assert not ("current_tilt_position" in state_attributes_dict)
|
assert not (ATTR_CURRENT_TILT_POSITION in state_attributes_dict)
|
||||||
assert not (4 & hass.states.get("cover.test").attributes["supported_features"] == 4)
|
assert not (4 & hass.states.get("cover.test").attributes["supported_features"] == 4)
|
||||||
|
|
||||||
async_fire_mqtt_message(hass, "get-position-topic", "0")
|
async_fire_mqtt_message(hass, "get-position-topic", "0")
|
||||||
current_cover_position = hass.states.get("cover.test").attributes[
|
current_cover_position = hass.states.get("cover.test").attributes[
|
||||||
"current_position"
|
ATTR_CURRENT_POSITION
|
||||||
]
|
]
|
||||||
assert current_cover_position == 0
|
assert current_cover_position == 0
|
||||||
|
|
||||||
async_fire_mqtt_message(hass, "get-position-topic", "50")
|
async_fire_mqtt_message(hass, "get-position-topic", "50")
|
||||||
current_cover_position = hass.states.get("cover.test").attributes[
|
current_cover_position = hass.states.get("cover.test").attributes[
|
||||||
"current_position"
|
ATTR_CURRENT_POSITION
|
||||||
]
|
]
|
||||||
assert current_cover_position == 50
|
assert current_cover_position == 50
|
||||||
|
|
||||||
async_fire_mqtt_message(hass, "get-position-topic", "non-numeric")
|
async_fire_mqtt_message(hass, "get-position-topic", "non-numeric")
|
||||||
current_cover_position = hass.states.get("cover.test").attributes[
|
current_cover_position = hass.states.get("cover.test").attributes[
|
||||||
"current_position"
|
ATTR_CURRENT_POSITION
|
||||||
]
|
]
|
||||||
assert current_cover_position == 50
|
assert current_cover_position == 50
|
||||||
|
|
||||||
async_fire_mqtt_message(hass, "get-position-topic", "101")
|
async_fire_mqtt_message(hass, "get-position-topic", "101")
|
||||||
current_cover_position = hass.states.get("cover.test").attributes[
|
current_cover_position = hass.states.get("cover.test").attributes[
|
||||||
"current_position"
|
ATTR_CURRENT_POSITION
|
||||||
]
|
]
|
||||||
assert current_cover_position == 100
|
assert current_cover_position == 100
|
||||||
|
|
||||||
|
@ -490,48 +557,67 @@ async def test_current_cover_position_inverted(hass, mqtt_mock):
|
||||||
)
|
)
|
||||||
|
|
||||||
state_attributes_dict = hass.states.get("cover.test").attributes
|
state_attributes_dict = hass.states.get("cover.test").attributes
|
||||||
assert not ("current_position" in state_attributes_dict)
|
assert not (ATTR_CURRENT_POSITION in state_attributes_dict)
|
||||||
assert not ("current_tilt_position" in state_attributes_dict)
|
assert not (ATTR_CURRENT_TILT_POSITION in state_attributes_dict)
|
||||||
assert not (4 & hass.states.get("cover.test").attributes["supported_features"] == 4)
|
assert not (4 & hass.states.get("cover.test").attributes["supported_features"] == 4)
|
||||||
|
|
||||||
async_fire_mqtt_message(hass, "get-position-topic", "100")
|
async_fire_mqtt_message(hass, "get-position-topic", "100")
|
||||||
current_percentage_cover_position = hass.states.get("cover.test").attributes[
|
current_percentage_cover_position = hass.states.get("cover.test").attributes[
|
||||||
"current_position"
|
ATTR_CURRENT_POSITION
|
||||||
]
|
]
|
||||||
assert current_percentage_cover_position == 0
|
assert current_percentage_cover_position == 0
|
||||||
assert hass.states.get("cover.test").state == STATE_CLOSED
|
assert hass.states.get("cover.test").state == STATE_CLOSED
|
||||||
|
|
||||||
async_fire_mqtt_message(hass, "get-position-topic", "0")
|
async_fire_mqtt_message(hass, "get-position-topic", "0")
|
||||||
current_percentage_cover_position = hass.states.get("cover.test").attributes[
|
current_percentage_cover_position = hass.states.get("cover.test").attributes[
|
||||||
"current_position"
|
ATTR_CURRENT_POSITION
|
||||||
]
|
]
|
||||||
assert current_percentage_cover_position == 100
|
assert current_percentage_cover_position == 100
|
||||||
assert hass.states.get("cover.test").state == STATE_OPEN
|
assert hass.states.get("cover.test").state == STATE_OPEN
|
||||||
|
|
||||||
async_fire_mqtt_message(hass, "get-position-topic", "50")
|
async_fire_mqtt_message(hass, "get-position-topic", "50")
|
||||||
current_percentage_cover_position = hass.states.get("cover.test").attributes[
|
current_percentage_cover_position = hass.states.get("cover.test").attributes[
|
||||||
"current_position"
|
ATTR_CURRENT_POSITION
|
||||||
]
|
]
|
||||||
assert current_percentage_cover_position == 50
|
assert current_percentage_cover_position == 50
|
||||||
assert hass.states.get("cover.test").state == STATE_OPEN
|
assert hass.states.get("cover.test").state == STATE_OPEN
|
||||||
|
|
||||||
async_fire_mqtt_message(hass, "get-position-topic", "non-numeric")
|
async_fire_mqtt_message(hass, "get-position-topic", "non-numeric")
|
||||||
current_percentage_cover_position = hass.states.get("cover.test").attributes[
|
current_percentage_cover_position = hass.states.get("cover.test").attributes[
|
||||||
"current_position"
|
ATTR_CURRENT_POSITION
|
||||||
]
|
]
|
||||||
assert current_percentage_cover_position == 50
|
assert current_percentage_cover_position == 50
|
||||||
assert hass.states.get("cover.test").state == STATE_OPEN
|
assert hass.states.get("cover.test").state == STATE_OPEN
|
||||||
|
|
||||||
async_fire_mqtt_message(hass, "get-position-topic", "101")
|
async_fire_mqtt_message(hass, "get-position-topic", "101")
|
||||||
current_percentage_cover_position = hass.states.get("cover.test").attributes[
|
current_percentage_cover_position = hass.states.get("cover.test").attributes[
|
||||||
"current_position"
|
ATTR_CURRENT_POSITION
|
||||||
]
|
]
|
||||||
assert current_percentage_cover_position == 0
|
assert current_percentage_cover_position == 0
|
||||||
assert hass.states.get("cover.test").state == STATE_CLOSED
|
assert hass.states.get("cover.test").state == STATE_CLOSED
|
||||||
|
|
||||||
|
|
||||||
async def test_set_cover_position(hass, mqtt_mock):
|
async def test_optimistic_position(hass, mqtt_mock):
|
||||||
"""Test setting cover position."""
|
"""Test optimistic position is not supported."""
|
||||||
|
assert await async_setup_component(
|
||||||
|
hass,
|
||||||
|
cover.DOMAIN,
|
||||||
|
{
|
||||||
|
cover.DOMAIN: {
|
||||||
|
"platform": "mqtt",
|
||||||
|
"name": "test",
|
||||||
|
"command_topic": "command-topic",
|
||||||
|
"set_position_topic": "set-position-topic",
|
||||||
|
}
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
state = hass.states.get("cover.test")
|
||||||
|
assert state is None
|
||||||
|
|
||||||
|
|
||||||
|
async def test_position_update(hass, mqtt_mock):
|
||||||
|
"""Test cover position update from received MQTT message."""
|
||||||
assert await async_setup_component(
|
assert await async_setup_component(
|
||||||
hass,
|
hass,
|
||||||
cover.DOMAIN,
|
cover.DOMAIN,
|
||||||
|
@ -552,16 +638,16 @@ async def test_set_cover_position(hass, mqtt_mock):
|
||||||
)
|
)
|
||||||
|
|
||||||
state_attributes_dict = hass.states.get("cover.test").attributes
|
state_attributes_dict = hass.states.get("cover.test").attributes
|
||||||
assert not ("current_position" in state_attributes_dict)
|
assert not (ATTR_CURRENT_POSITION in state_attributes_dict)
|
||||||
assert not ("current_tilt_position" in state_attributes_dict)
|
assert not (ATTR_CURRENT_TILT_POSITION in state_attributes_dict)
|
||||||
assert 4 & hass.states.get("cover.test").attributes["supported_features"] == 4
|
assert 4 & hass.states.get("cover.test").attributes["supported_features"] == 4
|
||||||
|
|
||||||
async_fire_mqtt_message(hass, "get-position-topic", "22")
|
async_fire_mqtt_message(hass, "get-position-topic", "22")
|
||||||
state_attributes_dict = hass.states.get("cover.test").attributes
|
state_attributes_dict = hass.states.get("cover.test").attributes
|
||||||
assert "current_position" in state_attributes_dict
|
assert ATTR_CURRENT_POSITION in state_attributes_dict
|
||||||
assert not ("current_tilt_position" in state_attributes_dict)
|
assert not (ATTR_CURRENT_TILT_POSITION in state_attributes_dict)
|
||||||
current_cover_position = hass.states.get("cover.test").attributes[
|
current_cover_position = hass.states.get("cover.test").attributes[
|
||||||
"current_position"
|
ATTR_CURRENT_POSITION
|
||||||
]
|
]
|
||||||
assert current_cover_position == 22
|
assert current_cover_position == 22
|
||||||
|
|
||||||
|
@ -629,6 +715,37 @@ async def test_set_position_untemplated(hass, mqtt_mock):
|
||||||
mqtt_mock.async_publish.assert_called_once_with("position-topic", 62, 0, False)
|
mqtt_mock.async_publish.assert_called_once_with("position-topic", 62, 0, False)
|
||||||
|
|
||||||
|
|
||||||
|
async def test_set_position_untemplated_custom_percentage_range(hass, mqtt_mock):
|
||||||
|
"""Test setting cover position via template."""
|
||||||
|
assert await async_setup_component(
|
||||||
|
hass,
|
||||||
|
cover.DOMAIN,
|
||||||
|
{
|
||||||
|
cover.DOMAIN: {
|
||||||
|
"platform": "mqtt",
|
||||||
|
"name": "test",
|
||||||
|
"position_topic": "state-topic",
|
||||||
|
"command_topic": "command-topic",
|
||||||
|
"set_position_topic": "position-topic",
|
||||||
|
"position_open": 0,
|
||||||
|
"position_closed": 100,
|
||||||
|
"payload_open": "OPEN",
|
||||||
|
"payload_close": "CLOSE",
|
||||||
|
"payload_stop": "STOP",
|
||||||
|
}
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
await hass.services.async_call(
|
||||||
|
cover.DOMAIN,
|
||||||
|
SERVICE_SET_COVER_POSITION,
|
||||||
|
{ATTR_ENTITY_ID: "cover.test", ATTR_POSITION: 38},
|
||||||
|
blocking=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
mqtt_mock.async_publish.assert_called_once_with("position-topic", 62, 0, False)
|
||||||
|
|
||||||
|
|
||||||
async def test_no_command_topic(hass, mqtt_mock):
|
async def test_no_command_topic(hass, mqtt_mock):
|
||||||
"""Test with no command topic."""
|
"""Test with no command topic."""
|
||||||
assert await async_setup_component(
|
assert await async_setup_component(
|
||||||
|
@ -717,10 +834,10 @@ async def test_tilt_defaults(hass, mqtt_mock):
|
||||||
)
|
)
|
||||||
|
|
||||||
state_attributes_dict = hass.states.get("cover.test").attributes
|
state_attributes_dict = hass.states.get("cover.test").attributes
|
||||||
assert "current_tilt_position" in state_attributes_dict
|
assert ATTR_CURRENT_TILT_POSITION in state_attributes_dict
|
||||||
|
|
||||||
current_cover_position = hass.states.get("cover.test").attributes[
|
current_cover_position = hass.states.get("cover.test").attributes[
|
||||||
"current_tilt_position"
|
ATTR_CURRENT_TILT_POSITION
|
||||||
]
|
]
|
||||||
assert current_cover_position == STATE_UNKNOWN
|
assert current_cover_position == STATE_UNKNOWN
|
||||||
|
|
||||||
|
@ -770,7 +887,7 @@ async def test_tilt_via_invocation_defaults(hass, mqtt_mock):
|
||||||
async_fire_mqtt_message(hass, "tilt-status-topic", "0")
|
async_fire_mqtt_message(hass, "tilt-status-topic", "0")
|
||||||
|
|
||||||
current_cover_tilt_position = hass.states.get("cover.test").attributes[
|
current_cover_tilt_position = hass.states.get("cover.test").attributes[
|
||||||
"current_tilt_position"
|
ATTR_CURRENT_TILT_POSITION
|
||||||
]
|
]
|
||||||
assert current_cover_tilt_position == 0
|
assert current_cover_tilt_position == 0
|
||||||
|
|
||||||
|
@ -788,7 +905,7 @@ async def test_tilt_via_invocation_defaults(hass, mqtt_mock):
|
||||||
async_fire_mqtt_message(hass, "tilt-status-topic", "100")
|
async_fire_mqtt_message(hass, "tilt-status-topic", "100")
|
||||||
|
|
||||||
current_cover_tilt_position = hass.states.get("cover.test").attributes[
|
current_cover_tilt_position = hass.states.get("cover.test").attributes[
|
||||||
"current_tilt_position"
|
ATTR_CURRENT_TILT_POSITION
|
||||||
]
|
]
|
||||||
assert current_cover_tilt_position == 100
|
assert current_cover_tilt_position == 100
|
||||||
|
|
||||||
|
@ -849,7 +966,7 @@ async def test_tilt_given_value(hass, mqtt_mock):
|
||||||
async_fire_mqtt_message(hass, "tilt-status-topic", "25")
|
async_fire_mqtt_message(hass, "tilt-status-topic", "25")
|
||||||
|
|
||||||
current_cover_tilt_position = hass.states.get("cover.test").attributes[
|
current_cover_tilt_position = hass.states.get("cover.test").attributes[
|
||||||
"current_tilt_position"
|
ATTR_CURRENT_TILT_POSITION
|
||||||
]
|
]
|
||||||
assert current_cover_tilt_position == 25
|
assert current_cover_tilt_position == 25
|
||||||
|
|
||||||
|
@ -867,7 +984,7 @@ async def test_tilt_given_value(hass, mqtt_mock):
|
||||||
async_fire_mqtt_message(hass, "tilt-status-topic", "80")
|
async_fire_mqtt_message(hass, "tilt-status-topic", "80")
|
||||||
|
|
||||||
current_cover_tilt_position = hass.states.get("cover.test").attributes[
|
current_cover_tilt_position = hass.states.get("cover.test").attributes[
|
||||||
"current_tilt_position"
|
ATTR_CURRENT_TILT_POSITION
|
||||||
]
|
]
|
||||||
assert current_cover_tilt_position == 80
|
assert current_cover_tilt_position == 80
|
||||||
|
|
||||||
|
@ -913,7 +1030,7 @@ async def test_tilt_given_value_optimistic(hass, mqtt_mock):
|
||||||
)
|
)
|
||||||
|
|
||||||
current_cover_tilt_position = hass.states.get("cover.test").attributes[
|
current_cover_tilt_position = hass.states.get("cover.test").attributes[
|
||||||
"current_tilt_position"
|
ATTR_CURRENT_TILT_POSITION
|
||||||
]
|
]
|
||||||
assert current_cover_tilt_position == 80
|
assert current_cover_tilt_position == 80
|
||||||
|
|
||||||
|
@ -928,7 +1045,7 @@ async def test_tilt_given_value_optimistic(hass, mqtt_mock):
|
||||||
)
|
)
|
||||||
|
|
||||||
current_cover_tilt_position = hass.states.get("cover.test").attributes[
|
current_cover_tilt_position = hass.states.get("cover.test").attributes[
|
||||||
"current_tilt_position"
|
ATTR_CURRENT_TILT_POSITION
|
||||||
]
|
]
|
||||||
assert current_cover_tilt_position == 25
|
assert current_cover_tilt_position == 25
|
||||||
|
|
||||||
|
@ -969,7 +1086,7 @@ async def test_tilt_given_value_altered_range(hass, mqtt_mock):
|
||||||
)
|
)
|
||||||
|
|
||||||
current_cover_tilt_position = hass.states.get("cover.test").attributes[
|
current_cover_tilt_position = hass.states.get("cover.test").attributes[
|
||||||
"current_tilt_position"
|
ATTR_CURRENT_TILT_POSITION
|
||||||
]
|
]
|
||||||
assert current_cover_tilt_position == 50
|
assert current_cover_tilt_position == 50
|
||||||
|
|
||||||
|
@ -984,7 +1101,7 @@ async def test_tilt_given_value_altered_range(hass, mqtt_mock):
|
||||||
)
|
)
|
||||||
|
|
||||||
current_cover_tilt_position = hass.states.get("cover.test").attributes[
|
current_cover_tilt_position = hass.states.get("cover.test").attributes[
|
||||||
"current_tilt_position"
|
ATTR_CURRENT_TILT_POSITION
|
||||||
]
|
]
|
||||||
assert current_cover_tilt_position == 0
|
assert current_cover_tilt_position == 0
|
||||||
|
|
||||||
|
@ -999,7 +1116,7 @@ async def test_tilt_given_value_altered_range(hass, mqtt_mock):
|
||||||
)
|
)
|
||||||
|
|
||||||
current_cover_tilt_position = hass.states.get("cover.test").attributes[
|
current_cover_tilt_position = hass.states.get("cover.test").attributes[
|
||||||
"current_tilt_position"
|
ATTR_CURRENT_TILT_POSITION
|
||||||
]
|
]
|
||||||
assert current_cover_tilt_position == 50
|
assert current_cover_tilt_position == 50
|
||||||
|
|
||||||
|
@ -1030,14 +1147,14 @@ async def test_tilt_via_topic(hass, mqtt_mock):
|
||||||
async_fire_mqtt_message(hass, "tilt-status-topic", "0")
|
async_fire_mqtt_message(hass, "tilt-status-topic", "0")
|
||||||
|
|
||||||
current_cover_tilt_position = hass.states.get("cover.test").attributes[
|
current_cover_tilt_position = hass.states.get("cover.test").attributes[
|
||||||
"current_tilt_position"
|
ATTR_CURRENT_TILT_POSITION
|
||||||
]
|
]
|
||||||
assert current_cover_tilt_position == 0
|
assert current_cover_tilt_position == 0
|
||||||
|
|
||||||
async_fire_mqtt_message(hass, "tilt-status-topic", "50")
|
async_fire_mqtt_message(hass, "tilt-status-topic", "50")
|
||||||
|
|
||||||
current_cover_tilt_position = hass.states.get("cover.test").attributes[
|
current_cover_tilt_position = hass.states.get("cover.test").attributes[
|
||||||
"current_tilt_position"
|
ATTR_CURRENT_TILT_POSITION
|
||||||
]
|
]
|
||||||
assert current_cover_tilt_position == 50
|
assert current_cover_tilt_position == 50
|
||||||
|
|
||||||
|
@ -1069,14 +1186,14 @@ async def test_tilt_via_topic_template(hass, mqtt_mock):
|
||||||
async_fire_mqtt_message(hass, "tilt-status-topic", "99")
|
async_fire_mqtt_message(hass, "tilt-status-topic", "99")
|
||||||
|
|
||||||
current_cover_tilt_position = hass.states.get("cover.test").attributes[
|
current_cover_tilt_position = hass.states.get("cover.test").attributes[
|
||||||
"current_tilt_position"
|
ATTR_CURRENT_TILT_POSITION
|
||||||
]
|
]
|
||||||
assert current_cover_tilt_position == 0
|
assert current_cover_tilt_position == 0
|
||||||
|
|
||||||
async_fire_mqtt_message(hass, "tilt-status-topic", "5000")
|
async_fire_mqtt_message(hass, "tilt-status-topic", "5000")
|
||||||
|
|
||||||
current_cover_tilt_position = hass.states.get("cover.test").attributes[
|
current_cover_tilt_position = hass.states.get("cover.test").attributes[
|
||||||
"current_tilt_position"
|
ATTR_CURRENT_TILT_POSITION
|
||||||
]
|
]
|
||||||
assert current_cover_tilt_position == 50
|
assert current_cover_tilt_position == 50
|
||||||
|
|
||||||
|
@ -1107,21 +1224,21 @@ async def test_tilt_via_topic_altered_range(hass, mqtt_mock):
|
||||||
async_fire_mqtt_message(hass, "tilt-status-topic", "0")
|
async_fire_mqtt_message(hass, "tilt-status-topic", "0")
|
||||||
|
|
||||||
current_cover_tilt_position = hass.states.get("cover.test").attributes[
|
current_cover_tilt_position = hass.states.get("cover.test").attributes[
|
||||||
"current_tilt_position"
|
ATTR_CURRENT_TILT_POSITION
|
||||||
]
|
]
|
||||||
assert current_cover_tilt_position == 0
|
assert current_cover_tilt_position == 0
|
||||||
|
|
||||||
async_fire_mqtt_message(hass, "tilt-status-topic", "50")
|
async_fire_mqtt_message(hass, "tilt-status-topic", "50")
|
||||||
|
|
||||||
current_cover_tilt_position = hass.states.get("cover.test").attributes[
|
current_cover_tilt_position = hass.states.get("cover.test").attributes[
|
||||||
"current_tilt_position"
|
ATTR_CURRENT_TILT_POSITION
|
||||||
]
|
]
|
||||||
assert current_cover_tilt_position == 100
|
assert current_cover_tilt_position == 100
|
||||||
|
|
||||||
async_fire_mqtt_message(hass, "tilt-status-topic", "25")
|
async_fire_mqtt_message(hass, "tilt-status-topic", "25")
|
||||||
|
|
||||||
current_cover_tilt_position = hass.states.get("cover.test").attributes[
|
current_cover_tilt_position = hass.states.get("cover.test").attributes[
|
||||||
"current_tilt_position"
|
ATTR_CURRENT_TILT_POSITION
|
||||||
]
|
]
|
||||||
assert current_cover_tilt_position == 50
|
assert current_cover_tilt_position == 50
|
||||||
|
|
||||||
|
@ -1155,21 +1272,21 @@ async def test_tilt_via_topic_template_altered_range(hass, mqtt_mock):
|
||||||
async_fire_mqtt_message(hass, "tilt-status-topic", "99")
|
async_fire_mqtt_message(hass, "tilt-status-topic", "99")
|
||||||
|
|
||||||
current_cover_tilt_position = hass.states.get("cover.test").attributes[
|
current_cover_tilt_position = hass.states.get("cover.test").attributes[
|
||||||
"current_tilt_position"
|
ATTR_CURRENT_TILT_POSITION
|
||||||
]
|
]
|
||||||
assert current_cover_tilt_position == 0
|
assert current_cover_tilt_position == 0
|
||||||
|
|
||||||
async_fire_mqtt_message(hass, "tilt-status-topic", "5000")
|
async_fire_mqtt_message(hass, "tilt-status-topic", "5000")
|
||||||
|
|
||||||
current_cover_tilt_position = hass.states.get("cover.test").attributes[
|
current_cover_tilt_position = hass.states.get("cover.test").attributes[
|
||||||
"current_tilt_position"
|
ATTR_CURRENT_TILT_POSITION
|
||||||
]
|
]
|
||||||
assert current_cover_tilt_position == 100
|
assert current_cover_tilt_position == 100
|
||||||
|
|
||||||
async_fire_mqtt_message(hass, "tilt-status-topic", "2500")
|
async_fire_mqtt_message(hass, "tilt-status-topic", "2500")
|
||||||
|
|
||||||
current_cover_tilt_position = hass.states.get("cover.test").attributes[
|
current_cover_tilt_position = hass.states.get("cover.test").attributes[
|
||||||
"current_tilt_position"
|
ATTR_CURRENT_TILT_POSITION
|
||||||
]
|
]
|
||||||
assert current_cover_tilt_position == 50
|
assert current_cover_tilt_position == 50
|
||||||
|
|
||||||
|
|
|
@ -51,32 +51,32 @@ async def test_subscribing_config_topic(hass, mqtt_mock):
|
||||||
async def test_invalid_topic(hass, mqtt_mock):
|
async def test_invalid_topic(hass, mqtt_mock):
|
||||||
"""Test sending to invalid topic."""
|
"""Test sending to invalid topic."""
|
||||||
with patch(
|
with patch(
|
||||||
"homeassistant.components.mqtt.discovery.async_load_platform"
|
"homeassistant.components.mqtt.discovery.async_dispatcher_send"
|
||||||
) as mock_load_platform:
|
) as mock_dispatcher_send:
|
||||||
entry = MockConfigEntry(
|
entry = MockConfigEntry(
|
||||||
domain=mqtt.DOMAIN, data={mqtt.CONF_BROKER: "test-broker"}
|
domain=mqtt.DOMAIN, data={mqtt.CONF_BROKER: "test-broker"}
|
||||||
)
|
)
|
||||||
|
|
||||||
mock_load_platform.return_value = mock_coro()
|
mock_dispatcher_send.return_value = mock_coro()
|
||||||
await async_start(hass, "homeassistant", {}, entry)
|
await async_start(hass, "homeassistant", {}, entry)
|
||||||
|
|
||||||
async_fire_mqtt_message(
|
async_fire_mqtt_message(
|
||||||
hass, "homeassistant/binary_sensor/bla/not_config", "{}"
|
hass, "homeassistant/binary_sensor/bla/not_config", "{}"
|
||||||
)
|
)
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
assert not mock_load_platform.called
|
assert not mock_dispatcher_send.called
|
||||||
|
|
||||||
|
|
||||||
async def test_invalid_json(hass, mqtt_mock, caplog):
|
async def test_invalid_json(hass, mqtt_mock, caplog):
|
||||||
"""Test sending in invalid JSON."""
|
"""Test sending in invalid JSON."""
|
||||||
with patch(
|
with patch(
|
||||||
"homeassistant.components.mqtt.discovery.async_load_platform"
|
"homeassistant.components.mqtt.discovery.async_dispatcher_send"
|
||||||
) as mock_load_platform:
|
) as mock_dispatcher_send:
|
||||||
entry = MockConfigEntry(
|
entry = MockConfigEntry(
|
||||||
domain=mqtt.DOMAIN, data={mqtt.CONF_BROKER: "test-broker"}
|
domain=mqtt.DOMAIN, data={mqtt.CONF_BROKER: "test-broker"}
|
||||||
)
|
)
|
||||||
|
|
||||||
mock_load_platform.return_value = mock_coro()
|
mock_dispatcher_send.return_value = mock_coro()
|
||||||
await async_start(hass, "homeassistant", {}, entry)
|
await async_start(hass, "homeassistant", {}, entry)
|
||||||
|
|
||||||
async_fire_mqtt_message(
|
async_fire_mqtt_message(
|
||||||
|
@ -84,19 +84,19 @@ async def test_invalid_json(hass, mqtt_mock, caplog):
|
||||||
)
|
)
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
assert "Unable to parse JSON" in caplog.text
|
assert "Unable to parse JSON" in caplog.text
|
||||||
assert not mock_load_platform.called
|
assert not mock_dispatcher_send.called
|
||||||
|
|
||||||
|
|
||||||
async def test_only_valid_components(hass, mqtt_mock, caplog):
|
async def test_only_valid_components(hass, mqtt_mock, caplog):
|
||||||
"""Test for a valid component."""
|
"""Test for a valid component."""
|
||||||
with patch(
|
with patch(
|
||||||
"homeassistant.components.mqtt.discovery.async_load_platform"
|
"homeassistant.components.mqtt.discovery.async_dispatcher_send"
|
||||||
) as mock_load_platform:
|
) as mock_dispatcher_send:
|
||||||
entry = MockConfigEntry(domain=mqtt.DOMAIN)
|
entry = MockConfigEntry(domain=mqtt.DOMAIN)
|
||||||
|
|
||||||
invalid_component = "timer"
|
invalid_component = "timer"
|
||||||
|
|
||||||
mock_load_platform.return_value = mock_coro()
|
mock_dispatcher_send.return_value = mock_coro()
|
||||||
await async_start(hass, "homeassistant", {}, entry)
|
await async_start(hass, "homeassistant", {}, entry)
|
||||||
|
|
||||||
async_fire_mqtt_message(
|
async_fire_mqtt_message(
|
||||||
|
@ -107,7 +107,7 @@ async def test_only_valid_components(hass, mqtt_mock, caplog):
|
||||||
|
|
||||||
assert "Integration {} is not supported".format(invalid_component) in caplog.text
|
assert "Integration {} is not supported".format(invalid_component) in caplog.text
|
||||||
|
|
||||||
assert not mock_load_platform.called
|
assert not mock_dispatcher_send.called
|
||||||
|
|
||||||
|
|
||||||
async def test_correct_config_discovery(hass, mqtt_mock, caplog):
|
async def test_correct_config_discovery(hass, mqtt_mock, caplog):
|
||||||
|
|
|
@ -1,6 +1,11 @@
|
||||||
"""Test MQTT fans."""
|
"""Test MQTT fans."""
|
||||||
from homeassistant.components import fan
|
from homeassistant.components import fan
|
||||||
from homeassistant.const import ATTR_ASSUMED_STATE, STATE_OFF, STATE_ON
|
from homeassistant.const import (
|
||||||
|
ATTR_ASSUMED_STATE,
|
||||||
|
ATTR_SUPPORTED_FEATURES,
|
||||||
|
STATE_OFF,
|
||||||
|
STATE_ON,
|
||||||
|
)
|
||||||
from homeassistant.setup import async_setup_component
|
from homeassistant.setup import async_setup_component
|
||||||
|
|
||||||
from .test_common import (
|
from .test_common import (
|
||||||
|
@ -278,6 +283,54 @@ async def test_sending_mqtt_commands_and_optimistic(hass, mqtt_mock):
|
||||||
assert state.attributes.get(ATTR_ASSUMED_STATE)
|
assert state.attributes.get(ATTR_ASSUMED_STATE)
|
||||||
|
|
||||||
|
|
||||||
|
async def test_on_sending_mqtt_commands_and_optimistic(hass, mqtt_mock):
|
||||||
|
"""Test on with speed."""
|
||||||
|
assert await async_setup_component(
|
||||||
|
hass,
|
||||||
|
fan.DOMAIN,
|
||||||
|
{
|
||||||
|
fan.DOMAIN: {
|
||||||
|
"platform": "mqtt",
|
||||||
|
"name": "test",
|
||||||
|
"command_topic": "command-topic",
|
||||||
|
"oscillation_command_topic": "oscillation-command-topic",
|
||||||
|
"speed_command_topic": "speed-command-topic",
|
||||||
|
}
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
state = hass.states.get("fan.test")
|
||||||
|
assert state.state is STATE_OFF
|
||||||
|
assert state.attributes.get(ATTR_ASSUMED_STATE)
|
||||||
|
|
||||||
|
await common.async_turn_on(hass, "fan.test")
|
||||||
|
mqtt_mock.async_publish.assert_called_once_with("command-topic", "ON", 0, False)
|
||||||
|
mqtt_mock.async_publish.reset_mock()
|
||||||
|
state = hass.states.get("fan.test")
|
||||||
|
assert state.state is STATE_ON
|
||||||
|
assert state.attributes.get(ATTR_ASSUMED_STATE)
|
||||||
|
assert state.attributes.get(fan.ATTR_SPEED) is None
|
||||||
|
assert state.attributes.get(fan.ATTR_OSCILLATING) is None
|
||||||
|
|
||||||
|
await common.async_turn_off(hass, "fan.test")
|
||||||
|
mqtt_mock.async_publish.assert_called_once_with("command-topic", "OFF", 0, False)
|
||||||
|
mqtt_mock.async_publish.reset_mock()
|
||||||
|
state = hass.states.get("fan.test")
|
||||||
|
assert state.state is STATE_OFF
|
||||||
|
assert state.attributes.get(ATTR_ASSUMED_STATE)
|
||||||
|
|
||||||
|
await common.async_turn_on(hass, "fan.test", speed="low")
|
||||||
|
assert mqtt_mock.async_publish.call_count == 2
|
||||||
|
mqtt_mock.async_publish.assert_any_call("command-topic", "ON", 0, False)
|
||||||
|
mqtt_mock.async_publish.assert_any_call("speed-command-topic", "low", 0, False)
|
||||||
|
mqtt_mock.async_publish.reset_mock()
|
||||||
|
state = hass.states.get("fan.test")
|
||||||
|
assert state.state is STATE_ON
|
||||||
|
assert state.attributes.get(ATTR_ASSUMED_STATE)
|
||||||
|
assert state.attributes.get(fan.ATTR_SPEED) == "low"
|
||||||
|
assert state.attributes.get(fan.ATTR_OSCILLATING) is None
|
||||||
|
|
||||||
|
|
||||||
async def test_sending_mqtt_commands_and_explicit_optimistic(hass, mqtt_mock):
|
async def test_sending_mqtt_commands_and_explicit_optimistic(hass, mqtt_mock):
|
||||||
"""Test optimistic mode with state topic."""
|
"""Test optimistic mode with state topic."""
|
||||||
assert await async_setup_component(
|
assert await async_setup_component(
|
||||||
|
@ -370,6 +423,171 @@ async def test_sending_mqtt_commands_and_explicit_optimistic(hass, mqtt_mock):
|
||||||
assert state.state is STATE_OFF
|
assert state.state is STATE_OFF
|
||||||
assert state.attributes.get(ATTR_ASSUMED_STATE)
|
assert state.attributes.get(ATTR_ASSUMED_STATE)
|
||||||
|
|
||||||
|
await common.async_set_speed(hass, "fan.test", "cUsToM")
|
||||||
|
mqtt_mock.async_publish.assert_called_once_with(
|
||||||
|
"speed-command-topic", "cUsToM", 0, False
|
||||||
|
)
|
||||||
|
mqtt_mock.async_publish.reset_mock()
|
||||||
|
state = hass.states.get("fan.test")
|
||||||
|
assert state.state is STATE_OFF
|
||||||
|
assert state.attributes.get(ATTR_ASSUMED_STATE)
|
||||||
|
|
||||||
|
|
||||||
|
async def test_attributes(hass, mqtt_mock):
|
||||||
|
"""Test attributes."""
|
||||||
|
assert await async_setup_component(
|
||||||
|
hass,
|
||||||
|
fan.DOMAIN,
|
||||||
|
{
|
||||||
|
fan.DOMAIN: {
|
||||||
|
"platform": "mqtt",
|
||||||
|
"name": "test",
|
||||||
|
"command_topic": "command-topic",
|
||||||
|
"oscillation_command_topic": "oscillation-command-topic",
|
||||||
|
"speed_command_topic": "speed-command-topic",
|
||||||
|
}
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
state = hass.states.get("fan.test")
|
||||||
|
assert state.state is STATE_OFF
|
||||||
|
assert state.attributes.get(fan.ATTR_SPEED_LIST) == ["off", "low", "medium", "high"]
|
||||||
|
|
||||||
|
await common.async_turn_on(hass, "fan.test")
|
||||||
|
state = hass.states.get("fan.test")
|
||||||
|
assert state.state is STATE_ON
|
||||||
|
assert state.attributes.get(ATTR_ASSUMED_STATE)
|
||||||
|
assert state.attributes.get(fan.ATTR_SPEED) is None
|
||||||
|
assert state.attributes.get(fan.ATTR_OSCILLATING) is None
|
||||||
|
|
||||||
|
await common.async_turn_off(hass, "fan.test")
|
||||||
|
state = hass.states.get("fan.test")
|
||||||
|
assert state.state is STATE_OFF
|
||||||
|
assert state.attributes.get(ATTR_ASSUMED_STATE)
|
||||||
|
assert state.attributes.get(fan.ATTR_SPEED) is None
|
||||||
|
assert state.attributes.get(fan.ATTR_OSCILLATING) is None
|
||||||
|
|
||||||
|
await common.async_oscillate(hass, "fan.test", True)
|
||||||
|
state = hass.states.get("fan.test")
|
||||||
|
assert state.state is STATE_OFF
|
||||||
|
assert state.attributes.get(ATTR_ASSUMED_STATE)
|
||||||
|
assert state.attributes.get(fan.ATTR_SPEED) is None
|
||||||
|
assert state.attributes.get(fan.ATTR_OSCILLATING) is True
|
||||||
|
|
||||||
|
await common.async_oscillate(hass, "fan.test", False)
|
||||||
|
state = hass.states.get("fan.test")
|
||||||
|
assert state.state is STATE_OFF
|
||||||
|
assert state.attributes.get(ATTR_ASSUMED_STATE)
|
||||||
|
assert state.attributes.get(fan.ATTR_SPEED) is None
|
||||||
|
assert state.attributes.get(fan.ATTR_OSCILLATING) is False
|
||||||
|
|
||||||
|
await common.async_set_speed(hass, "fan.test", fan.SPEED_LOW)
|
||||||
|
state = hass.states.get("fan.test")
|
||||||
|
assert state.state is STATE_OFF
|
||||||
|
assert state.attributes.get(ATTR_ASSUMED_STATE)
|
||||||
|
assert state.attributes.get(fan.ATTR_SPEED) == "low"
|
||||||
|
assert state.attributes.get(fan.ATTR_OSCILLATING) is False
|
||||||
|
|
||||||
|
await common.async_set_speed(hass, "fan.test", fan.SPEED_MEDIUM)
|
||||||
|
state = hass.states.get("fan.test")
|
||||||
|
assert state.state is STATE_OFF
|
||||||
|
assert state.attributes.get(ATTR_ASSUMED_STATE)
|
||||||
|
assert state.attributes.get(fan.ATTR_SPEED) == "medium"
|
||||||
|
assert state.attributes.get(fan.ATTR_OSCILLATING) is False
|
||||||
|
|
||||||
|
await common.async_set_speed(hass, "fan.test", fan.SPEED_HIGH)
|
||||||
|
state = hass.states.get("fan.test")
|
||||||
|
assert state.state is STATE_OFF
|
||||||
|
assert state.attributes.get(ATTR_ASSUMED_STATE)
|
||||||
|
assert state.attributes.get(fan.ATTR_SPEED) == "high"
|
||||||
|
assert state.attributes.get(fan.ATTR_OSCILLATING) is False
|
||||||
|
|
||||||
|
await common.async_set_speed(hass, "fan.test", fan.SPEED_OFF)
|
||||||
|
state = hass.states.get("fan.test")
|
||||||
|
assert state.state is STATE_OFF
|
||||||
|
assert state.attributes.get(ATTR_ASSUMED_STATE)
|
||||||
|
assert state.attributes.get(fan.ATTR_SPEED) == "off"
|
||||||
|
assert state.attributes.get(fan.ATTR_OSCILLATING) is False
|
||||||
|
|
||||||
|
await common.async_set_speed(hass, "fan.test", "cUsToM")
|
||||||
|
state = hass.states.get("fan.test")
|
||||||
|
assert state.state is STATE_OFF
|
||||||
|
assert state.attributes.get(ATTR_ASSUMED_STATE)
|
||||||
|
assert state.attributes.get(fan.ATTR_SPEED) == "cUsToM"
|
||||||
|
assert state.attributes.get(fan.ATTR_OSCILLATING) is False
|
||||||
|
|
||||||
|
|
||||||
|
async def test_custom_speed_list(hass, mqtt_mock):
|
||||||
|
"""Test optimistic mode without state topic."""
|
||||||
|
assert await async_setup_component(
|
||||||
|
hass,
|
||||||
|
fan.DOMAIN,
|
||||||
|
{
|
||||||
|
fan.DOMAIN: {
|
||||||
|
"platform": "mqtt",
|
||||||
|
"name": "test",
|
||||||
|
"command_topic": "command-topic",
|
||||||
|
"oscillation_command_topic": "oscillation-command-topic",
|
||||||
|
"oscillation_state_topic": "oscillation-state-topic",
|
||||||
|
"speed_command_topic": "speed-command-topic",
|
||||||
|
"speed_state_topic": "speed-state-topic",
|
||||||
|
"speeds": ["off", "high"],
|
||||||
|
}
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
state = hass.states.get("fan.test")
|
||||||
|
assert state.state is STATE_OFF
|
||||||
|
assert state.attributes.get(fan.ATTR_SPEED_LIST) == ["off", "high"]
|
||||||
|
|
||||||
|
|
||||||
|
async def test_supported_features(hass, mqtt_mock):
|
||||||
|
"""Test optimistic mode without state topic."""
|
||||||
|
assert await async_setup_component(
|
||||||
|
hass,
|
||||||
|
fan.DOMAIN,
|
||||||
|
{
|
||||||
|
fan.DOMAIN: [
|
||||||
|
{
|
||||||
|
"platform": "mqtt",
|
||||||
|
"name": "test1",
|
||||||
|
"command_topic": "command-topic",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"platform": "mqtt",
|
||||||
|
"name": "test2",
|
||||||
|
"command_topic": "command-topic",
|
||||||
|
"oscillation_command_topic": "oscillation-command-topic",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"platform": "mqtt",
|
||||||
|
"name": "test3",
|
||||||
|
"command_topic": "command-topic",
|
||||||
|
"speed_command_topic": "speed-command-topic",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"platform": "mqtt",
|
||||||
|
"name": "test4",
|
||||||
|
"command_topic": "command-topic",
|
||||||
|
"oscillation_command_topic": "oscillation-command-topic",
|
||||||
|
"speed_command_topic": "speed-command-topic",
|
||||||
|
},
|
||||||
|
]
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
state = hass.states.get("fan.test1")
|
||||||
|
assert state.attributes.get(ATTR_SUPPORTED_FEATURES) == 0
|
||||||
|
state = hass.states.get("fan.test2")
|
||||||
|
assert state.attributes.get(ATTR_SUPPORTED_FEATURES) == fan.SUPPORT_OSCILLATE
|
||||||
|
state = hass.states.get("fan.test3")
|
||||||
|
assert state.attributes.get(ATTR_SUPPORTED_FEATURES) == fan.SUPPORT_SET_SPEED
|
||||||
|
state = hass.states.get("fan.test4")
|
||||||
|
assert (
|
||||||
|
state.attributes.get(ATTR_SUPPORTED_FEATURES)
|
||||||
|
== fan.SUPPORT_OSCILLATE | fan.SUPPORT_SET_SPEED
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
async def test_availability_without_topic(hass, mqtt_mock):
|
async def test_availability_without_topic(hass, mqtt_mock):
|
||||||
"""Test availability without defined availability topic."""
|
"""Test availability without defined availability topic."""
|
||||||
|
|
|
@ -9,6 +9,7 @@ import pytest
|
||||||
import voluptuous as vol
|
import voluptuous as vol
|
||||||
|
|
||||||
from homeassistant.components import mqtt, websocket_api
|
from homeassistant.components import mqtt, websocket_api
|
||||||
|
from homeassistant.components.mqtt import debug_info
|
||||||
from homeassistant.components.mqtt.discovery import async_start
|
from homeassistant.components.mqtt.discovery import async_start
|
||||||
from homeassistant.const import (
|
from homeassistant.const import (
|
||||||
ATTR_DOMAIN,
|
ATTR_DOMAIN,
|
||||||
|
@ -36,6 +37,7 @@ from tests.common import (
|
||||||
mock_storage,
|
mock_storage,
|
||||||
threadsafe_coroutine_factory,
|
threadsafe_coroutine_factory,
|
||||||
)
|
)
|
||||||
|
from tests.testing_config.custom_components.test.sensor import DEVICE_CLASSES
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
|
@ -363,6 +365,56 @@ class TestMQTTCallbacks(unittest.TestCase):
|
||||||
self.hass.block_till_done()
|
self.hass.block_till_done()
|
||||||
assert len(self.calls) == 1
|
assert len(self.calls) == 1
|
||||||
|
|
||||||
|
def test_subscribe_deprecated(self):
|
||||||
|
"""Test the subscription of a topic using deprecated callback signature."""
|
||||||
|
calls = []
|
||||||
|
|
||||||
|
@callback
|
||||||
|
def record_calls(topic, payload, qos):
|
||||||
|
"""Record calls."""
|
||||||
|
calls.append((topic, payload, qos))
|
||||||
|
|
||||||
|
unsub = mqtt.subscribe(self.hass, "test-topic", record_calls)
|
||||||
|
|
||||||
|
fire_mqtt_message(self.hass, "test-topic", "test-payload")
|
||||||
|
|
||||||
|
self.hass.block_till_done()
|
||||||
|
assert len(calls) == 1
|
||||||
|
assert calls[0][0] == "test-topic"
|
||||||
|
assert calls[0][1] == "test-payload"
|
||||||
|
|
||||||
|
unsub()
|
||||||
|
|
||||||
|
fire_mqtt_message(self.hass, "test-topic", "test-payload")
|
||||||
|
|
||||||
|
self.hass.block_till_done()
|
||||||
|
assert len(calls) == 1
|
||||||
|
|
||||||
|
def test_subscribe_deprecated_async(self):
|
||||||
|
"""Test the subscription of a topic using deprecated callback signature."""
|
||||||
|
calls = []
|
||||||
|
|
||||||
|
@callback
|
||||||
|
async def record_calls(topic, payload, qos):
|
||||||
|
"""Record calls."""
|
||||||
|
calls.append((topic, payload, qos))
|
||||||
|
|
||||||
|
unsub = mqtt.subscribe(self.hass, "test-topic", record_calls)
|
||||||
|
|
||||||
|
fire_mqtt_message(self.hass, "test-topic", "test-payload")
|
||||||
|
|
||||||
|
self.hass.block_till_done()
|
||||||
|
assert len(calls) == 1
|
||||||
|
assert calls[0][0] == "test-topic"
|
||||||
|
assert calls[0][1] == "test-payload"
|
||||||
|
|
||||||
|
unsub()
|
||||||
|
|
||||||
|
fire_mqtt_message(self.hass, "test-topic", "test-payload")
|
||||||
|
|
||||||
|
self.hass.block_till_done()
|
||||||
|
assert len(calls) == 1
|
||||||
|
|
||||||
def test_subscribe_topic_not_match(self):
|
def test_subscribe_topic_not_match(self):
|
||||||
"""Test if subscribed topic is not a match."""
|
"""Test if subscribed topic is not a match."""
|
||||||
mqtt.subscribe(self.hass, "test-topic", self.record_calls)
|
mqtt.subscribe(self.hass, "test-topic", self.record_calls)
|
||||||
|
@ -988,3 +1040,198 @@ async def test_mqtt_ws_get_device_debug_info(
|
||||||
"triggers": [],
|
"triggers": [],
|
||||||
}
|
}
|
||||||
assert response["result"] == expected_result
|
assert response["result"] == expected_result
|
||||||
|
|
||||||
|
|
||||||
|
async def test_debug_info_multiple_devices(hass, mqtt_mock):
|
||||||
|
"""Test we get correct debug_info when multiple devices are present."""
|
||||||
|
devices = [
|
||||||
|
{
|
||||||
|
"domain": "sensor",
|
||||||
|
"config": {
|
||||||
|
"device": {"identifiers": ["0AFFD0"]},
|
||||||
|
"platform": "mqtt",
|
||||||
|
"state_topic": "test-topic-sensor",
|
||||||
|
"unique_id": "unique",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"domain": "binary_sensor",
|
||||||
|
"config": {
|
||||||
|
"device": {"identifiers": ["0AFFD1"]},
|
||||||
|
"platform": "mqtt",
|
||||||
|
"state_topic": "test-topic-binary-sensor",
|
||||||
|
"unique_id": "unique",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"domain": "device_automation",
|
||||||
|
"config": {
|
||||||
|
"automation_type": "trigger",
|
||||||
|
"device": {"identifiers": ["0AFFD2"]},
|
||||||
|
"platform": "mqtt",
|
||||||
|
"topic": "test-topic1",
|
||||||
|
"type": "foo",
|
||||||
|
"subtype": "bar",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"domain": "device_automation",
|
||||||
|
"config": {
|
||||||
|
"automation_type": "trigger",
|
||||||
|
"device": {"identifiers": ["0AFFD3"]},
|
||||||
|
"platform": "mqtt",
|
||||||
|
"topic": "test-topic2",
|
||||||
|
"type": "ikk",
|
||||||
|
"subtype": "baz",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
entry = MockConfigEntry(domain=mqtt.DOMAIN)
|
||||||
|
entry.add_to_hass(hass)
|
||||||
|
await async_start(hass, "homeassistant", {}, entry)
|
||||||
|
registry = await hass.helpers.device_registry.async_get_registry()
|
||||||
|
|
||||||
|
for d in devices:
|
||||||
|
data = json.dumps(d["config"])
|
||||||
|
domain = d["domain"]
|
||||||
|
id = d["config"]["device"]["identifiers"][0]
|
||||||
|
async_fire_mqtt_message(hass, f"homeassistant/{domain}/{id}/config", data)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
for d in devices:
|
||||||
|
domain = d["domain"]
|
||||||
|
id = d["config"]["device"]["identifiers"][0]
|
||||||
|
device = registry.async_get_device({("mqtt", id)}, set())
|
||||||
|
assert device is not None
|
||||||
|
|
||||||
|
debug_info_data = await debug_info.info_for_device(hass, device.id)
|
||||||
|
if d["domain"] != "device_automation":
|
||||||
|
assert len(debug_info_data["entities"]) == 1
|
||||||
|
assert len(debug_info_data["triggers"]) == 0
|
||||||
|
discovery_data = debug_info_data["entities"][0]["discovery_data"]
|
||||||
|
assert len(debug_info_data["entities"][0]["topics"]) == 1
|
||||||
|
topic = d["config"]["state_topic"]
|
||||||
|
assert {"topic": topic, "messages": []} in debug_info_data["entities"][0][
|
||||||
|
"topics"
|
||||||
|
]
|
||||||
|
else:
|
||||||
|
assert len(debug_info_data["entities"]) == 0
|
||||||
|
assert len(debug_info_data["triggers"]) == 1
|
||||||
|
discovery_data = debug_info_data["triggers"][0]["discovery_data"]
|
||||||
|
|
||||||
|
assert discovery_data["topic"] == f"homeassistant/{domain}/{id}/config"
|
||||||
|
assert discovery_data["payload"] == d["config"]
|
||||||
|
|
||||||
|
|
||||||
|
async def test_debug_info_multiple_entities_triggers(hass, mqtt_mock):
|
||||||
|
"""Test we get correct debug_info for a device with multiple entities and triggers."""
|
||||||
|
config = [
|
||||||
|
{
|
||||||
|
"domain": "sensor",
|
||||||
|
"config": {
|
||||||
|
"device": {"identifiers": ["0AFFD0"]},
|
||||||
|
"platform": "mqtt",
|
||||||
|
"state_topic": "test-topic-sensor",
|
||||||
|
"unique_id": "unique",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"domain": "binary_sensor",
|
||||||
|
"config": {
|
||||||
|
"device": {"identifiers": ["0AFFD0"]},
|
||||||
|
"platform": "mqtt",
|
||||||
|
"state_topic": "test-topic-binary-sensor",
|
||||||
|
"unique_id": "unique",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"domain": "device_automation",
|
||||||
|
"config": {
|
||||||
|
"automation_type": "trigger",
|
||||||
|
"device": {"identifiers": ["0AFFD0"]},
|
||||||
|
"platform": "mqtt",
|
||||||
|
"topic": "test-topic1",
|
||||||
|
"type": "foo",
|
||||||
|
"subtype": "bar",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"domain": "device_automation",
|
||||||
|
"config": {
|
||||||
|
"automation_type": "trigger",
|
||||||
|
"device": {"identifiers": ["0AFFD0"]},
|
||||||
|
"platform": "mqtt",
|
||||||
|
"topic": "test-topic2",
|
||||||
|
"type": "ikk",
|
||||||
|
"subtype": "baz",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
entry = MockConfigEntry(domain=mqtt.DOMAIN)
|
||||||
|
entry.add_to_hass(hass)
|
||||||
|
await async_start(hass, "homeassistant", {}, entry)
|
||||||
|
registry = await hass.helpers.device_registry.async_get_registry()
|
||||||
|
|
||||||
|
for c in config:
|
||||||
|
data = json.dumps(c["config"])
|
||||||
|
domain = c["domain"]
|
||||||
|
# Use topic as discovery_id
|
||||||
|
id = c["config"].get("topic", c["config"].get("state_topic"))
|
||||||
|
async_fire_mqtt_message(hass, f"homeassistant/{domain}/{id}/config", data)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
device_id = config[0]["config"]["device"]["identifiers"][0]
|
||||||
|
device = registry.async_get_device({("mqtt", device_id)}, set())
|
||||||
|
assert device is not None
|
||||||
|
debug_info_data = await debug_info.info_for_device(hass, device.id)
|
||||||
|
assert len(debug_info_data["entities"]) == 2
|
||||||
|
assert len(debug_info_data["triggers"]) == 2
|
||||||
|
|
||||||
|
for c in config:
|
||||||
|
# Test we get debug info for each entity and trigger
|
||||||
|
domain = c["domain"]
|
||||||
|
# Use topic as discovery_id
|
||||||
|
id = c["config"].get("topic", c["config"].get("state_topic"))
|
||||||
|
|
||||||
|
if c["domain"] != "device_automation":
|
||||||
|
discovery_data = [e["discovery_data"] for e in debug_info_data["entities"]]
|
||||||
|
topic = c["config"]["state_topic"]
|
||||||
|
assert {"topic": topic, "messages": []} in [
|
||||||
|
t for e in debug_info_data["entities"] for t in e["topics"]
|
||||||
|
]
|
||||||
|
else:
|
||||||
|
discovery_data = [e["discovery_data"] for e in debug_info_data["triggers"]]
|
||||||
|
|
||||||
|
assert {
|
||||||
|
"topic": f"homeassistant/{domain}/{id}/config",
|
||||||
|
"payload": c["config"],
|
||||||
|
} in discovery_data
|
||||||
|
|
||||||
|
|
||||||
|
async def test_debug_info_non_mqtt(hass, device_reg, entity_reg):
|
||||||
|
"""Test we get empty debug_info for a device with non MQTT entities."""
|
||||||
|
DOMAIN = "sensor"
|
||||||
|
platform = getattr(hass.components, f"test.{DOMAIN}")
|
||||||
|
platform.init()
|
||||||
|
|
||||||
|
config_entry = MockConfigEntry(domain="test", data={})
|
||||||
|
config_entry.add_to_hass(hass)
|
||||||
|
device_entry = device_reg.async_get_or_create(
|
||||||
|
config_entry_id=config_entry.entry_id,
|
||||||
|
connections={(device_registry.CONNECTION_NETWORK_MAC, "12:34:56:AB:CD:EF")},
|
||||||
|
)
|
||||||
|
for device_class in DEVICE_CLASSES:
|
||||||
|
entity_reg.async_get_or_create(
|
||||||
|
DOMAIN,
|
||||||
|
"test",
|
||||||
|
platform.ENTITIES[device_class].unique_id,
|
||||||
|
device_id=device_entry.id,
|
||||||
|
)
|
||||||
|
|
||||||
|
assert await async_setup_component(hass, DOMAIN, {DOMAIN: {"platform": "test"}})
|
||||||
|
|
||||||
|
debug_info_data = await debug_info.info_for_device(hass, device_entry.id)
|
||||||
|
assert len(debug_info_data["entities"]) == 0
|
||||||
|
assert len(debug_info_data["triggers"]) == 0
|
||||||
|
|
|
@ -14,6 +14,7 @@ from homeassistant.components.vacuum import (
|
||||||
ATTR_BATTERY_ICON,
|
ATTR_BATTERY_ICON,
|
||||||
ATTR_BATTERY_LEVEL,
|
ATTR_BATTERY_LEVEL,
|
||||||
ATTR_FAN_SPEED,
|
ATTR_FAN_SPEED,
|
||||||
|
ATTR_FAN_SPEED_LIST,
|
||||||
ATTR_STATUS,
|
ATTR_STATUS,
|
||||||
)
|
)
|
||||||
from homeassistant.const import CONF_NAME, CONF_PLATFORM, STATE_OFF, STATE_ON
|
from homeassistant.const import CONF_NAME, CONF_PLATFORM, STATE_OFF, STATE_ON
|
||||||
|
@ -223,10 +224,20 @@ async def test_attributes_without_supported_features(hass, mqtt_mock):
|
||||||
|
|
||||||
assert await async_setup_component(hass, vacuum.DOMAIN, {vacuum.DOMAIN: config})
|
assert await async_setup_component(hass, vacuum.DOMAIN, {vacuum.DOMAIN: config})
|
||||||
|
|
||||||
|
message = """{
|
||||||
|
"battery_level": 54,
|
||||||
|
"cleaning": true,
|
||||||
|
"docked": false,
|
||||||
|
"charging": false,
|
||||||
|
"fan_speed": "max"
|
||||||
|
}"""
|
||||||
|
async_fire_mqtt_message(hass, "vacuum/state", message)
|
||||||
state = hass.states.get("vacuum.mqtttest")
|
state = hass.states.get("vacuum.mqtttest")
|
||||||
assert state.state == STATE_OFF
|
assert state.state == STATE_ON
|
||||||
assert state.attributes.get(ATTR_BATTERY_LEVEL) is None
|
assert state.attributes.get(ATTR_BATTERY_LEVEL) is None
|
||||||
assert state.attributes.get(ATTR_BATTERY_ICON) is None
|
assert state.attributes.get(ATTR_BATTERY_ICON) is None
|
||||||
|
assert state.attributes.get(ATTR_FAN_SPEED) is None
|
||||||
|
assert state.attributes.get(ATTR_FAN_SPEED_LIST) is None
|
||||||
|
|
||||||
|
|
||||||
async def test_status(hass, mqtt_mock):
|
async def test_status(hass, mqtt_mock):
|
||||||
|
@ -353,6 +364,36 @@ async def test_status_fan_speed(hass, mqtt_mock):
|
||||||
assert state.attributes.get(ATTR_FAN_SPEED) == "max"
|
assert state.attributes.get(ATTR_FAN_SPEED) == "max"
|
||||||
|
|
||||||
|
|
||||||
|
async def test_status_fan_speed_list(hass, mqtt_mock):
|
||||||
|
"""Test status updates from the vacuum."""
|
||||||
|
config = deepcopy(DEFAULT_CONFIG)
|
||||||
|
config[mqttvacuum.CONF_SUPPORTED_FEATURES] = services_to_strings(
|
||||||
|
ALL_SERVICES, SERVICE_TO_STRING
|
||||||
|
)
|
||||||
|
|
||||||
|
assert await async_setup_component(hass, vacuum.DOMAIN, {vacuum.DOMAIN: config})
|
||||||
|
|
||||||
|
state = hass.states.get("vacuum.mqtttest")
|
||||||
|
assert state.attributes.get(ATTR_FAN_SPEED_LIST) == ["min", "medium", "high", "max"]
|
||||||
|
|
||||||
|
|
||||||
|
async def test_status_no_fan_speed_list(hass, mqtt_mock):
|
||||||
|
"""Test status updates from the vacuum.
|
||||||
|
|
||||||
|
If the vacuum doesn't support fan speed, fan speed list should be None.
|
||||||
|
"""
|
||||||
|
config = deepcopy(DEFAULT_CONFIG)
|
||||||
|
services = ALL_SERVICES - mqttvacuum.SUPPORT_FAN_SPEED
|
||||||
|
config[mqttvacuum.CONF_SUPPORTED_FEATURES] = services_to_strings(
|
||||||
|
services, SERVICE_TO_STRING
|
||||||
|
)
|
||||||
|
|
||||||
|
assert await async_setup_component(hass, vacuum.DOMAIN, {vacuum.DOMAIN: config})
|
||||||
|
|
||||||
|
state = hass.states.get("vacuum.mqtttest")
|
||||||
|
assert state.attributes.get(ATTR_FAN_SPEED_LIST) is None
|
||||||
|
|
||||||
|
|
||||||
async def test_status_error(hass, mqtt_mock):
|
async def test_status_error(hass, mqtt_mock):
|
||||||
"""Test status updates from the vacuum."""
|
"""Test status updates from the vacuum."""
|
||||||
config = deepcopy(DEFAULT_CONFIG)
|
config = deepcopy(DEFAULT_CONFIG)
|
||||||
|
|
Loading…
Add table
Reference in a new issue