diff --git a/homeassistant/components/devolo_home_control/manifest.json b/homeassistant/components/devolo_home_control/manifest.json index 93cf4be5d35..e53e715ffb1 100644 --- a/homeassistant/components/devolo_home_control/manifest.json +++ b/homeassistant/components/devolo_home_control/manifest.json @@ -2,7 +2,7 @@ "domain": "devolo_home_control", "name": "devolo Home Control", "documentation": "https://www.home-assistant.io/integrations/devolo_home_control", - "requirements": ["devolo-home-control-api==0.17.1"], + "requirements": ["devolo-home-control-api==0.17.3"], "after_dependencies": ["zeroconf"], "config_flow": true, "codeowners": ["@2Fake", "@Shutgun"], diff --git a/homeassistant/components/mqtt/fan.py b/homeassistant/components/mqtt/fan.py index 395480a041d..6009b941c5c 100644 --- a/homeassistant/components/mqtt/fan.py +++ b/homeassistant/components/mqtt/fan.py @@ -32,6 +32,7 @@ import homeassistant.helpers.config_validation as cv from homeassistant.helpers.reload import async_setup_reload_service from homeassistant.helpers.typing import ConfigType, HomeAssistantType from homeassistant.util.percentage import ( + int_states_in_range, ordered_list_item_to_percentage, percentage_to_ordered_list_item, percentage_to_ranged_value, @@ -224,6 +225,9 @@ class MqttFan(MqttEntity, FanEntity): self._optimistic_preset_mode = None self._optimistic_speed = None + self._legacy_speeds_list = [] + self._legacy_speeds_list_no_off = [] + MqttEntity.__init__(self, hass, config, config_entry, discovery_data) @staticmethod @@ -284,28 +288,18 @@ class MqttFan(MqttEntity, FanEntity): self._legacy_speeds_list_no_off = speed_list_without_preset_modes( self._legacy_speeds_list ) - else: - self._legacy_speeds_list = [] self._feature_percentage = CONF_PERCENTAGE_COMMAND_TOPIC in config self._feature_preset_mode = CONF_PRESET_MODE_COMMAND_TOPIC in config if self._feature_preset_mode: - self._speeds_list = speed_list_without_preset_modes( - self._legacy_speeds_list + config[CONF_PRESET_MODES_LIST] - ) - self._preset_modes = ( - self._legacy_speeds_list + config[CONF_PRESET_MODES_LIST] - ) + self._preset_modes = config[CONF_PRESET_MODES_LIST] else: - self._speeds_list = speed_list_without_preset_modes( - self._legacy_speeds_list - ) self._preset_modes = [] - if not self._speeds_list or self._feature_percentage: - self._speed_count = 100 + if self._feature_percentage: + self._speed_count = min(int_states_in_range(self._speed_range), 100) else: - self._speed_count = len(self._speeds_list) + self._speed_count = len(self._legacy_speeds_list_no_off) or 100 optimistic = config[CONF_OPTIMISTIC] self._optimistic = optimistic or self._topic[CONF_STATE_TOPIC] is None @@ -327,11 +321,7 @@ class MqttFan(MqttEntity, FanEntity): self._topic[CONF_OSCILLATION_COMMAND_TOPIC] is not None and SUPPORT_OSCILLATE ) - if self._feature_preset_mode and self._speeds_list: - self._supported_features |= SUPPORT_SET_SPEED - if self._feature_percentage: - self._supported_features |= SUPPORT_SET_SPEED - if self._feature_legacy_speeds: + if self._feature_percentage or self._feature_legacy_speeds: self._supported_features |= SUPPORT_SET_SPEED if self._feature_preset_mode: self._supported_features |= SUPPORT_PRESET_MODE @@ -414,10 +404,6 @@ class MqttFan(MqttEntity, FanEntity): return self._preset_mode = preset_mode - if not self._implemented_percentage and (preset_mode in self.speed_list): - self._percentage = ordered_list_item_to_percentage( - self.speed_list, preset_mode - ) self.async_write_ha_state() if self._topic[CONF_PRESET_MODE_STATE_TOPIC] is not None: @@ -455,10 +441,10 @@ class MqttFan(MqttEntity, FanEntity): ) return - if not self._implemented_percentage: - if speed in self._speeds_list: + if not self._feature_percentage: + if speed in self._legacy_speeds_list_no_off: self._percentage = ordered_list_item_to_percentage( - self._speeds_list, speed + self._legacy_speeds_list_no_off, speed ) elif speed == SPEED_OFF: self._percentage = 0 @@ -506,19 +492,9 @@ class MqttFan(MqttEntity, FanEntity): """Return true if device is on.""" return self._state - @property - def _implemented_percentage(self): - """Return true if percentage has been implemented.""" - return self._feature_percentage - - @property - def _implemented_preset_mode(self): - """Return true if preset_mode has been implemented.""" - return self._feature_preset_mode - # The use of legacy speeds is deprecated in the schema, support will be removed after a quarter (2021.7) @property - def _implemented_speed(self): + def _implemented_speed(self) -> bool: """Return true if speed has been implemented.""" return self._feature_legacy_speeds @@ -541,7 +517,7 @@ class MqttFan(MqttEntity, FanEntity): @property def speed_list(self) -> list: """Get the list of available speeds.""" - return self._speeds_list + return self._legacy_speeds_list_no_off @property def supported_features(self) -> int: @@ -555,7 +531,7 @@ class MqttFan(MqttEntity, FanEntity): @property def speed_count(self) -> int: - """Return the number of speeds the fan supports or 100 if percentage is supported.""" + """Return the number of speeds the fan supports.""" return self._speed_count @property @@ -620,20 +596,8 @@ class MqttFan(MqttEntity, FanEntity): percentage_to_ranged_value(self._speed_range, percentage) ) mqtt_payload = self._command_templates[ATTR_PERCENTAGE](percentage_payload) - if self._implemented_preset_mode: - if percentage: - await self.async_set_preset_mode( - preset_mode=percentage_to_ordered_list_item( - self.speed_list, percentage - ) - ) - # Legacy are deprecated in the schema, support will be removed after a quarter (2021.7) - elif self._feature_legacy_speeds and ( - SPEED_OFF in self._legacy_speeds_list - ): - await self.async_set_preset_mode(SPEED_OFF) # Legacy are deprecated in the schema, support will be removed after a quarter (2021.7) - elif self._feature_legacy_speeds: + if self._feature_legacy_speeds: if percentage: await self.async_set_speed( percentage_to_ordered_list_item( @@ -644,7 +608,7 @@ class MqttFan(MqttEntity, FanEntity): elif SPEED_OFF in self._legacy_speeds_list: await self.async_set_speed(SPEED_OFF) - if self._implemented_percentage: + if self._feature_percentage: mqtt.async_publish( self.hass, self._topic[CONF_PERCENTAGE_COMMAND_TOPIC], @@ -665,13 +629,7 @@ class MqttFan(MqttEntity, FanEntity): if preset_mode not in self.preset_modes: _LOGGER.warning("'%s'is not a valid preset mode", preset_mode) return - # Legacy are deprecated in the schema, support will be removed after a quarter (2021.7) - if preset_mode in self._legacy_speeds_list: - await self.async_set_speed(speed=preset_mode) - if not self._implemented_percentage and preset_mode in self.speed_list: - self._percentage = ordered_list_item_to_percentage( - self.speed_list, preset_mode - ) + mqtt_payload = self._command_templates[ATTR_PRESET_MODE](preset_mode) mqtt.async_publish( @@ -693,18 +651,18 @@ class MqttFan(MqttEntity, FanEntity): This method is a coroutine. """ speed_payload = None - if self._feature_legacy_speeds: + if speed in self._legacy_speeds_list: if speed == SPEED_LOW: speed_payload = self._payload["SPEED_LOW"] elif speed == SPEED_MEDIUM: speed_payload = self._payload["SPEED_MEDIUM"] elif speed == SPEED_HIGH: speed_payload = self._payload["SPEED_HIGH"] - elif speed == SPEED_OFF: - speed_payload = self._payload["SPEED_OFF"] else: - _LOGGER.warning("'%s'is not a valid speed", speed) - return + speed_payload = self._payload["SPEED_OFF"] + else: + _LOGGER.warning("'%s' is not a valid speed", speed) + return if speed_payload: mqtt.async_publish( diff --git a/homeassistant/components/ping/__init__.py b/homeassistant/components/ping/__init__.py index 726bb212574..b9a9f6460db 100644 --- a/homeassistant/components/ping/__init__.py +++ b/homeassistant/components/ping/__init__.py @@ -24,20 +24,22 @@ async def async_setup(hass, config): @callback -def async_get_next_ping_id(hass): +def async_get_next_ping_id(hass, count=1): """Find the next id to use in the outbound ping. + When using multiping, we increment the id + by the number of ids that multiping + will use. + Must be called in async """ - current_id = hass.data[DOMAIN][PING_ID] - if current_id == MAX_PING_ID: - next_id = DEFAULT_START_ID - else: - next_id = current_id + 1 - - hass.data[DOMAIN][PING_ID] = next_id - - return next_id + allocated_id = hass.data[DOMAIN][PING_ID] + 1 + if allocated_id > MAX_PING_ID: + allocated_id -= MAX_PING_ID - DEFAULT_START_ID + hass.data[DOMAIN][PING_ID] += count + if hass.data[DOMAIN][PING_ID] > MAX_PING_ID: + hass.data[DOMAIN][PING_ID] -= MAX_PING_ID - DEFAULT_START_ID + return allocated_id def _can_use_icmp_lib_with_privilege() -> None | bool: diff --git a/homeassistant/components/ping/device_tracker.py b/homeassistant/components/ping/device_tracker.py index a6b75a9245b..256023263ba 100644 --- a/homeassistant/components/ping/device_tracker.py +++ b/homeassistant/components/ping/device_tracker.py @@ -125,7 +125,7 @@ async def async_setup_scanner(hass, config, async_see, discovery_info=None): count=PING_ATTEMPTS_COUNT, timeout=ICMP_TIMEOUT, privileged=privileged, - id=async_get_next_ping_id(hass), + id=async_get_next_ping_id(hass, len(ip_to_dev_id)), ) ) _LOGGER.debug("Multiping responses: %s", responses) diff --git a/homeassistant/components/shelly/device_trigger.py b/homeassistant/components/shelly/device_trigger.py index b7cf1120949..97938040543 100644 --- a/homeassistant/components/shelly/device_trigger.py +++ b/homeassistant/components/shelly/device_trigger.py @@ -27,6 +27,7 @@ from .const import ( DOMAIN, EVENT_SHELLY_CLICK, INPUTS_EVENTS_SUBTYPES, + SHBTN_1_INPUTS_EVENTS_TYPES, SUPPORTED_INPUTS_EVENTS_TYPES, ) from .utils import get_device_wrapper, get_input_triggers @@ -45,7 +46,7 @@ async def async_validate_trigger_config(hass, config): # if device is available verify parameters against device capabilities wrapper = get_device_wrapper(hass, config[CONF_DEVICE_ID]) - if not wrapper: + if not wrapper or not wrapper.device.initialized: return config trigger = (config[CONF_TYPE], config[CONF_SUBTYPE]) @@ -68,6 +69,19 @@ async def async_get_triggers(hass: HomeAssistant, device_id: str) -> list[dict]: if not wrapper: raise InvalidDeviceAutomationConfig(f"Device not found: {device_id}") + if wrapper.model in ("SHBTN-1", "SHBTN-2"): + for trigger in SHBTN_1_INPUTS_EVENTS_TYPES: + triggers.append( + { + CONF_PLATFORM: "device", + CONF_DEVICE_ID: device_id, + CONF_DOMAIN: DOMAIN, + CONF_TYPE: trigger, + CONF_SUBTYPE: "button", + } + ) + return triggers + for block in wrapper.device.blocks: input_triggers = get_input_triggers(wrapper.device, block) diff --git a/homeassistant/components/template/__init__.py b/homeassistant/components/template/__init__.py index 72a97d6eeab..3b10e708e51 100644 --- a/homeassistant/components/template/__init__.py +++ b/homeassistant/components/template/__init__.py @@ -68,7 +68,7 @@ async def _process_config(hass, config): async def init_coordinator(hass, conf): coordinator = TriggerUpdateCoordinator(hass, conf) - await coordinator.async_setup(conf) + await coordinator.async_setup(config) return coordinator hass.data[DOMAIN] = await asyncio.gather( diff --git a/homeassistant/components/tts/__init__.py b/homeassistant/components/tts/__init__.py index e0f59c51e5a..5922392f17d 100644 --- a/homeassistant/components/tts/__init__.py +++ b/homeassistant/components/tts/__init__.py @@ -31,6 +31,7 @@ from homeassistant.const import ( CONF_PLATFORM, HTTP_BAD_REQUEST, HTTP_NOT_FOUND, + PLATFORM_FORMAT, ) from homeassistant.core import callback from homeassistant.exceptions import HomeAssistantError @@ -316,6 +317,10 @@ class SpeechManager: provider.name = engine self.providers[engine] = provider + self.hass.config.components.add( + PLATFORM_FORMAT.format(domain=engine, platform=DOMAIN) + ) + async def async_get_url_path( self, engine, message, cache=None, language=None, options=None ): diff --git a/homeassistant/components/tts/manifest.json b/homeassistant/components/tts/manifest.json index 3db130d01bc..07cee3b867b 100644 --- a/homeassistant/components/tts/manifest.json +++ b/homeassistant/components/tts/manifest.json @@ -5,5 +5,6 @@ "requirements": ["mutagen==1.45.1"], "dependencies": ["http"], "after_dependencies": ["media_player"], + "quality_scale": "internal", "codeowners": ["@pvizeli"] } diff --git a/homeassistant/const.py b/homeassistant/const.py index ffc2d1a3427..9e6fe036d5c 100644 --- a/homeassistant/const.py +++ b/homeassistant/const.py @@ -1,7 +1,7 @@ """Constants used by Home Assistant components.""" MAJOR_VERSION = 2021 MINOR_VERSION = 4 -PATCH_VERSION = "2" +PATCH_VERSION = "3" __short_version__ = f"{MAJOR_VERSION}.{MINOR_VERSION}" __version__ = f"{__short_version__}.{PATCH_VERSION}" REQUIRED_PYTHON_VER = (3, 8, 0) diff --git a/homeassistant/setup.py b/homeassistant/setup.py index 6b306995dfc..1b48efb8c0f 100644 --- a/homeassistant/setup.py +++ b/homeassistant/setup.py @@ -36,6 +36,7 @@ BASE_PLATFORMS = { "scene", "sensor", "switch", + "tts", "vacuum", "water_heater", } diff --git a/requirements_all.txt b/requirements_all.txt index 694f7c73b89..26c9af80aa3 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -479,7 +479,7 @@ deluge-client==1.7.1 denonavr==0.9.10 # homeassistant.components.devolo_home_control -devolo-home-control-api==0.17.1 +devolo-home-control-api==0.17.3 # homeassistant.components.directv directv==0.4.0 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index 3936ed66128..0094e499f22 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -261,7 +261,7 @@ defusedxml==0.6.0 denonavr==0.9.10 # homeassistant.components.devolo_home_control -devolo-home-control-api==0.17.1 +devolo-home-control-api==0.17.3 # homeassistant.components.directv directv==0.4.0 diff --git a/tests/components/mqtt/test_fan.py b/tests/components/mqtt/test_fan.py index be32540b04d..5caec9b7473 100644 --- a/tests/components/mqtt/test_fan.py +++ b/tests/components/mqtt/test_fan.py @@ -85,11 +85,11 @@ async def test_controlling_state_via_topic(hass, mqtt_mock, caplog): "preset_mode_state_topic": "preset-mode-state-topic", "preset_mode_command_topic": "preset-mode-command-topic", "preset_modes": [ - "medium", - "medium-high", - "high", - "very-high", - "freaking-high", + "auto", + "smart", + "whoosh", + "eco", + "breeze", "silent", ], "speed_range_min": 1, @@ -126,6 +126,8 @@ async def test_controlling_state_via_topic(hass, mqtt_mock, caplog): state = hass.states.get("fan.test") assert state.attributes.get("oscillating") is False + assert state.attributes.get("percentage_step") == 1.0 + async_fire_mqtt_message(hass, "percentage-state-topic", "0") state = hass.states.get("fan.test") assert state.attributes.get(fan.ATTR_PERCENTAGE) == 0 @@ -151,16 +153,16 @@ async def test_controlling_state_via_topic(hass, mqtt_mock, caplog): caplog.clear() async_fire_mqtt_message(hass, "preset-mode-state-topic", "low") - state = hass.states.get("fan.test") - assert state.attributes.get("preset_mode") == "low" + assert "not a valid preset mode" in caplog.text + caplog.clear() - async_fire_mqtt_message(hass, "preset-mode-state-topic", "medium") + async_fire_mqtt_message(hass, "preset-mode-state-topic", "auto") state = hass.states.get("fan.test") - assert state.attributes.get("preset_mode") == "medium" + assert state.attributes.get("preset_mode") == "auto" - async_fire_mqtt_message(hass, "preset-mode-state-topic", "very-high") + async_fire_mqtt_message(hass, "preset-mode-state-topic", "eco") state = hass.states.get("fan.test") - assert state.attributes.get("preset_mode") == "very-high" + assert state.attributes.get("preset_mode") == "eco" async_fire_mqtt_message(hass, "preset-mode-state-topic", "silent") state = hass.states.get("fan.test") @@ -256,7 +258,9 @@ async def test_controlling_state_via_topic_with_different_speed_range( caplog.clear() -async def test_controlling_state_via_topic_no_percentage_topics(hass, mqtt_mock): +async def test_controlling_state_via_topic_no_percentage_topics( + hass, mqtt_mock, caplog +): """Test the controlling state via topic without percentage topics.""" assert await async_setup_component( hass, @@ -273,9 +277,11 @@ async def test_controlling_state_via_topic_no_percentage_topics(hass, mqtt_mock) "preset_mode_state_topic": "preset-mode-state-topic", "preset_mode_command_topic": "preset-mode-command-topic", "preset_modes": [ - "high", - "freaking-high", - "silent", + "auto", + "smart", + "whoosh", + "eco", + "breeze", ], # use of speeds is deprecated, support will be removed after a quarter (2021.7) "speeds": ["off", "low", "medium"], @@ -288,57 +294,51 @@ async def test_controlling_state_via_topic_no_percentage_topics(hass, mqtt_mock) assert state.state == STATE_OFF assert not state.attributes.get(ATTR_ASSUMED_STATE) - async_fire_mqtt_message(hass, "preset-mode-state-topic", "freaking-high") + async_fire_mqtt_message(hass, "preset-mode-state-topic", "smart") state = hass.states.get("fan.test") - assert state.attributes.get("preset_mode") == "freaking-high" - assert state.attributes.get(fan.ATTR_PERCENTAGE) == 100 + assert state.attributes.get("preset_mode") == "smart" + assert state.attributes.get(fan.ATTR_PERCENTAGE) is None # use of speeds is deprecated, support will be removed after a quarter (2021.7) assert state.attributes.get("speed") == fan.SPEED_OFF - async_fire_mqtt_message(hass, "preset-mode-state-topic", "high") + async_fire_mqtt_message(hass, "preset-mode-state-topic", "auto") state = hass.states.get("fan.test") - assert state.attributes.get("preset_mode") == "high" - assert state.attributes.get(fan.ATTR_PERCENTAGE) == 75 + assert state.attributes.get("preset_mode") == "auto" + assert state.attributes.get(fan.ATTR_PERCENTAGE) is None # use of speeds is deprecated, support will be removed after a quarter (2021.7) assert state.attributes.get("speed") == fan.SPEED_OFF - async_fire_mqtt_message(hass, "preset-mode-state-topic", "silent") + async_fire_mqtt_message(hass, "preset-mode-state-topic", "whoosh") state = hass.states.get("fan.test") - assert state.attributes.get("preset_mode") == "silent" - assert state.attributes.get(fan.ATTR_PERCENTAGE) == 75 + assert state.attributes.get("preset_mode") == "whoosh" + assert state.attributes.get(fan.ATTR_PERCENTAGE) is None # use of speeds is deprecated, support will be removed after a quarter (2021.7) assert state.attributes.get("speed") == fan.SPEED_OFF async_fire_mqtt_message(hass, "preset-mode-state-topic", "medium") - state = hass.states.get("fan.test") - assert state.attributes.get("preset_mode") == "medium" - assert state.attributes.get(fan.ATTR_PERCENTAGE) == 50 - # use of speeds is deprecated, support will be removed after a quarter (2021.7) - assert state.attributes.get("speed") == fan.SPEED_OFF + assert "not a valid preset mode" in caplog.text + caplog.clear() async_fire_mqtt_message(hass, "preset-mode-state-topic", "low") - state = hass.states.get("fan.test") - assert state.attributes.get("preset_mode") == "low" - assert state.attributes.get(fan.ATTR_PERCENTAGE) == 25 - # use of speeds is deprecated, support will be removed after a quarter (2021.7) - assert state.attributes.get("speed") == fan.SPEED_OFF + assert "not a valid preset mode" in caplog.text + caplog.clear() # use of speeds is deprecated, support will be removed after a quarter (2021.7) async_fire_mqtt_message(hass, "speed-state-topic", "medium") state = hass.states.get("fan.test") - assert state.attributes.get("preset_mode") == "low" - assert state.attributes.get(fan.ATTR_PERCENTAGE) == 50 + assert state.attributes.get("preset_mode") == "whoosh" + assert state.attributes.get(fan.ATTR_PERCENTAGE) == 100 assert state.attributes.get("speed") == fan.SPEED_MEDIUM async_fire_mqtt_message(hass, "speed-state-topic", "low") state = hass.states.get("fan.test") - assert state.attributes.get("preset_mode") == "low" - assert state.attributes.get(fan.ATTR_PERCENTAGE) == 25 + assert state.attributes.get("preset_mode") == "whoosh" + assert state.attributes.get(fan.ATTR_PERCENTAGE) == 50 assert state.attributes.get("speed") == fan.SPEED_LOW async_fire_mqtt_message(hass, "speed-state-topic", "off") state = hass.states.get("fan.test") - assert state.attributes.get("preset_mode") == "low" + assert state.attributes.get("preset_mode") == "whoosh" assert state.attributes.get(fan.ATTR_PERCENTAGE) == 0 assert state.attributes.get("speed") == fan.SPEED_OFF @@ -361,11 +361,11 @@ async def test_controlling_state_via_topic_and_json_message(hass, mqtt_mock, cap "preset_mode_state_topic": "preset-mode-state-topic", "preset_mode_command_topic": "preset-mode-command-topic", "preset_modes": [ - "medium", - "medium-high", - "high", - "very-high", - "freaking-high", + "auto", + "smart", + "whoosh", + "eco", + "breeze", "silent", ], "state_value_template": "{{ value_json.val }}", @@ -412,20 +412,20 @@ async def test_controlling_state_via_topic_and_json_message(hass, mqtt_mock, cap assert "not a valid preset mode" in caplog.text caplog.clear() - async_fire_mqtt_message(hass, "preset-mode-state-topic", '{"val": "medium"}') + async_fire_mqtt_message(hass, "preset-mode-state-topic", '{"val": "auto"}') state = hass.states.get("fan.test") - assert state.attributes.get("preset_mode") == "medium" + assert state.attributes.get("preset_mode") == "auto" - async_fire_mqtt_message(hass, "preset-mode-state-topic", '{"val": "freaking-high"}') + async_fire_mqtt_message(hass, "preset-mode-state-topic", '{"val": "breeze"}') state = hass.states.get("fan.test") - assert state.attributes.get("preset_mode") == "freaking-high" + assert state.attributes.get("preset_mode") == "breeze" async_fire_mqtt_message(hass, "preset-mode-state-topic", '{"val": "silent"}') state = hass.states.get("fan.test") assert state.attributes.get("preset_mode") == "silent" -async def test_sending_mqtt_commands_and_optimistic(hass, mqtt_mock): +async def test_sending_mqtt_commands_and_optimistic(hass, mqtt_mock, caplog): """Test optimistic mode without state topic.""" assert await async_setup_component( hass, @@ -447,8 +447,8 @@ async def test_sending_mqtt_commands_and_optimistic(hass, mqtt_mock): # use of speeds is deprecated, support will be removed after a quarter (2021.7) "speeds": ["off", "low", "medium"], "preset_modes": [ - "high", - "freaking-high", + "whoosh", + "breeze", "silent", ], # use of speeds is deprecated, support will be removed after a quarter (2021.7) @@ -510,7 +510,7 @@ async def test_sending_mqtt_commands_and_optimistic(hass, mqtt_mock): assert mqtt_mock.async_publish.call_count == 2 mqtt_mock.async_publish.assert_any_call("percentage-command-topic", "100", 0, False) mqtt_mock.async_publish.assert_any_call( - "preset-mode-command-topic", "freaking-high", 0, False + "speed-command-topic", "speed_mEdium", 0, False ) mqtt_mock.async_publish.reset_mock() state = hass.states.get("fan.test") @@ -518,11 +518,8 @@ async def test_sending_mqtt_commands_and_optimistic(hass, mqtt_mock): assert state.attributes.get(ATTR_ASSUMED_STATE) await common.async_set_percentage(hass, "fan.test", 0) - assert mqtt_mock.async_publish.call_count == 3 + assert mqtt_mock.async_publish.call_count == 2 mqtt_mock.async_publish.assert_any_call("percentage-command-topic", "0", 0, False) - mqtt_mock.async_publish.assert_any_call( - "preset-mode-command-topic", "off", 0, False - ) # use of speeds is deprecated, support will be removed after a quarter (2021.7) mqtt_mock.async_publish.assert_any_call( "speed-command-topic", "speed_OfF", 0, False @@ -534,54 +531,32 @@ async def test_sending_mqtt_commands_and_optimistic(hass, mqtt_mock): assert state.attributes.get(fan.ATTR_SPEED) == fan.SPEED_OFF assert state.attributes.get(ATTR_ASSUMED_STATE) + # use of speeds is deprecated, support will be removed after a quarter (2021.7) await common.async_set_preset_mode(hass, "fan.test", "low") - assert mqtt_mock.async_publish.call_count == 2 - # use of speeds is deprecated, support will be removed after a quarter (2021.7) - mqtt_mock.async_publish.assert_any_call( - "speed-command-topic", "speed_lOw", 0, False - ) - mqtt_mock.async_publish.assert_any_call( - "preset-mode-command-topic", "low", 0, False - ) - mqtt_mock.async_publish.reset_mock() - state = hass.states.get("fan.test") - assert state.attributes.get(fan.ATTR_PRESET_MODE) == "low" - # use of speeds is deprecated, support will be removed after a quarter (2021.7) - assert state.attributes.get(fan.ATTR_SPEED) == fan.SPEED_LOW - assert state.attributes.get(ATTR_ASSUMED_STATE) + assert "not a valid preset mode" in caplog.text + caplog.clear() + # use of speeds is deprecated, support will be removed after a quarter (2021.7) await common.async_set_preset_mode(hass, "fan.test", "medium") - assert mqtt_mock.async_publish.call_count == 2 - # use of speeds is deprecated, support will be removed after a quarter (2021.7) - mqtt_mock.async_publish.assert_any_call( - "speed-command-topic", "speed_mEdium", 0, False - ) - mqtt_mock.async_publish.assert_any_call( - "preset-mode-command-topic", "medium", 0, False + assert "not a valid preset mode" in caplog.text + caplog.clear() + + await common.async_set_preset_mode(hass, "fan.test", "whoosh") + mqtt_mock.async_publish.assert_called_once_with( + "preset-mode-command-topic", "whoosh", 0, False ) mqtt_mock.async_publish.reset_mock() state = hass.states.get("fan.test") - assert state.attributes.get(fan.ATTR_PRESET_MODE) == "medium" - # use of speeds is deprecated, support will be removed after a quarter (2021.7) - assert state.attributes.get(fan.ATTR_SPEED) == fan.SPEED_MEDIUM + assert state.attributes.get(fan.ATTR_PRESET_MODE) == "whoosh" assert state.attributes.get(ATTR_ASSUMED_STATE) - await common.async_set_preset_mode(hass, "fan.test", "high") + await common.async_set_preset_mode(hass, "fan.test", "breeze") mqtt_mock.async_publish.assert_called_once_with( - "preset-mode-command-topic", "high", 0, False + "preset-mode-command-topic", "breeze", 0, False ) mqtt_mock.async_publish.reset_mock() state = hass.states.get("fan.test") - assert state.attributes.get(fan.ATTR_PRESET_MODE) == "high" - assert state.attributes.get(ATTR_ASSUMED_STATE) - - await common.async_set_preset_mode(hass, "fan.test", "freaking-high") - mqtt_mock.async_publish.assert_called_once_with( - "preset-mode-command-topic", "freaking-high", 0, False - ) - mqtt_mock.async_publish.reset_mock() - state = hass.states.get("fan.test") - assert state.attributes.get(fan.ATTR_PRESET_MODE) == "freaking-high" + assert state.attributes.get(fan.ATTR_PRESET_MODE) == "breeze" assert state.attributes.get(ATTR_ASSUMED_STATE) await common.async_set_preset_mode(hass, "fan.test", "silent") @@ -615,13 +590,8 @@ async def test_sending_mqtt_commands_and_optimistic(hass, mqtt_mock): # use of speeds is deprecated, support will be removed after a quarter (2021.7) await common.async_set_speed(hass, "fan.test", fan.SPEED_HIGH) - mqtt_mock.async_publish.assert_called_once_with( - "speed-command-topic", "speed_High", 0, False - ) - mqtt_mock.async_publish.reset_mock() - state = hass.states.get("fan.test") - assert state.state == STATE_OFF - assert state.attributes.get(ATTR_ASSUMED_STATE) + assert "not a valid speed" in caplog.text + caplog.clear() # use of speeds is deprecated, support will be removed after a quarter (2021.7) await common.async_set_speed(hass, "fan.test", fan.SPEED_OFF) @@ -735,8 +705,8 @@ async def test_sending_mqtt_commands_and_optimistic_no_legacy(hass, mqtt_mock, c "percentage_command_topic": "percentage-command-topic", "preset_mode_command_topic": "preset-mode-command-topic", "preset_modes": [ - "high", - "freaking-high", + "whoosh", + "breeze", "silent", ], } @@ -769,14 +739,12 @@ async def test_sending_mqtt_commands_and_optimistic_no_legacy(hass, mqtt_mock, c await common.async_set_percentage(hass, "fan.test", 101) await common.async_set_percentage(hass, "fan.test", 100) - mqtt_mock.async_publish.assert_any_call("percentage-command-topic", "100", 0, False) - mqtt_mock.async_publish.assert_any_call( - "preset-mode-command-topic", "freaking-high", 0, False + mqtt_mock.async_publish.assert_called_once_with( + "percentage-command-topic", "100", 0, False ) mqtt_mock.async_publish.reset_mock() state = hass.states.get("fan.test") assert state.attributes.get(fan.ATTR_PERCENTAGE) == 100 - assert state.attributes.get(fan.ATTR_PRESET_MODE) == "freaking-high" assert state.attributes.get(ATTR_ASSUMED_STATE) await common.async_set_percentage(hass, "fan.test", 0) @@ -793,26 +761,26 @@ async def test_sending_mqtt_commands_and_optimistic_no_legacy(hass, mqtt_mock, c assert "not a valid preset mode" in caplog.text caplog.clear() - await common.async_set_preset_mode(hass, "fan.test", "medium") + await common.async_set_preset_mode(hass, "fan.test", "auto") assert "not a valid preset mode" in caplog.text caplog.clear() - await common.async_set_preset_mode(hass, "fan.test", "high") + await common.async_set_preset_mode(hass, "fan.test", "whoosh") mqtt_mock.async_publish.assert_called_once_with( - "preset-mode-command-topic", "high", 0, False + "preset-mode-command-topic", "whoosh", 0, False ) mqtt_mock.async_publish.reset_mock() state = hass.states.get("fan.test") - assert state.attributes.get(fan.ATTR_PRESET_MODE) == "high" + assert state.attributes.get(fan.ATTR_PRESET_MODE) == "whoosh" assert state.attributes.get(ATTR_ASSUMED_STATE) - await common.async_set_preset_mode(hass, "fan.test", "freaking-high") + await common.async_set_preset_mode(hass, "fan.test", "breeze") mqtt_mock.async_publish.assert_called_once_with( - "preset-mode-command-topic", "freaking-high", 0, False + "preset-mode-command-topic", "breeze", 0, False ) mqtt_mock.async_publish.reset_mock() state = hass.states.get("fan.test") - assert state.attributes.get(fan.ATTR_PRESET_MODE) == "freaking-high" + assert state.attributes.get(fan.ATTR_PRESET_MODE) == "breeze" assert state.attributes.get(ATTR_ASSUMED_STATE) await common.async_set_preset_mode(hass, "fan.test", "silent") @@ -825,12 +793,9 @@ async def test_sending_mqtt_commands_and_optimistic_no_legacy(hass, mqtt_mock, c assert state.attributes.get(ATTR_ASSUMED_STATE) await common.async_turn_on(hass, "fan.test", percentage=25) - assert mqtt_mock.async_publish.call_count == 3 + 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("percentage-command-topic", "25", 0, False) - mqtt_mock.async_publish.assert_any_call( - "preset-mode-command-topic", "high", 0, False - ) mqtt_mock.async_publish.reset_mock() state = hass.states.get("fan.test") assert state.state == STATE_ON @@ -843,11 +808,11 @@ async def test_sending_mqtt_commands_and_optimistic_no_legacy(hass, mqtt_mock, c assert state.state == STATE_OFF assert state.attributes.get(ATTR_ASSUMED_STATE) - await common.async_turn_on(hass, "fan.test", preset_mode="high") + await common.async_turn_on(hass, "fan.test", preset_mode="whoosh") 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( - "preset-mode-command-topic", "high", 0, False + "preset-mode-command-topic", "whoosh", 0, False ) mqtt_mock.async_publish.reset_mock() state = hass.states.get("fan.test") @@ -855,7 +820,7 @@ async def test_sending_mqtt_commands_and_optimistic_no_legacy(hass, mqtt_mock, c assert state.attributes.get(ATTR_ASSUMED_STATE) with pytest.raises(NotValidPresetModeError): - await common.async_turn_on(hass, "fan.test", preset_mode="low") + await common.async_turn_on(hass, "fan.test", preset_mode="freaking-high") async def test_sending_mqtt_command_templates_(hass, mqtt_mock, caplog): @@ -876,8 +841,8 @@ async def test_sending_mqtt_command_templates_(hass, mqtt_mock, caplog): "preset_mode_command_topic": "preset-mode-command-topic", "preset_mode_command_template": "preset_mode: {{ value }}", "preset_modes": [ - "high", - "freaking-high", + "whoosh", + "breeze", "silent", ], } @@ -914,16 +879,12 @@ async def test_sending_mqtt_command_templates_(hass, mqtt_mock, caplog): await common.async_set_percentage(hass, "fan.test", 101) await common.async_set_percentage(hass, "fan.test", 100) - mqtt_mock.async_publish.assert_any_call( + mqtt_mock.async_publish.assert_called_once_with( "percentage-command-topic", "percentage: 100", 0, False ) - mqtt_mock.async_publish.assert_any_call( - "preset-mode-command-topic", "preset_mode: freaking-high", 0, False - ) mqtt_mock.async_publish.reset_mock() state = hass.states.get("fan.test") assert state.attributes.get(fan.ATTR_PERCENTAGE) == 100 - assert state.attributes.get(fan.ATTR_PRESET_MODE) == "freaking-high" assert state.attributes.get(ATTR_ASSUMED_STATE) await common.async_set_percentage(hass, "fan.test", 0) @@ -944,22 +905,22 @@ async def test_sending_mqtt_command_templates_(hass, mqtt_mock, caplog): assert "not a valid preset mode" in caplog.text caplog.clear() - await common.async_set_preset_mode(hass, "fan.test", "high") + await common.async_set_preset_mode(hass, "fan.test", "whoosh") mqtt_mock.async_publish.assert_called_once_with( - "preset-mode-command-topic", "preset_mode: high", 0, False + "preset-mode-command-topic", "preset_mode: whoosh", 0, False ) mqtt_mock.async_publish.reset_mock() state = hass.states.get("fan.test") - assert state.attributes.get(fan.ATTR_PRESET_MODE) == "high" + assert state.attributes.get(fan.ATTR_PRESET_MODE) == "whoosh" assert state.attributes.get(ATTR_ASSUMED_STATE) - await common.async_set_preset_mode(hass, "fan.test", "freaking-high") + await common.async_set_preset_mode(hass, "fan.test", "breeze") mqtt_mock.async_publish.assert_called_once_with( - "preset-mode-command-topic", "preset_mode: freaking-high", 0, False + "preset-mode-command-topic", "preset_mode: breeze", 0, False ) mqtt_mock.async_publish.reset_mock() state = hass.states.get("fan.test") - assert state.attributes.get(fan.ATTR_PRESET_MODE) == "freaking-high" + assert state.attributes.get(fan.ATTR_PRESET_MODE) == "breeze" assert state.attributes.get(ATTR_ASSUMED_STATE) await common.async_set_preset_mode(hass, "fan.test", "silent") @@ -972,14 +933,11 @@ async def test_sending_mqtt_command_templates_(hass, mqtt_mock, caplog): assert state.attributes.get(ATTR_ASSUMED_STATE) await common.async_turn_on(hass, "fan.test", percentage=25) - assert mqtt_mock.async_publish.call_count == 3 + assert mqtt_mock.async_publish.call_count == 2 mqtt_mock.async_publish.assert_any_call("command-topic", "state: ON", 0, False) mqtt_mock.async_publish.assert_any_call( "percentage-command-topic", "percentage: 25", 0, False ) - mqtt_mock.async_publish.assert_any_call( - "preset-mode-command-topic", "preset_mode: high", 0, False - ) mqtt_mock.async_publish.reset_mock() state = hass.states.get("fan.test") assert state.state == STATE_ON @@ -992,11 +950,11 @@ async def test_sending_mqtt_command_templates_(hass, mqtt_mock, caplog): assert state.state == STATE_OFF assert state.attributes.get(ATTR_ASSUMED_STATE) - await common.async_turn_on(hass, "fan.test", preset_mode="high") + await common.async_turn_on(hass, "fan.test", preset_mode="whoosh") assert mqtt_mock.async_publish.call_count == 2 mqtt_mock.async_publish.assert_any_call("command-topic", "state: ON", 0, False) mqtt_mock.async_publish.assert_any_call( - "preset-mode-command-topic", "preset_mode: high", 0, False + "preset-mode-command-topic", "preset_mode: whoosh", 0, False ) mqtt_mock.async_publish.reset_mock() state = hass.states.get("fan.test") @@ -1008,7 +966,7 @@ async def test_sending_mqtt_command_templates_(hass, mqtt_mock, caplog): async def test_sending_mqtt_commands_and_optimistic_no_percentage_topic( - hass, mqtt_mock + hass, mqtt_mock, caplog ): """Test optimistic mode without state topic without percentage command topic.""" assert await async_setup_component( @@ -1027,9 +985,10 @@ async def test_sending_mqtt_commands_and_optimistic_no_percentage_topic( # use of speeds is deprecated, support will be removed after a quarter (2021.7) "speeds": ["off", "low", "medium"], "preset_modes": [ - "high", - "freaking-high", + "whoosh", + "breeze", "silent", + "high", ], } }, @@ -1047,9 +1006,7 @@ async def test_sending_mqtt_commands_and_optimistic_no_percentage_topic( await common.async_set_percentage(hass, "fan.test", 101) await common.async_set_percentage(hass, "fan.test", 100) - mqtt_mock.async_publish.assert_any_call( - "preset-mode-command-topic", "freaking-high", 0, False - ) + mqtt_mock.async_publish.assert_any_call("speed-command-topic", "medium", 0, False) mqtt_mock.async_publish.reset_mock() state = hass.states.get("fan.test") assert state.attributes.get(fan.ATTR_PERCENTAGE) == 100 @@ -1063,41 +1020,27 @@ async def test_sending_mqtt_commands_and_optimistic_no_percentage_topic( assert state.attributes.get(fan.ATTR_PERCENTAGE) == 0 assert state.attributes.get(ATTR_ASSUMED_STATE) - await common.async_set_preset_mode(hass, "fan.test", "low") - assert mqtt_mock.async_publish.call_count == 2 # use of speeds is deprecated, support will be removed after a quarter (2021.7) - mqtt_mock.async_publish.assert_any_call("speed-command-topic", "low", 0, False) - mqtt_mock.async_publish.assert_any_call( - "preset-mode-command-topic", "low", 0, False - ) - mqtt_mock.async_publish.reset_mock() - state = hass.states.get("fan.test") - assert state.attributes.get(fan.ATTR_PRESET_MODE) is None - assert state.attributes.get(ATTR_ASSUMED_STATE) + await common.async_set_preset_mode(hass, "fan.test", "low") + assert "not a valid preset mode" in caplog.text + caplog.clear() await common.async_set_preset_mode(hass, "fan.test", "medium") - assert mqtt_mock.async_publish.call_count == 2 - mqtt_mock.async_publish.assert_any_call("speed-command-topic", "medium", 0, False) - mqtt_mock.async_publish.assert_any_call( - "preset-mode-command-topic", "medium", 0, False + assert "not a valid preset mode" in caplog.text + caplog.clear() + + await common.async_set_preset_mode(hass, "fan.test", "whoosh") + mqtt_mock.async_publish.assert_called_once_with( + "preset-mode-command-topic", "whoosh", 0, False ) mqtt_mock.async_publish.reset_mock() state = hass.states.get("fan.test") assert state.attributes.get(fan.ATTR_PRESET_MODE) is None assert state.attributes.get(ATTR_ASSUMED_STATE) - await common.async_set_preset_mode(hass, "fan.test", "high") + await common.async_set_preset_mode(hass, "fan.test", "breeze") mqtt_mock.async_publish.assert_called_once_with( - "preset-mode-command-topic", "high", 0, False - ) - mqtt_mock.async_publish.reset_mock() - state = hass.states.get("fan.test") - assert state.attributes.get(fan.ATTR_PRESET_MODE) is None - assert state.attributes.get(ATTR_ASSUMED_STATE) - - await common.async_set_preset_mode(hass, "fan.test", "freaking-high") - mqtt_mock.async_publish.assert_called_once_with( - "preset-mode-command-topic", "freaking-high", 0, False + "preset-mode-command-topic", "breeze", 0, False ) mqtt_mock.async_publish.reset_mock() state = hass.states.get("fan.test") @@ -1133,14 +1076,8 @@ async def test_sending_mqtt_commands_and_optimistic_no_percentage_topic( assert state.attributes.get(ATTR_ASSUMED_STATE) await common.async_set_speed(hass, "fan.test", fan.SPEED_HIGH) - mqtt_mock.async_publish.assert_called_once_with( - "speed-command-topic", "high", 0, False - ) - mqtt_mock.async_publish.reset_mock() - state = hass.states.get("fan.test") - assert state.state == STATE_OFF - assert state.attributes.get(ATTR_ASSUMED_STATE) - + assert "not a valid speed" in caplog.text + caplog.clear() await common.async_set_speed(hass, "fan.test", fan.SPEED_OFF) mqtt_mock.async_publish.assert_any_call("speed-command-topic", "off", 0, False) @@ -1150,13 +1087,10 @@ async def test_sending_mqtt_commands_and_optimistic_no_percentage_topic( assert state.attributes.get(ATTR_ASSUMED_STATE) await common.async_turn_on(hass, "fan.test", speed="medium") - assert mqtt_mock.async_publish.call_count == 3 + assert mqtt_mock.async_publish.call_count == 2 mqtt_mock.async_publish.assert_any_call("command-topic", "ON", 0, False) # use of speeds is deprecated, support will be removed after a quarter (2021.7) mqtt_mock.async_publish.assert_any_call("speed-command-topic", "medium", 0, False) - mqtt_mock.async_publish.assert_any_call( - "preset-mode-command-topic", "medium", 0, False - ) mqtt_mock.async_publish.reset_mock() state = hass.states.get("fan.test") assert state.state == STATE_ON @@ -1325,8 +1259,8 @@ async def test_sending_mqtt_commands_and_explicit_optimistic(hass, mqtt_mock, ca # use of speeds is deprecated, support will be removed after a quarter (2021.7) "speeds": ["off", "low", "medium"], "preset_modes": [ - "high", - "freaking-high", + "whoosh", + "breeze", "silent", ], "optimistic": True, @@ -1358,9 +1292,7 @@ async def test_sending_mqtt_commands_and_explicit_optimistic(hass, mqtt_mock, ca mqtt_mock.async_publish.assert_any_call("command-topic", "ON", 0, False) # use of speeds is deprecated, support will be removed after a quarter (2021.7) mqtt_mock.async_publish.assert_any_call("speed-command-topic", "medium", 0, False) - mqtt_mock.async_publish.assert_any_call( - "preset-mode-command-topic", "medium", 0, False - ) + mqtt_mock.async_publish.assert_any_call("percentage-command-topic", "100", 0, False) mqtt_mock.async_publish.reset_mock() state = hass.states.get("fan.test") assert state.state == STATE_ON @@ -1374,11 +1306,8 @@ async def test_sending_mqtt_commands_and_explicit_optimistic(hass, mqtt_mock, ca assert state.attributes.get(ATTR_ASSUMED_STATE) await common.async_turn_on(hass, "fan.test", percentage=25) - assert mqtt_mock.async_publish.call_count == 4 + assert mqtt_mock.async_publish.call_count == 3 mqtt_mock.async_publish.assert_any_call("command-topic", "ON", 0, False) - mqtt_mock.async_publish.assert_any_call( - "preset-mode-command-topic", "low", 0, False - ) mqtt_mock.async_publish.assert_any_call("percentage-command-topic", "25", 0, False) # use of speeds is deprecated, support will be removed after a quarter (2021.7) mqtt_mock.async_publish.assert_any_call("speed-command-topic", "low", 0, False) @@ -1394,24 +1323,15 @@ async def test_sending_mqtt_commands_and_explicit_optimistic(hass, mqtt_mock, ca assert state.state == STATE_OFF assert state.attributes.get(ATTR_ASSUMED_STATE) - await common.async_turn_on(hass, "fan.test", preset_mode="medium") - assert mqtt_mock.async_publish.call_count == 3 - mqtt_mock.async_publish.assert_any_call("command-topic", "ON", 0, False) - mqtt_mock.async_publish.assert_any_call( - "preset-mode-command-topic", "medium", 0, False - ) # use of speeds is deprecated, support will be removed after a quarter (2021.7) - mqtt_mock.async_publish.assert_any_call("speed-command-topic", "medium", 0, False) - mqtt_mock.async_publish.reset_mock() - state = hass.states.get("fan.test") - assert state.state == STATE_ON - assert state.attributes.get(ATTR_ASSUMED_STATE) + with pytest.raises(NotValidPresetModeError): + await common.async_turn_on(hass, "fan.test", preset_mode="auto") - await common.async_turn_on(hass, "fan.test", preset_mode="high") + await common.async_turn_on(hass, "fan.test", preset_mode="whoosh") 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( - "preset-mode-command-topic", "high", 0, False + "preset-mode-command-topic", "whoosh", 0, False ) mqtt_mock.async_publish.reset_mock() state = hass.states.get("fan.test") @@ -1471,14 +1391,11 @@ async def test_sending_mqtt_commands_and_explicit_optimistic(hass, mqtt_mock, ca assert state.attributes.get(ATTR_ASSUMED_STATE) await common.async_turn_on(hass, "fan.test", percentage=50) - assert mqtt_mock.async_publish.call_count == 4 + assert mqtt_mock.async_publish.call_count == 3 mqtt_mock.async_publish.assert_any_call("command-topic", "ON", 0, False) mqtt_mock.async_publish.assert_any_call("percentage-command-topic", "50", 0, False) - mqtt_mock.async_publish.assert_any_call( - "preset-mode-command-topic", "medium", 0, False - ) # use of speeds is deprecated, support will be removed after a quarter (2021.7) - mqtt_mock.async_publish.assert_any_call("speed-command-topic", "medium", 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 == STATE_ON @@ -1501,26 +1418,20 @@ async def test_sending_mqtt_commands_and_explicit_optimistic(hass, mqtt_mock, ca assert state.attributes.get(ATTR_ASSUMED_STATE) await common.async_set_percentage(hass, "fan.test", 33) - assert mqtt_mock.async_publish.call_count == 3 + assert mqtt_mock.async_publish.call_count == 2 mqtt_mock.async_publish.assert_any_call("percentage-command-topic", "33", 0, False) # use of speeds is deprecated, support will be removed after a quarter (2021.7) - mqtt_mock.async_publish.assert_any_call("speed-command-topic", "medium", 0, False) - mqtt_mock.async_publish.assert_any_call( - "preset-mode-command-topic", "medium", 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 == STATE_OFF assert state.attributes.get(ATTR_ASSUMED_STATE) await common.async_set_percentage(hass, "fan.test", 50) - assert mqtt_mock.async_publish.call_count == 3 + assert mqtt_mock.async_publish.call_count == 2 mqtt_mock.async_publish.assert_any_call("percentage-command-topic", "50", 0, False) # use of speeds is deprecated, support will be removed after a quarter (2021.7) - mqtt_mock.async_publish.assert_any_call("speed-command-topic", "medium", 0, False) - mqtt_mock.async_publish.assert_any_call( - "preset-mode-command-topic", "medium", 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 == STATE_OFF @@ -1529,22 +1440,18 @@ async def test_sending_mqtt_commands_and_explicit_optimistic(hass, mqtt_mock, ca await common.async_set_percentage(hass, "fan.test", 100) assert mqtt_mock.async_publish.call_count == 2 mqtt_mock.async_publish.assert_any_call("percentage-command-topic", "100", 0, False) - mqtt_mock.async_publish.assert_any_call( - "preset-mode-command-topic", "freaking-high", 0, False - ) + # use of speeds is deprecated, support will be removed after a quarter (2021.7) + mqtt_mock.async_publish.assert_any_call("speed-command-topic", "medium", 0, False) mqtt_mock.async_publish.reset_mock() state = hass.states.get("fan.test") assert state.state == STATE_OFF assert state.attributes.get(ATTR_ASSUMED_STATE) await common.async_set_percentage(hass, "fan.test", 0) - assert mqtt_mock.async_publish.call_count == 3 + assert mqtt_mock.async_publish.call_count == 2 mqtt_mock.async_publish.assert_any_call("percentage-command-topic", "0", 0, False) # use of speeds is deprecated, support will be removed after a quarter (2021.7) mqtt_mock.async_publish.assert_any_call("speed-command-topic", "off", 0, False) - mqtt_mock.async_publish.assert_any_call( - "preset-mode-command-topic", "off", 0, False - ) mqtt_mock.async_publish.reset_mock() state = hass.states.get("fan.test") assert state.state == STATE_OFF @@ -1554,32 +1461,16 @@ async def test_sending_mqtt_commands_and_explicit_optimistic(hass, mqtt_mock, ca await common.async_set_percentage(hass, "fan.test", 101) await common.async_set_preset_mode(hass, "fan.test", "low") - assert mqtt_mock.async_publish.call_count == 2 - # use of speeds is deprecated, support will be removed after a quarter (2021.7) - mqtt_mock.async_publish.assert_any_call("speed-command-topic", "low", 0, False) - mqtt_mock.async_publish.assert_any_call( - "preset-mode-command-topic", "low", 0, False - ) - mqtt_mock.async_publish.reset_mock() - state = hass.states.get("fan.test") - assert state.state == STATE_OFF - assert state.attributes.get(ATTR_ASSUMED_STATE) + assert "not a valid preset mode" in caplog.text + caplog.clear() await common.async_set_preset_mode(hass, "fan.test", "medium") - assert mqtt_mock.async_publish.call_count == 2 - # use of speeds is deprecated, support will be removed after a quarter (2021.7) - mqtt_mock.async_publish.assert_any_call("speed-command-topic", "medium", 0, False) - mqtt_mock.async_publish.assert_any_call( - "preset-mode-command-topic", "medium", 0, False - ) - mqtt_mock.async_publish.reset_mock() - state = hass.states.get("fan.test") - assert state.state == STATE_OFF - assert state.attributes.get(ATTR_ASSUMED_STATE) + assert "not a valid preset mode" in caplog.text + caplog.clear() - await common.async_set_preset_mode(hass, "fan.test", "high") + await common.async_set_preset_mode(hass, "fan.test", "whoosh") mqtt_mock.async_publish.assert_called_once_with( - "preset-mode-command-topic", "high", 0, False + "preset-mode-command-topic", "whoosh", 0, False ) mqtt_mock.async_publish.reset_mock() state = hass.states.get("fan.test") @@ -1595,7 +1486,7 @@ async def test_sending_mqtt_commands_and_explicit_optimistic(hass, mqtt_mock, ca assert state.state == STATE_OFF assert state.attributes.get(ATTR_ASSUMED_STATE) - await common.async_set_preset_mode(hass, "fan.test", "ModeX") + await common.async_set_preset_mode(hass, "fan.test", "freaking-high") assert "not a valid preset mode" in caplog.text caplog.clear() @@ -1615,13 +1506,8 @@ async def test_sending_mqtt_commands_and_explicit_optimistic(hass, mqtt_mock, ca assert state.attributes.get(ATTR_ASSUMED_STATE) await common.async_set_speed(hass, "fan.test", fan.SPEED_HIGH) - mqtt_mock.async_publish.assert_called_once_with( - "speed-command-topic", "high", 0, False - ) - mqtt_mock.async_publish.reset_mock() - state = hass.states.get("fan.test") - assert state.state == STATE_OFF - assert state.attributes.get(ATTR_ASSUMED_STATE) + assert "not a valid speed" in caplog.text + caplog.clear() await common.async_set_speed(hass, "fan.test", fan.SPEED_OFF) mqtt_mock.async_publish.assert_called_once_with( @@ -1653,7 +1539,7 @@ async def test_attributes(hass, mqtt_mock, caplog): "preset_mode_command_topic": "preset-mode-command-topic", "percentage_command_topic": "percentage-command-topic", "preset_modes": [ - "freaking-high", + "breeze", "silent", ], } @@ -1667,7 +1553,6 @@ async def test_attributes(hass, mqtt_mock, caplog): "low", "medium", "high", - "freaking-high", ] await common.async_turn_on(hass, "fan.test") @@ -1821,14 +1706,14 @@ async def test_supported_features(hass, mqtt_mock): "name": "test3c2", "command_topic": "command-topic", "preset_mode_command_topic": "preset-mode-command-topic", - "preset_modes": ["very-fast", "auto"], + "preset_modes": ["eco", "auto"], }, { "platform": "mqtt", "name": "test3c3", "command_topic": "command-topic", "preset_mode_command_topic": "preset-mode-command-topic", - "preset_modes": ["off", "on", "auto"], + "preset_modes": ["eco", "smart", "auto"], }, { "platform": "mqtt", @@ -1863,7 +1748,7 @@ async def test_supported_features(hass, mqtt_mock): "name": "test5pr_mb", "command_topic": "command-topic", "preset_mode_command_topic": "preset-mode-command-topic", - "preset_modes": ["off", "on", "auto"], + "preset_modes": ["whoosh", "silent", "auto"], }, { "platform": "mqtt", @@ -1927,10 +1812,7 @@ async def test_supported_features(hass, mqtt_mock): assert state is None state = hass.states.get("fan.test3c2") - assert ( - state.attributes.get(ATTR_SUPPORTED_FEATURES) - == fan.SUPPORT_PRESET_MODE | fan.SUPPORT_SET_SPEED - ) + assert state.attributes.get(ATTR_SUPPORTED_FEATURES) == fan.SUPPORT_PRESET_MODE state = hass.states.get("fan.test3c3") assert state.attributes.get(ATTR_SUPPORTED_FEATURES) == fan.SUPPORT_PRESET_MODE @@ -1949,21 +1831,19 @@ async def test_supported_features(hass, mqtt_mock): ) state = hass.states.get("fan.test5pr_ma") - assert ( - state.attributes.get(ATTR_SUPPORTED_FEATURES) - == fan.SUPPORT_SET_SPEED | fan.SUPPORT_PRESET_MODE - ) + assert state.attributes.get(ATTR_SUPPORTED_FEATURES) == fan.SUPPORT_PRESET_MODE state = hass.states.get("fan.test5pr_mb") assert state.attributes.get(ATTR_SUPPORTED_FEATURES) == fan.SUPPORT_PRESET_MODE state = hass.states.get("fan.test5pr_mc") assert ( state.attributes.get(ATTR_SUPPORTED_FEATURES) - == fan.SUPPORT_OSCILLATE | fan.SUPPORT_SET_SPEED | fan.SUPPORT_PRESET_MODE + == fan.SUPPORT_OSCILLATE | fan.SUPPORT_PRESET_MODE ) state = hass.states.get("fan.test6spd_range_a") assert state.attributes.get(ATTR_SUPPORTED_FEATURES) == fan.SUPPORT_SET_SPEED + assert state.attributes.get("percentage_step") == 2.5 state = hass.states.get("fan.test6spd_range_b") assert state is None state = hass.states.get("fan.test6spd_range_c") diff --git a/tests/components/ping/test_init.py b/tests/components/ping/test_init.py new file mode 100644 index 00000000000..3dfe193c4d5 --- /dev/null +++ b/tests/components/ping/test_init.py @@ -0,0 +1,27 @@ +"""Test ping id allocation.""" + +from homeassistant.components.ping import async_get_next_ping_id +from homeassistant.components.ping.const import ( + DEFAULT_START_ID, + DOMAIN, + MAX_PING_ID, + PING_ID, +) + + +async def test_async_get_next_ping_id(hass): + """Verify we allocate ping ids as expected.""" + hass.data[DOMAIN] = {PING_ID: DEFAULT_START_ID} + + assert async_get_next_ping_id(hass) == DEFAULT_START_ID + 1 + assert async_get_next_ping_id(hass) == DEFAULT_START_ID + 2 + assert async_get_next_ping_id(hass, 2) == DEFAULT_START_ID + 3 + assert async_get_next_ping_id(hass) == DEFAULT_START_ID + 5 + + hass.data[DOMAIN][PING_ID] = MAX_PING_ID + assert async_get_next_ping_id(hass) == DEFAULT_START_ID + 1 + assert async_get_next_ping_id(hass) == DEFAULT_START_ID + 2 + + hass.data[DOMAIN][PING_ID] = MAX_PING_ID + assert async_get_next_ping_id(hass, 2) == DEFAULT_START_ID + 1 + assert async_get_next_ping_id(hass) == DEFAULT_START_ID + 3 diff --git a/tests/components/shelly/test_device_trigger.py b/tests/components/shelly/test_device_trigger.py index a725f5a1f30..bedf4abc0f2 100644 --- a/tests/components/shelly/test_device_trigger.py +++ b/tests/components/shelly/test_device_trigger.py @@ -1,4 +1,6 @@ """The tests for Shelly device triggers.""" +from unittest.mock import AsyncMock, Mock + import pytest from homeassistant import setup @@ -6,10 +8,13 @@ from homeassistant.components import automation from homeassistant.components.device_automation.exceptions import ( InvalidDeviceAutomationConfig, ) +from homeassistant.components.shelly import ShellyDeviceWrapper from homeassistant.components.shelly.const import ( ATTR_CHANNEL, ATTR_CLICK_TYPE, + COAP, CONF_SUBTYPE, + DATA_CONFIG_ENTRY, DOMAIN, EVENT_SHELLY_CLICK, ) @@ -52,6 +57,71 @@ async def test_get_triggers(hass, coap_wrapper): assert_lists_same(triggers, expected_triggers) +async def test_get_triggers_button(hass): + """Test we get the expected triggers from a shelly button.""" + await async_setup_component(hass, "shelly", {}) + + config_entry = MockConfigEntry( + domain=DOMAIN, + data={"sleep_period": 43200, "model": "SHBTN-1"}, + unique_id="12345678", + ) + config_entry.add_to_hass(hass) + + device = Mock( + blocks=None, + settings=None, + shelly=None, + update=AsyncMock(), + initialized=False, + ) + + hass.data[DOMAIN] = {DATA_CONFIG_ENTRY: {}} + hass.data[DOMAIN][DATA_CONFIG_ENTRY][config_entry.entry_id] = {} + coap_wrapper = hass.data[DOMAIN][DATA_CONFIG_ENTRY][config_entry.entry_id][ + COAP + ] = ShellyDeviceWrapper(hass, config_entry, device) + + await coap_wrapper.async_setup() + + expected_triggers = [ + { + CONF_PLATFORM: "device", + CONF_DEVICE_ID: coap_wrapper.device_id, + CONF_DOMAIN: DOMAIN, + CONF_TYPE: "single", + CONF_SUBTYPE: "button", + }, + { + CONF_PLATFORM: "device", + CONF_DEVICE_ID: coap_wrapper.device_id, + CONF_DOMAIN: DOMAIN, + CONF_TYPE: "double", + CONF_SUBTYPE: "button", + }, + { + CONF_PLATFORM: "device", + CONF_DEVICE_ID: coap_wrapper.device_id, + CONF_DOMAIN: DOMAIN, + CONF_TYPE: "triple", + CONF_SUBTYPE: "button", + }, + { + CONF_PLATFORM: "device", + CONF_DEVICE_ID: coap_wrapper.device_id, + CONF_DOMAIN: DOMAIN, + CONF_TYPE: "long", + CONF_SUBTYPE: "button", + }, + ] + + triggers = await async_get_device_automations( + hass, "trigger", coap_wrapper.device_id + ) + + assert_lists_same(triggers, expected_triggers) + + async def test_get_triggers_for_invalid_device_id(hass, device_reg, coap_wrapper): """Test error raised for invalid shelly device_id.""" assert coap_wrapper diff --git a/tests/components/tts/test_init.py b/tests/components/tts/test_init.py index 77fbd3f7170..8cd1641caa0 100644 --- a/tests/components/tts/test_init.py +++ b/tests/components/tts/test_init.py @@ -102,6 +102,7 @@ async def test_setup_component_demo(hass): assert hass.services.has_service(tts.DOMAIN, "demo_say") assert hass.services.has_service(tts.DOMAIN, "clear_cache") + assert f"{tts.DOMAIN}.demo" in hass.config.components async def test_setup_component_demo_no_access_cache_folder(hass, mock_init_cache_dir):