Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 24 additions & 33 deletions homeassistant/components/mqtt/cover.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@
STATE_UNKNOWN,
)
from homeassistant.core import callback
from homeassistant.exceptions import TemplateError
import homeassistant.helpers.config_validation as cv
from homeassistant.helpers.dispatcher import async_dispatcher_connect
from homeassistant.helpers.typing import ConfigType, HomeAssistantType
Expand Down Expand Up @@ -531,9 +530,6 @@ async def async_close_cover_tilt(self, **kwargs):

async def async_set_cover_tilt_position(self, **kwargs):
"""Move the cover tilt to a specific position."""
if ATTR_TILT_POSITION not in kwargs:
return

position = float(kwargs[ATTR_TILT_POSITION])

# The position needs to be between min and max
Expand All @@ -550,36 +546,31 @@ async def async_set_cover_tilt_position(self, **kwargs):
async def async_set_cover_position(self, **kwargs):
"""Move the cover to a specific position."""
set_position_template = self._config.get(CONF_SET_POSITION_TEMPLATE)
if ATTR_POSITION in kwargs:
position = kwargs[ATTR_POSITION]
percentage_position = position
if set_position_template is not None:
try:
position = set_position_template.async_render(**kwargs)
except TemplateError as ex:
_LOGGER.error(ex)
self._state = None
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(
self.hass,
self._config.get(CONF_SET_POSITION_TOPIC),
position,
self._config[CONF_QOS],
self._config[CONF_RETAIN],
position = kwargs[ATTR_POSITION]
percentage_position = position
if set_position_template is not None:
position = set_position_template.async_render(**kwargs)
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(
self.hass,
self._config.get(CONF_SET_POSITION_TOPIC),
position,
self._config[CONF_QOS],
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._state = (
STATE_CLOSED
if percentage_position == self._config[CONF_POSITION_CLOSED]
else STATE_OPEN
)
self._position = percentage_position
self.async_write_ha_state()
self._position = percentage_position
self.async_write_ha_state()

async def async_toggle_tilt(self, **kwargs):
"""Toggle the entity."""
Expand Down
20 changes: 0 additions & 20 deletions homeassistant/components/mqtt/discovery.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@

from homeassistant.components import mqtt
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.typing import HomeAssistantType

Expand Down Expand Up @@ -35,21 +34,6 @@
"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"
DATA_CONFIG_ENTRY_LOCK = "mqtt_config_entry_lock"
CONFIG_ENTRY_IS_SETUP = "mqtt_config_entry_is_setup"
Expand Down Expand Up @@ -159,10 +143,6 @@ async def async_device_message_received(msg):
_LOGGER.info("Found new component: %s %s", component, discovery_id)
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"
async with hass.data[DATA_CONFIG_ENTRY_LOCK]:
if config_entries_key not in hass.data[CONFIG_ENTRY_IS_SETUP]:
Expand Down
6 changes: 0 additions & 6 deletions homeassistant/components/mqtt/fan.py
Original file line number Diff line number Diff line change
Expand Up @@ -401,9 +401,6 @@ async def async_set_speed(self, speed: str) -> None:

This method is a coroutine.
"""
if self._topic[CONF_SPEED_COMMAND_TOPIC] is None:
return

if speed == SPEED_LOW:
mqtt_payload = self._payload["SPEED_LOW"]
elif speed == SPEED_MEDIUM:
Expand Down Expand Up @@ -432,9 +429,6 @@ async def async_oscillate(self, oscillating: bool) -> None:

This method is a coroutine.
"""
if self._topic[CONF_OSCILLATION_COMMAND_TOPIC] is None:
return

if oscillating is False:
payload = self._payload["OSCILLATE_OFF_PAYLOAD"]
else:
Expand Down
16 changes: 9 additions & 7 deletions homeassistant/components/mqtt/vacuum/schema_legacy.py
Original file line number Diff line number Diff line change
Expand Up @@ -410,24 +410,26 @@ def fan_speed(self):

@property
def fan_speed_list(self):
"""Return the status of the vacuum."""
if self.supported_features & SUPPORT_FAN_SPEED == 0:
return []
"""Return the status of the vacuum.

No need to check SUPPORT_FAN_SPEED, this won't be called if fan_speed is None.
"""
return self._fan_speed_list

@property
def battery_level(self):
"""Return the status of the vacuum."""
if self.supported_features & SUPPORT_BATTERY == 0:
return
return None

return max(0, min(100, self._battery_level))

@property
def battery_icon(self):
"""Return the battery icon for the vacuum cleaner."""
if self.supported_features & SUPPORT_BATTERY == 0:
return
"""Return the battery icon for the vacuum cleaner.

No need to check SUPPORT_BATTERY, this won't be called if battery_level is None.
"""

return icon_for_battery_level(
battery_level=self.battery_level, charging=self._charging
Expand Down
7 changes: 4 additions & 3 deletions homeassistant/components/mqtt/vacuum/schema_state.py
Original file line number Diff line number Diff line change
Expand Up @@ -282,9 +282,10 @@ def fan_speed(self):

@property
def fan_speed_list(self):
"""Return fan speed list of the vacuum."""
if self.supported_features & SUPPORT_FAN_SPEED == 0:
return None
"""Return fan speed list of the vacuum.

No need to check SUPPORT_FAN_SPEED, this won't be called if fan_speed is None.
"""
return self._fan_speed_list

@property
Expand Down
31 changes: 30 additions & 1 deletion tests/components/mqtt/test_alarm_control_panel.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,8 @@
)
from tests.components.alarm_control_panel import common

CODE = "HELLO_CODE"
CODE_NUMBER = "1234"
CODE_TEXT = "HELLO_CODE"

DEFAULT_CONFIG = {
alarm_control_panel.DOMAIN: {
Expand Down Expand Up @@ -341,6 +342,34 @@ async def test_update_state_via_state_topic_template(hass, mqtt_mock):
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):
"""Test availability without defined availability topic."""
await help_test_availability_without_topic(
Expand Down
16 changes: 16 additions & 0 deletions tests/components/mqtt/test_climate.py
Original file line number Diff line number Diff line change
Expand Up @@ -534,6 +534,22 @@ async def test_set_hold(hass, mqtt_mock):
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):
"""Test setting of the aux heating in pessimistic mode."""
config = copy.deepcopy(DEFAULT_CONFIG)
Expand Down
Loading