mirror of
https://github.com/home-assistant/core.git
synced 2025-07-03 19:37:10 +00:00
Add support for Bot in SwitchBot Cloud (#135606)
This commit is contained in:
parent
e822f5de6e
commit
33a2fa2c85
@ -16,6 +16,7 @@ from .coordinator import SwitchBotCoordinator
|
|||||||
|
|
||||||
_LOGGER = getLogger(__name__)
|
_LOGGER = getLogger(__name__)
|
||||||
PLATFORMS: list[Platform] = [
|
PLATFORMS: list[Platform] = [
|
||||||
|
Platform.BUTTON,
|
||||||
Platform.CLIMATE,
|
Platform.CLIMATE,
|
||||||
Platform.LOCK,
|
Platform.LOCK,
|
||||||
Platform.SENSOR,
|
Platform.SENSOR,
|
||||||
@ -28,6 +29,7 @@ PLATFORMS: list[Platform] = [
|
|||||||
class SwitchbotDevices:
|
class SwitchbotDevices:
|
||||||
"""Switchbot devices data."""
|
"""Switchbot devices data."""
|
||||||
|
|
||||||
|
buttons: list[Device] = field(default_factory=list)
|
||||||
climates: list[Remote] = field(default_factory=list)
|
climates: list[Remote] = field(default_factory=list)
|
||||||
switches: list[Device | Remote] = field(default_factory=list)
|
switches: list[Device | Remote] = field(default_factory=list)
|
||||||
sensors: list[Device] = field(default_factory=list)
|
sensors: list[Device] = field(default_factory=list)
|
||||||
@ -136,6 +138,16 @@ async def make_device_data(
|
|||||||
)
|
)
|
||||||
devices_data.locks.append((device, coordinator))
|
devices_data.locks.append((device, coordinator))
|
||||||
|
|
||||||
|
if isinstance(device, Device) and device.device_type in ["Bot"]:
|
||||||
|
coordinator = await coordinator_for_device(
|
||||||
|
hass, api, device, coordinators_by_id
|
||||||
|
)
|
||||||
|
if coordinator.data is not None:
|
||||||
|
if coordinator.data.get("deviceMode") == "pressMode":
|
||||||
|
devices_data.buttons.append((device, coordinator))
|
||||||
|
else:
|
||||||
|
devices_data.switches.append((device, coordinator))
|
||||||
|
|
||||||
|
|
||||||
async def async_setup_entry(hass: HomeAssistant, config: ConfigEntry) -> bool:
|
async def async_setup_entry(hass: HomeAssistant, config: ConfigEntry) -> bool:
|
||||||
"""Set up SwitchBot via API from a config entry."""
|
"""Set up SwitchBot via API from a config entry."""
|
||||||
|
41
homeassistant/components/switchbot_cloud/button.py
Normal file
41
homeassistant/components/switchbot_cloud/button.py
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
"""Support for the Switchbot Bot as a Button."""
|
||||||
|
|
||||||
|
from typing import Any
|
||||||
|
|
||||||
|
from switchbot_api import BotCommands
|
||||||
|
|
||||||
|
from homeassistant.components.button import ButtonEntity
|
||||||
|
from homeassistant.config_entries import ConfigEntry
|
||||||
|
from homeassistant.core import HomeAssistant, callback
|
||||||
|
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||||
|
|
||||||
|
from . import SwitchbotCloudData
|
||||||
|
from .const import DOMAIN
|
||||||
|
from .entity import SwitchBotCloudEntity
|
||||||
|
|
||||||
|
|
||||||
|
async def async_setup_entry(
|
||||||
|
hass: HomeAssistant,
|
||||||
|
config: ConfigEntry,
|
||||||
|
async_add_entities: AddEntitiesCallback,
|
||||||
|
) -> None:
|
||||||
|
"""Set up SwitchBot Cloud entry."""
|
||||||
|
data: SwitchbotCloudData = hass.data[DOMAIN][config.entry_id]
|
||||||
|
async_add_entities(
|
||||||
|
SwitchBotCloudBot(data.api, device, coordinator)
|
||||||
|
for device, coordinator in data.devices.buttons
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class SwitchBotCloudBot(SwitchBotCloudEntity, ButtonEntity):
|
||||||
|
"""Representation of a SwitchBot Bot."""
|
||||||
|
|
||||||
|
_attr_name = None
|
||||||
|
|
||||||
|
@callback
|
||||||
|
def _handle_coordinator_update(self) -> None:
|
||||||
|
"""Handle updated data from the coordinator."""
|
||||||
|
|
||||||
|
async def async_press(self, **kwargs: Any) -> None:
|
||||||
|
"""Bot press command."""
|
||||||
|
await self.send_api_command(BotCommands.PRESS)
|
@ -90,4 +90,6 @@ def _async_make_entity(
|
|||||||
"Relay Switch 1",
|
"Relay Switch 1",
|
||||||
]:
|
]:
|
||||||
return SwitchBotCloudRelaySwitchSwitch(api, device, coordinator)
|
return SwitchBotCloudRelaySwitchSwitch(api, device, coordinator)
|
||||||
|
if "Bot" in device.device_type:
|
||||||
|
return SwitchBotCloudSwitch(api, device, coordinator)
|
||||||
raise NotImplementedError(f"Unsupported device type: {device.device_type}")
|
raise NotImplementedError(f"Unsupported device type: {device.device_type}")
|
||||||
|
71
tests/components/switchbot_cloud/test_button.py
Normal file
71
tests/components/switchbot_cloud/test_button.py
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
"""Test for the switchbot_cloud bot as a button."""
|
||||||
|
|
||||||
|
from unittest.mock import patch
|
||||||
|
|
||||||
|
from switchbot_api import BotCommands, Device
|
||||||
|
|
||||||
|
from homeassistant.components.button import DOMAIN as BUTTON_DOMAIN, SERVICE_PRESS
|
||||||
|
from homeassistant.components.switchbot_cloud import SwitchBotAPI
|
||||||
|
from homeassistant.config_entries import ConfigEntryState
|
||||||
|
from homeassistant.const import ATTR_ENTITY_ID, STATE_UNKNOWN
|
||||||
|
from homeassistant.core import HomeAssistant
|
||||||
|
|
||||||
|
from . import configure_integration
|
||||||
|
|
||||||
|
|
||||||
|
async def test_pressmode_bot(
|
||||||
|
hass: HomeAssistant, mock_list_devices, mock_get_status
|
||||||
|
) -> None:
|
||||||
|
"""Test press."""
|
||||||
|
mock_list_devices.return_value = [
|
||||||
|
Device(
|
||||||
|
deviceId="bot-id-1",
|
||||||
|
deviceName="bot-1",
|
||||||
|
deviceType="Bot",
|
||||||
|
hubDeviceId="test-hub-id",
|
||||||
|
),
|
||||||
|
]
|
||||||
|
|
||||||
|
mock_get_status.return_value = {"deviceMode": "pressMode"}
|
||||||
|
|
||||||
|
entry = configure_integration(hass)
|
||||||
|
await hass.config_entries.async_setup(entry.entry_id)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
assert entry.state is ConfigEntryState.LOADED
|
||||||
|
|
||||||
|
entity_id = "button.bot_1"
|
||||||
|
assert hass.states.get(entity_id).state == STATE_UNKNOWN
|
||||||
|
|
||||||
|
with patch.object(SwitchBotAPI, "send_command") as mock_send_command:
|
||||||
|
await hass.services.async_call(
|
||||||
|
BUTTON_DOMAIN, SERVICE_PRESS, {ATTR_ENTITY_ID: entity_id}, blocking=True
|
||||||
|
)
|
||||||
|
mock_send_command.assert_called_once_with(
|
||||||
|
"bot-id-1", BotCommands.PRESS, "command", "default"
|
||||||
|
)
|
||||||
|
|
||||||
|
assert hass.states.get(entity_id).state != STATE_UNKNOWN
|
||||||
|
|
||||||
|
|
||||||
|
async def test_switchmode_bot_no_button_entity(
|
||||||
|
hass: HomeAssistant, mock_list_devices, mock_get_status
|
||||||
|
) -> None:
|
||||||
|
"""Test a switchMode bot isn't added as a button."""
|
||||||
|
mock_list_devices.return_value = [
|
||||||
|
Device(
|
||||||
|
deviceId="bot-id-1",
|
||||||
|
deviceName="bot-1",
|
||||||
|
deviceType="Bot",
|
||||||
|
hubDeviceId="test-hub-id",
|
||||||
|
),
|
||||||
|
]
|
||||||
|
|
||||||
|
mock_get_status.return_value = {"deviceMode": "switchMode"}
|
||||||
|
|
||||||
|
entry = configure_integration(hass)
|
||||||
|
await hass.config_entries.async_setup(entry.entry_id)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
assert entry.state is ConfigEntryState.LOADED
|
||||||
|
assert not hass.states.async_entity_ids(BUTTON_DOMAIN)
|
@ -1,4 +1,4 @@
|
|||||||
"""Test for the switchbot_cloud relay switch."""
|
"""Test for the switchbot_cloud relay switch & bot."""
|
||||||
|
|
||||||
from unittest.mock import patch
|
from unittest.mock import patch
|
||||||
|
|
||||||
@ -54,3 +54,63 @@ async def test_relay_switch(
|
|||||||
SWITCH_DOMAIN, SERVICE_TURN_OFF, {ATTR_ENTITY_ID: entity_id}, blocking=True
|
SWITCH_DOMAIN, SERVICE_TURN_OFF, {ATTR_ENTITY_ID: entity_id}, blocking=True
|
||||||
)
|
)
|
||||||
assert hass.states.get(entity_id).state == STATE_OFF
|
assert hass.states.get(entity_id).state == STATE_OFF
|
||||||
|
|
||||||
|
|
||||||
|
async def test_switchmode_bot(
|
||||||
|
hass: HomeAssistant, mock_list_devices, mock_get_status
|
||||||
|
) -> None:
|
||||||
|
"""Test turn on and turn off."""
|
||||||
|
mock_list_devices.return_value = [
|
||||||
|
Device(
|
||||||
|
deviceId="bot-id-1",
|
||||||
|
deviceName="bot-1",
|
||||||
|
deviceType="Bot",
|
||||||
|
hubDeviceId="test-hub-id",
|
||||||
|
),
|
||||||
|
]
|
||||||
|
|
||||||
|
mock_get_status.return_value = {"deviceMode": "switchMode", "power": "off"}
|
||||||
|
|
||||||
|
entry = configure_integration(hass)
|
||||||
|
await hass.config_entries.async_setup(entry.entry_id)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
assert entry.state is ConfigEntryState.LOADED
|
||||||
|
|
||||||
|
entity_id = "switch.bot_1"
|
||||||
|
assert hass.states.get(entity_id).state == STATE_OFF
|
||||||
|
|
||||||
|
with patch.object(SwitchBotAPI, "send_command"):
|
||||||
|
await hass.services.async_call(
|
||||||
|
SWITCH_DOMAIN, SERVICE_TURN_ON, {ATTR_ENTITY_ID: entity_id}, blocking=True
|
||||||
|
)
|
||||||
|
assert hass.states.get(entity_id).state == STATE_ON
|
||||||
|
|
||||||
|
with patch.object(SwitchBotAPI, "send_command"):
|
||||||
|
await hass.services.async_call(
|
||||||
|
SWITCH_DOMAIN, SERVICE_TURN_OFF, {ATTR_ENTITY_ID: entity_id}, blocking=True
|
||||||
|
)
|
||||||
|
assert hass.states.get(entity_id).state == STATE_OFF
|
||||||
|
|
||||||
|
|
||||||
|
async def test_pressmode_bot_no_switch_entity(
|
||||||
|
hass: HomeAssistant, mock_list_devices, mock_get_status
|
||||||
|
) -> None:
|
||||||
|
"""Test a pressMode bot isn't added as a switch."""
|
||||||
|
mock_list_devices.return_value = [
|
||||||
|
Device(
|
||||||
|
deviceId="bot-id-1",
|
||||||
|
deviceName="bot-1",
|
||||||
|
deviceType="Bot",
|
||||||
|
hubDeviceId="test-hub-id",
|
||||||
|
),
|
||||||
|
]
|
||||||
|
|
||||||
|
mock_get_status.return_value = {"deviceMode": "pressMode"}
|
||||||
|
|
||||||
|
entry = configure_integration(hass)
|
||||||
|
await hass.config_entries.async_setup(entry.entry_id)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
assert entry.state is ConfigEntryState.LOADED
|
||||||
|
assert not hass.states.async_entity_ids(SWITCH_DOMAIN)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user