mirror of
https://github.com/home-assistant/core.git
synced 2025-07-19 11:17:21 +00:00
Add floor lamp and strip light 3 for switchbot integration (#147517)
This commit is contained in:
parent
e210681751
commit
c05d8aab1c
@ -93,6 +93,8 @@ PLATFORMS_BY_TYPE = {
|
|||||||
SupportedModels.AIR_PURIFIER.value: [Platform.FAN, Platform.SENSOR],
|
SupportedModels.AIR_PURIFIER.value: [Platform.FAN, Platform.SENSOR],
|
||||||
SupportedModels.AIR_PURIFIER_TABLE.value: [Platform.FAN, Platform.SENSOR],
|
SupportedModels.AIR_PURIFIER_TABLE.value: [Platform.FAN, Platform.SENSOR],
|
||||||
SupportedModels.EVAPORATIVE_HUMIDIFIER: [Platform.HUMIDIFIER, Platform.SENSOR],
|
SupportedModels.EVAPORATIVE_HUMIDIFIER: [Platform.HUMIDIFIER, Platform.SENSOR],
|
||||||
|
SupportedModels.FLOOR_LAMP.value: [Platform.LIGHT, Platform.SENSOR],
|
||||||
|
SupportedModels.STRIP_LIGHT_3.value: [Platform.LIGHT, Platform.SENSOR],
|
||||||
}
|
}
|
||||||
CLASS_BY_DEVICE = {
|
CLASS_BY_DEVICE = {
|
||||||
SupportedModels.CEILING_LIGHT.value: switchbot.SwitchbotCeilingLight,
|
SupportedModels.CEILING_LIGHT.value: switchbot.SwitchbotCeilingLight,
|
||||||
@ -119,6 +121,8 @@ CLASS_BY_DEVICE = {
|
|||||||
SupportedModels.AIR_PURIFIER.value: switchbot.SwitchbotAirPurifier,
|
SupportedModels.AIR_PURIFIER.value: switchbot.SwitchbotAirPurifier,
|
||||||
SupportedModels.AIR_PURIFIER_TABLE.value: switchbot.SwitchbotAirPurifier,
|
SupportedModels.AIR_PURIFIER_TABLE.value: switchbot.SwitchbotAirPurifier,
|
||||||
SupportedModels.EVAPORATIVE_HUMIDIFIER: switchbot.SwitchbotEvaporativeHumidifier,
|
SupportedModels.EVAPORATIVE_HUMIDIFIER: switchbot.SwitchbotEvaporativeHumidifier,
|
||||||
|
SupportedModels.FLOOR_LAMP.value: switchbot.SwitchbotStripLight3,
|
||||||
|
SupportedModels.STRIP_LIGHT_3.value: switchbot.SwitchbotStripLight3,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -49,6 +49,8 @@ class SupportedModels(StrEnum):
|
|||||||
AIR_PURIFIER = "air_purifier"
|
AIR_PURIFIER = "air_purifier"
|
||||||
AIR_PURIFIER_TABLE = "air_purifier_table"
|
AIR_PURIFIER_TABLE = "air_purifier_table"
|
||||||
EVAPORATIVE_HUMIDIFIER = "evaporative_humidifier"
|
EVAPORATIVE_HUMIDIFIER = "evaporative_humidifier"
|
||||||
|
FLOOR_LAMP = "floor_lamp"
|
||||||
|
STRIP_LIGHT_3 = "strip_light_3"
|
||||||
|
|
||||||
|
|
||||||
CONNECTABLE_SUPPORTED_MODEL_TYPES = {
|
CONNECTABLE_SUPPORTED_MODEL_TYPES = {
|
||||||
@ -77,6 +79,8 @@ CONNECTABLE_SUPPORTED_MODEL_TYPES = {
|
|||||||
SwitchbotModel.AIR_PURIFIER: SupportedModels.AIR_PURIFIER,
|
SwitchbotModel.AIR_PURIFIER: SupportedModels.AIR_PURIFIER,
|
||||||
SwitchbotModel.AIR_PURIFIER_TABLE: SupportedModels.AIR_PURIFIER_TABLE,
|
SwitchbotModel.AIR_PURIFIER_TABLE: SupportedModels.AIR_PURIFIER_TABLE,
|
||||||
SwitchbotModel.EVAPORATIVE_HUMIDIFIER: SupportedModels.EVAPORATIVE_HUMIDIFIER,
|
SwitchbotModel.EVAPORATIVE_HUMIDIFIER: SupportedModels.EVAPORATIVE_HUMIDIFIER,
|
||||||
|
SwitchbotModel.FLOOR_LAMP: SupportedModels.FLOOR_LAMP,
|
||||||
|
SwitchbotModel.STRIP_LIGHT_3: SupportedModels.STRIP_LIGHT_3,
|
||||||
}
|
}
|
||||||
|
|
||||||
NON_CONNECTABLE_SUPPORTED_MODEL_TYPES = {
|
NON_CONNECTABLE_SUPPORTED_MODEL_TYPES = {
|
||||||
@ -106,6 +110,8 @@ ENCRYPTED_MODELS = {
|
|||||||
SwitchbotModel.AIR_PURIFIER,
|
SwitchbotModel.AIR_PURIFIER,
|
||||||
SwitchbotModel.AIR_PURIFIER_TABLE,
|
SwitchbotModel.AIR_PURIFIER_TABLE,
|
||||||
SwitchbotModel.EVAPORATIVE_HUMIDIFIER,
|
SwitchbotModel.EVAPORATIVE_HUMIDIFIER,
|
||||||
|
SwitchbotModel.FLOOR_LAMP,
|
||||||
|
SwitchbotModel.STRIP_LIGHT_3,
|
||||||
}
|
}
|
||||||
|
|
||||||
ENCRYPTED_SWITCHBOT_MODEL_TO_CLASS: dict[
|
ENCRYPTED_SWITCHBOT_MODEL_TO_CLASS: dict[
|
||||||
@ -120,6 +126,8 @@ ENCRYPTED_SWITCHBOT_MODEL_TO_CLASS: dict[
|
|||||||
SwitchbotModel.AIR_PURIFIER: switchbot.SwitchbotAirPurifier,
|
SwitchbotModel.AIR_PURIFIER: switchbot.SwitchbotAirPurifier,
|
||||||
SwitchbotModel.AIR_PURIFIER_TABLE: switchbot.SwitchbotAirPurifier,
|
SwitchbotModel.AIR_PURIFIER_TABLE: switchbot.SwitchbotAirPurifier,
|
||||||
SwitchbotModel.EVAPORATIVE_HUMIDIFIER: switchbot.SwitchbotEvaporativeHumidifier,
|
SwitchbotModel.EVAPORATIVE_HUMIDIFIER: switchbot.SwitchbotEvaporativeHumidifier,
|
||||||
|
SwitchbotModel.FLOOR_LAMP: switchbot.SwitchbotStripLight3,
|
||||||
|
SwitchbotModel.STRIP_LIGHT_3: switchbot.SwitchbotStripLight3,
|
||||||
}
|
}
|
||||||
|
|
||||||
HASS_SENSOR_TYPE_TO_SWITCHBOT_MODEL = {
|
HASS_SENSOR_TYPE_TO_SWITCHBOT_MODEL = {
|
||||||
|
@ -941,3 +941,61 @@ CEILING_LIGHT_SERVICE_INFO = BluetoothServiceInfoBleak(
|
|||||||
connectable=True,
|
connectable=True,
|
||||||
tx_power=-127,
|
tx_power=-127,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
STRIP_LIGHT_3_SERVICE_INFO = BluetoothServiceInfoBleak(
|
||||||
|
name="Strip Light 3",
|
||||||
|
manufacturer_data={
|
||||||
|
2409: b'\xc0N0\xe0U\x9a\x85\x9e"\xd0\x00\x00\x00\x00\x00\x00\x12\x91\x00',
|
||||||
|
},
|
||||||
|
service_data={
|
||||||
|
"0000fd3d-0000-1000-8000-00805f9b34fb": b"\x00\x00\x00\x00\x10\xd0\xb1"
|
||||||
|
},
|
||||||
|
service_uuids=["cba20d00-224d-11e6-9fb8-0002a5d5c51b"],
|
||||||
|
address="AA:BB:CC:DD:EE:FF",
|
||||||
|
rssi=-60,
|
||||||
|
source="local",
|
||||||
|
advertisement=generate_advertisement_data(
|
||||||
|
local_name="Strip Light 3",
|
||||||
|
manufacturer_data={
|
||||||
|
2409: b'\xc0N0\xe0U\x9a\x85\x9e"\xd0\x00\x00\x00\x00\x00\x00\x12\x91\x00',
|
||||||
|
},
|
||||||
|
service_data={
|
||||||
|
"0000fd3d-0000-1000-8000-00805f9b34fb": b"\x00\x00\x00\x00\x10\xd0\xb1"
|
||||||
|
},
|
||||||
|
service_uuids=["cba20d00-224d-11e6-9fb8-0002a5d5c51b"],
|
||||||
|
),
|
||||||
|
device=generate_ble_device("AA:BB:CC:DD:EE:FF", "Strip Light 3"),
|
||||||
|
time=0,
|
||||||
|
connectable=True,
|
||||||
|
tx_power=-127,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
FLOOR_LAMP_SERVICE_INFO = BluetoothServiceInfoBleak(
|
||||||
|
name="Floor Lamp",
|
||||||
|
manufacturer_data={
|
||||||
|
2409: b'\xa0\x85\xe3e,\x06P\xaa"\xd4\x00\x00\x00\x00\x00\x00\r\x93\x00',
|
||||||
|
},
|
||||||
|
service_data={
|
||||||
|
"0000fd3d-0000-1000-8000-00805f9b34fb": b"\x00\x00\x00\x00\x10\xd0\xb0"
|
||||||
|
},
|
||||||
|
service_uuids=["cba20d00-224d-11e6-9fb8-0002a5d5c51b"],
|
||||||
|
address="AA:BB:CC:DD:EE:FF",
|
||||||
|
rssi=-60,
|
||||||
|
source="local",
|
||||||
|
advertisement=generate_advertisement_data(
|
||||||
|
local_name="Floor Lamp",
|
||||||
|
manufacturer_data={
|
||||||
|
2409: b'\xa0\x85\xe3e,\x06P\xaa"\xd4\x00\x00\x00\x00\x00\x00\r\x93\x00',
|
||||||
|
},
|
||||||
|
service_data={
|
||||||
|
"0000fd3d-0000-1000-8000-00805f9b34fb": b"\x00\x00\x00\x00\x10\xd0\xb0"
|
||||||
|
},
|
||||||
|
service_uuids=["cba20d00-224d-11e6-9fb8-0002a5d5c51b"],
|
||||||
|
),
|
||||||
|
device=generate_ble_device("AA:BB:CC:DD:EE:FF", "Floor Lamp"),
|
||||||
|
time=0,
|
||||||
|
connectable=True,
|
||||||
|
tx_power=-127,
|
||||||
|
)
|
||||||
|
@ -7,6 +7,7 @@ from unittest.mock import AsyncMock, patch
|
|||||||
import pytest
|
import pytest
|
||||||
from switchbot.devices.device import SwitchbotOperationError
|
from switchbot.devices.device import SwitchbotOperationError
|
||||||
|
|
||||||
|
from homeassistant.components.bluetooth import BluetoothServiceInfoBleak
|
||||||
from homeassistant.components.light import (
|
from homeassistant.components.light import (
|
||||||
ATTR_BRIGHTNESS,
|
ATTR_BRIGHTNESS,
|
||||||
ATTR_COLOR_TEMP_KELVIN,
|
ATTR_COLOR_TEMP_KELVIN,
|
||||||
@ -20,7 +21,13 @@ from homeassistant.const import ATTR_ENTITY_ID
|
|||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant
|
||||||
from homeassistant.exceptions import HomeAssistantError
|
from homeassistant.exceptions import HomeAssistantError
|
||||||
|
|
||||||
from . import BULB_SERVICE_INFO, CEILING_LIGHT_SERVICE_INFO, WOSTRIP_SERVICE_INFO
|
from . import (
|
||||||
|
BULB_SERVICE_INFO,
|
||||||
|
CEILING_LIGHT_SERVICE_INFO,
|
||||||
|
FLOOR_LAMP_SERVICE_INFO,
|
||||||
|
STRIP_LIGHT_3_SERVICE_INFO,
|
||||||
|
WOSTRIP_SERVICE_INFO,
|
||||||
|
)
|
||||||
|
|
||||||
from tests.common import MockConfigEntry
|
from tests.common import MockConfigEntry
|
||||||
from tests.components.bluetooth import inject_bluetooth_service_info
|
from tests.components.bluetooth import inject_bluetooth_service_info
|
||||||
@ -71,9 +78,9 @@ BULB_PARAMETERS = (
|
|||||||
SET_COLOR_TEMP_PARAMETERS,
|
SET_COLOR_TEMP_PARAMETERS,
|
||||||
(
|
(
|
||||||
SERVICE_TURN_ON,
|
SERVICE_TURN_ON,
|
||||||
{ATTR_EFFECT: "Breathing"},
|
{ATTR_EFFECT: "breathing"},
|
||||||
"set_effect",
|
"set_effect",
|
||||||
("Breathing",),
|
("breathing",),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
@ -95,9 +102,25 @@ STRIP_LIGHT_PARAMETERS = (
|
|||||||
SET_RGB_PARAMETERS,
|
SET_RGB_PARAMETERS,
|
||||||
(
|
(
|
||||||
SERVICE_TURN_ON,
|
SERVICE_TURN_ON,
|
||||||
{ATTR_EFFECT: "Halloween"},
|
{ATTR_EFFECT: "halloween"},
|
||||||
"set_effect",
|
"set_effect",
|
||||||
("Halloween",),
|
("halloween",),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
FLOOR_LAMP_PARAMETERS = (
|
||||||
|
COMMON_PARAMETERS,
|
||||||
|
[
|
||||||
|
TURN_ON_PARAMETERS,
|
||||||
|
TURN_OFF_PARAMETERS,
|
||||||
|
SET_BRIGHTNESS_PARAMETERS,
|
||||||
|
SET_RGB_PARAMETERS,
|
||||||
|
SET_COLOR_TEMP_PARAMETERS,
|
||||||
|
(
|
||||||
|
SERVICE_TURN_ON,
|
||||||
|
{ATTR_EFFECT: "halloween"},
|
||||||
|
"set_effect",
|
||||||
|
("halloween",),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
@ -317,3 +340,91 @@ async def test_strip_light_services_exception(
|
|||||||
{**service_data, ATTR_ENTITY_ID: entity_id},
|
{**service_data, ATTR_ENTITY_ID: entity_id},
|
||||||
blocking=True,
|
blocking=True,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
("sensor_type", "service_info"),
|
||||||
|
[
|
||||||
|
("strip_light_3", STRIP_LIGHT_3_SERVICE_INFO),
|
||||||
|
("floor_lamp", FLOOR_LAMP_SERVICE_INFO),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
@pytest.mark.parametrize(*FLOOR_LAMP_PARAMETERS)
|
||||||
|
async def test_floor_lamp_services(
|
||||||
|
hass: HomeAssistant,
|
||||||
|
mock_entry_encrypted_factory: Callable[[str], MockConfigEntry],
|
||||||
|
sensor_type: str,
|
||||||
|
service_info: BluetoothServiceInfoBleak,
|
||||||
|
service: str,
|
||||||
|
service_data: dict,
|
||||||
|
mock_method: str,
|
||||||
|
expected_args: Any,
|
||||||
|
) -> None:
|
||||||
|
"""Test all SwitchBot floor lamp services."""
|
||||||
|
inject_bluetooth_service_info(hass, service_info)
|
||||||
|
|
||||||
|
entry = mock_entry_encrypted_factory(sensor_type=sensor_type)
|
||||||
|
entry.add_to_hass(hass)
|
||||||
|
entity_id = "light.test_name"
|
||||||
|
|
||||||
|
mocked_instance = AsyncMock(return_value=True)
|
||||||
|
|
||||||
|
with patch.multiple(
|
||||||
|
"homeassistant.components.switchbot.light.switchbot.SwitchbotStripLight3",
|
||||||
|
**{mock_method: mocked_instance},
|
||||||
|
update=AsyncMock(return_value=None),
|
||||||
|
):
|
||||||
|
assert await hass.config_entries.async_setup(entry.entry_id)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
await hass.services.async_call(
|
||||||
|
LIGHT_DOMAIN,
|
||||||
|
service,
|
||||||
|
{**service_data, ATTR_ENTITY_ID: entity_id},
|
||||||
|
blocking=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
mocked_instance.assert_awaited_once_with(*expected_args)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(
|
||||||
|
("sensor_type", "service_info"),
|
||||||
|
[
|
||||||
|
("strip_light_3", STRIP_LIGHT_3_SERVICE_INFO),
|
||||||
|
("floor_lamp", FLOOR_LAMP_SERVICE_INFO),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
@pytest.mark.parametrize(*FLOOR_LAMP_PARAMETERS)
|
||||||
|
async def test_floor_lamp_services_exception(
|
||||||
|
hass: HomeAssistant,
|
||||||
|
mock_entry_encrypted_factory: Callable[[str], MockConfigEntry],
|
||||||
|
sensor_type: str,
|
||||||
|
service_info: BluetoothServiceInfoBleak,
|
||||||
|
service: str,
|
||||||
|
service_data: dict,
|
||||||
|
mock_method: str,
|
||||||
|
expected_args: Any,
|
||||||
|
) -> None:
|
||||||
|
"""Test all SwitchBot floor lamp services with exception."""
|
||||||
|
inject_bluetooth_service_info(hass, service_info)
|
||||||
|
|
||||||
|
entry = mock_entry_encrypted_factory(sensor_type=sensor_type)
|
||||||
|
entry.add_to_hass(hass)
|
||||||
|
entity_id = "light.test_name"
|
||||||
|
exception = SwitchbotOperationError("Operation failed")
|
||||||
|
error_message = "An error occurred while performing the action: Operation failed"
|
||||||
|
with patch.multiple(
|
||||||
|
"homeassistant.components.switchbot.light.switchbot.SwitchbotStripLight3",
|
||||||
|
**{mock_method: AsyncMock(side_effect=exception)},
|
||||||
|
update=AsyncMock(return_value=None),
|
||||||
|
):
|
||||||
|
assert await hass.config_entries.async_setup(entry.entry_id)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
with pytest.raises(HomeAssistantError, match=error_message):
|
||||||
|
await hass.services.async_call(
|
||||||
|
LIGHT_DOMAIN,
|
||||||
|
service,
|
||||||
|
{**service_data, ATTR_ENTITY_ID: entity_id},
|
||||||
|
blocking=True,
|
||||||
|
)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user