diff --git a/homeassistant/components/switchbot/__init__.py b/homeassistant/components/switchbot/__init__.py index 3b28c3d6dcee..6a0c1ef2f0c5 100644 --- a/homeassistant/components/switchbot/__init__.py +++ b/homeassistant/components/switchbot/__init__.py @@ -96,6 +96,7 @@ PLATFORMS_BY_TYPE = { ], SupportedModels.HUBMINI_MATTER.value: [Platform.SENSOR], SupportedModels.CIRCULATOR_FAN.value: [Platform.FAN, Platform.SENSOR], + SupportedModels.STANDING_FAN.value: [Platform.SENSOR], SupportedModels.S10_VACUUM.value: [Platform.VACUUM, Platform.SENSOR], SupportedModels.S20_VACUUM.value: [Platform.VACUUM, Platform.SENSOR], SupportedModels.K10_VACUUM.value: [Platform.VACUUM, Platform.SENSOR], @@ -207,6 +208,7 @@ CLASS_BY_DEVICE = { SupportedModels.RELAY_SWITCH_1.value: switchbot.SwitchbotRelaySwitch, SupportedModels.ROLLER_SHADE.value: switchbot.SwitchbotRollerShade, SupportedModels.CIRCULATOR_FAN.value: switchbot.SwitchbotFan, + SupportedModels.STANDING_FAN.value: switchbot.SwitchbotStandingFan, SupportedModels.S10_VACUUM.value: switchbot.SwitchbotVacuum, SupportedModels.S20_VACUUM.value: switchbot.SwitchbotVacuum, SupportedModels.K10_VACUUM.value: switchbot.SwitchbotVacuum, diff --git a/homeassistant/components/switchbot/const.py b/homeassistant/components/switchbot/const.py index 30293f359dff..6221bc22fdf7 100644 --- a/homeassistant/components/switchbot/const.py +++ b/homeassistant/components/switchbot/const.py @@ -71,6 +71,7 @@ class SupportedModels(StrEnum): LOCK_VISION = "lock_vision" LOCK_PRO_WIFI = "lock_pro_wifi" WEATHER_STATION = "weather_station" + STANDING_FAN = "standing_fan" CONNECTABLE_SUPPORTED_MODEL_TYPES = { @@ -120,6 +121,7 @@ CONNECTABLE_SUPPORTED_MODEL_TYPES = { SwitchbotModel.LOCK_VISION_PRO: SupportedModels.LOCK_VISION_PRO, SwitchbotModel.LOCK_VISION: SupportedModels.LOCK_VISION, SwitchbotModel.LOCK_PRO_WIFI: SupportedModels.LOCK_PRO_WIFI, + SwitchbotModel.STANDING_FAN: SupportedModels.STANDING_FAN, } NON_CONNECTABLE_SUPPORTED_MODEL_TYPES = { diff --git a/tests/components/switchbot/__init__.py b/tests/components/switchbot/__init__.py index a411fdc32011..ad1bc8589dd4 100644 --- a/tests/components/switchbot/__init__.py +++ b/tests/components/switchbot/__init__.py @@ -1532,3 +1532,27 @@ CONTACT_SENSOR_SERVICE_INFO = BluetoothServiceInfoBleak( connectable=False, tx_power=-127, ) + +STANDING_FAN_SERVICE_INFO = BluetoothServiceInfoBleak( + name="WoStandingFan", + manufacturer_data={2409: b"\xb0\xe9\xfe\x01\x02\x03~\xd3R9"}, + service_data={ + "0000fd3d-0000-1000-8000-00805f9b34fb": b"\x00\x00\x00\x00\x11\x07\x60" + }, + service_uuids=["cba20d00-224d-11e6-9fb8-0002a5d5c51b"], + address="AA:BB:CC:DD:EE:FF", + rssi=-60, + source="local", + advertisement=generate_advertisement_data( + local_name="WoStandingFan", + manufacturer_data={2409: b"\xb0\xe9\xfe\x01\x02\x03~\xd3R9"}, + service_data={ + "0000fd3d-0000-1000-8000-00805f9b34fb": b"\x00\x00\x00\x00\x11\x07\x60" + }, + service_uuids=["cba20d00-224d-11e6-9fb8-0002a5d5c51b"], + ), + device=generate_ble_device("AA:BB:CC:DD:EE:FF", "WoStandingFan"), + time=0, + connectable=True, + tx_power=-127, +) diff --git a/tests/components/switchbot/test_init.py b/tests/components/switchbot/test_init.py index 5904fb27bf23..eef2cc3d2a28 100644 --- a/tests/components/switchbot/test_init.py +++ b/tests/components/switchbot/test_init.py @@ -4,6 +4,7 @@ from collections.abc import Callable from unittest.mock import AsyncMock, patch import pytest +import switchbot from homeassistant.components.bluetooth import BluetoothServiceInfoBleak from homeassistant.components.switchbot.const import ( @@ -26,6 +27,7 @@ from . import ( AIR_PURIFIER_US_SERVICE_INFO, HUBMINI_MATTER_SERVICE_INFO, LOCK_SERVICE_INFO, + STANDING_FAN_SERVICE_INFO, WOCURTAIN_SERVICE_INFO, WOMETERTHPC_SERVICE_INFO, WOSENSORTH_SERVICE_INFO, @@ -327,3 +329,24 @@ async def test_migrate_deprecated_air_purifier_sensor_type_device_not_in_range( # sensor_type unchanged and entry not loaded; will retry when device advertises assert entry.data[CONF_SENSOR_TYPE] == DEPRECATED_SENSOR_TYPE_AIR_PURIFIER assert entry.state is ConfigEntryState.SETUP_RETRY + + +async def test_standing_fan_setup( + hass: HomeAssistant, + mock_entry_factory: Callable[[str], MockConfigEntry], +) -> None: + """Test the Standing Fan is recognized and set up.""" + inject_bluetooth_service_info(hass, STANDING_FAN_SERVICE_INFO) + + entry = mock_entry_factory(sensor_type="standing_fan") + entry.add_to_hass(hass) + + with patch( + "homeassistant.components.switchbot.switchbot.SwitchbotStandingFan.get_basic_info", + new=AsyncMock(return_value=None), + ): + assert await hass.config_entries.async_setup(entry.entry_id) + await hass.async_block_till_done() + + assert entry.state is ConfigEntryState.LOADED + assert isinstance(entry.runtime_data.device, switchbot.SwitchbotStandingFan)