mirror of
https://github.com/home-assistant/core.git
synced 2025-07-26 06:37:52 +00:00
Add MVP humidifier support to switchbot (#83696)
* Add MVP humidifier support to switchbot changelog: https://github.com/Danielhiversen/pySwitchbot/compare/0.22.0...0.23.0 * Update homeassistant/components/switchbot/config_flow.py * bump * coveragerc * Revert "coveragerc" This reverts commit eb642f6543e5f37511d65570c359670e1ee7be1f. * fix dirty branch
This commit is contained in:
parent
5c79dae4c0
commit
642cefb035
@ -1245,6 +1245,7 @@ omit =
|
|||||||
homeassistant/components/switchbot/coordinator.py
|
homeassistant/components/switchbot/coordinator.py
|
||||||
homeassistant/components/switchbot/cover.py
|
homeassistant/components/switchbot/cover.py
|
||||||
homeassistant/components/switchbot/entity.py
|
homeassistant/components/switchbot/entity.py
|
||||||
|
homeassistant/components/switchbot/humidifier.py
|
||||||
homeassistant/components/switchbot/light.py
|
homeassistant/components/switchbot/light.py
|
||||||
homeassistant/components/switchbot/sensor.py
|
homeassistant/components/switchbot/sensor.py
|
||||||
homeassistant/components/switchbot/switch.py
|
homeassistant/components/switchbot/switch.py
|
||||||
|
@ -42,6 +42,7 @@ PLATFORMS_BY_TYPE = {
|
|||||||
SupportedModels.HYGROMETER.value: [Platform.SENSOR],
|
SupportedModels.HYGROMETER.value: [Platform.SENSOR],
|
||||||
SupportedModels.CONTACT.value: [Platform.BINARY_SENSOR, Platform.SENSOR],
|
SupportedModels.CONTACT.value: [Platform.BINARY_SENSOR, Platform.SENSOR],
|
||||||
SupportedModels.MOTION.value: [Platform.BINARY_SENSOR, Platform.SENSOR],
|
SupportedModels.MOTION.value: [Platform.BINARY_SENSOR, Platform.SENSOR],
|
||||||
|
SupportedModels.HUMIDIFIER.value: [Platform.HUMIDIFIER, Platform.SENSOR],
|
||||||
}
|
}
|
||||||
CLASS_BY_DEVICE = {
|
CLASS_BY_DEVICE = {
|
||||||
SupportedModels.CEILING_LIGHT.value: switchbot.SwitchbotCeilingLight,
|
SupportedModels.CEILING_LIGHT.value: switchbot.SwitchbotCeilingLight,
|
||||||
@ -50,6 +51,7 @@ CLASS_BY_DEVICE = {
|
|||||||
SupportedModels.PLUG.value: switchbot.SwitchbotPlugMini,
|
SupportedModels.PLUG.value: switchbot.SwitchbotPlugMini,
|
||||||
SupportedModels.BULB.value: switchbot.SwitchbotBulb,
|
SupportedModels.BULB.value: switchbot.SwitchbotBulb,
|
||||||
SupportedModels.LIGHT_STRIP.value: switchbot.SwitchbotLightStrip,
|
SupportedModels.LIGHT_STRIP.value: switchbot.SwitchbotLightStrip,
|
||||||
|
SupportedModels.HUMIDIFIER.value: switchbot.SwitchbotHumidifier,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -66,7 +66,7 @@ class SwitchbotConfigFlow(ConfigFlow, domain=DOMAIN):
|
|||||||
self, discovery_info: BluetoothServiceInfoBleak
|
self, discovery_info: BluetoothServiceInfoBleak
|
||||||
) -> FlowResult:
|
) -> FlowResult:
|
||||||
"""Handle the bluetooth discovery step."""
|
"""Handle the bluetooth discovery step."""
|
||||||
_LOGGER.debug("Discovered bluetooth device: %s", discovery_info)
|
_LOGGER.debug("Discovered bluetooth device: %s", discovery_info.as_dict())
|
||||||
await self.async_set_unique_id(format_unique_id(discovery_info.address))
|
await self.async_set_unique_id(format_unique_id(discovery_info.address))
|
||||||
self._abort_if_unique_id_configured()
|
self._abort_if_unique_id_configured()
|
||||||
parsed = parse_advertisement_data(
|
parsed = parse_advertisement_data(
|
||||||
|
@ -23,6 +23,7 @@ class SupportedModels(StrEnum):
|
|||||||
CONTACT = "contact"
|
CONTACT = "contact"
|
||||||
PLUG = "plug"
|
PLUG = "plug"
|
||||||
MOTION = "motion"
|
MOTION = "motion"
|
||||||
|
HUMIDIFIER = "humidifier"
|
||||||
|
|
||||||
|
|
||||||
CONNECTABLE_SUPPORTED_MODEL_TYPES = {
|
CONNECTABLE_SUPPORTED_MODEL_TYPES = {
|
||||||
@ -32,6 +33,7 @@ CONNECTABLE_SUPPORTED_MODEL_TYPES = {
|
|||||||
SwitchbotModel.COLOR_BULB: SupportedModels.BULB,
|
SwitchbotModel.COLOR_BULB: SupportedModels.BULB,
|
||||||
SwitchbotModel.LIGHT_STRIP: SupportedModels.LIGHT_STRIP,
|
SwitchbotModel.LIGHT_STRIP: SupportedModels.LIGHT_STRIP,
|
||||||
SwitchbotModel.CEILING_LIGHT: SupportedModels.CEILING_LIGHT,
|
SwitchbotModel.CEILING_LIGHT: SupportedModels.CEILING_LIGHT,
|
||||||
|
SwitchbotModel.HUMIDIFIER: SupportedModels.HUMIDIFIER,
|
||||||
}
|
}
|
||||||
|
|
||||||
NON_CONNECTABLE_SUPPORTED_MODEL_TYPES = {
|
NON_CONNECTABLE_SUPPORTED_MODEL_TYPES = {
|
||||||
|
@ -3,9 +3,10 @@ from __future__ import annotations
|
|||||||
|
|
||||||
from abc import abstractmethod
|
from abc import abstractmethod
|
||||||
from collections.abc import Mapping
|
from collections.abc import Mapping
|
||||||
|
import logging
|
||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
from switchbot import SwitchbotDevice
|
from switchbot import Switchbot, SwitchbotDevice
|
||||||
|
|
||||||
from homeassistant.components.bluetooth.passive_update_coordinator import (
|
from homeassistant.components.bluetooth.passive_update_coordinator import (
|
||||||
PassiveBluetoothCoordinatorEntity,
|
PassiveBluetoothCoordinatorEntity,
|
||||||
@ -13,11 +14,13 @@ from homeassistant.components.bluetooth.passive_update_coordinator import (
|
|||||||
from homeassistant.const import ATTR_CONNECTIONS
|
from homeassistant.const import ATTR_CONNECTIONS
|
||||||
from homeassistant.core import callback
|
from homeassistant.core import callback
|
||||||
from homeassistant.helpers import device_registry as dr
|
from homeassistant.helpers import device_registry as dr
|
||||||
from homeassistant.helpers.entity import DeviceInfo
|
from homeassistant.helpers.entity import DeviceInfo, ToggleEntity
|
||||||
|
|
||||||
from .const import MANUFACTURER
|
from .const import MANUFACTURER
|
||||||
from .coordinator import SwitchbotDataUpdateCoordinator
|
from .coordinator import SwitchbotDataUpdateCoordinator
|
||||||
|
|
||||||
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class SwitchbotEntity(PassiveBluetoothCoordinatorEntity):
|
class SwitchbotEntity(PassiveBluetoothCoordinatorEntity):
|
||||||
"""Generic entity encapsulating common features of Switchbot device."""
|
"""Generic entity encapsulating common features of Switchbot device."""
|
||||||
@ -61,6 +64,30 @@ class SwitchbotEntity(PassiveBluetoothCoordinatorEntity):
|
|||||||
return {"last_run_success": self._last_run_success}
|
return {"last_run_success": self._last_run_success}
|
||||||
|
|
||||||
|
|
||||||
|
class SwitchbotSwitchedEntity(SwitchbotEntity, ToggleEntity):
|
||||||
|
"""Base class for Switchbot entities that can be turned on and off."""
|
||||||
|
|
||||||
|
_device: Switchbot
|
||||||
|
|
||||||
|
async def async_turn_on(self, **kwargs: Any) -> None:
|
||||||
|
"""Turn device on."""
|
||||||
|
_LOGGER.debug("Turn Switchbot device on %s", self._address)
|
||||||
|
|
||||||
|
self._last_run_success = bool(await self._device.turn_on())
|
||||||
|
if self._last_run_success:
|
||||||
|
self._attr_is_on = True
|
||||||
|
self.async_write_ha_state()
|
||||||
|
|
||||||
|
async def async_turn_off(self, **kwargs: Any) -> None:
|
||||||
|
"""Turn device off."""
|
||||||
|
_LOGGER.debug("Turn Switchbot device off %s", self._address)
|
||||||
|
|
||||||
|
self._last_run_success = bool(await self._device.turn_off())
|
||||||
|
if self._last_run_success:
|
||||||
|
self._attr_is_on = False
|
||||||
|
self.async_write_ha_state()
|
||||||
|
|
||||||
|
|
||||||
class SwitchbotSubscribeEntity(SwitchbotEntity):
|
class SwitchbotSubscribeEntity(SwitchbotEntity):
|
||||||
"""Base class for Switchbot entities that use subscribe."""
|
"""Base class for Switchbot entities that use subscribe."""
|
||||||
|
|
||||||
|
72
homeassistant/components/switchbot/humidifier.py
Normal file
72
homeassistant/components/switchbot/humidifier.py
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
"""Support for Switchbot humidifier."""
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import logging
|
||||||
|
|
||||||
|
import switchbot
|
||||||
|
|
||||||
|
from homeassistant.components.humidifier import (
|
||||||
|
MODE_AUTO,
|
||||||
|
MODE_NORMAL,
|
||||||
|
HumidifierDeviceClass,
|
||||||
|
HumidifierEntity,
|
||||||
|
HumidifierEntityFeature,
|
||||||
|
)
|
||||||
|
from homeassistant.config_entries import ConfigEntry
|
||||||
|
from homeassistant.core import HomeAssistant
|
||||||
|
from homeassistant.helpers import entity_platform
|
||||||
|
|
||||||
|
from .const import DOMAIN
|
||||||
|
from .coordinator import SwitchbotDataUpdateCoordinator
|
||||||
|
from .entity import SwitchbotSwitchedEntity
|
||||||
|
|
||||||
|
PARALLEL_UPDATES = 0
|
||||||
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
async def async_setup_entry(
|
||||||
|
hass: HomeAssistant,
|
||||||
|
entry: ConfigEntry,
|
||||||
|
async_add_entities: entity_platform.AddEntitiesCallback,
|
||||||
|
) -> None:
|
||||||
|
"""Set up Switchbot based on a config entry."""
|
||||||
|
coordinator: SwitchbotDataUpdateCoordinator = hass.data[DOMAIN][entry.entry_id]
|
||||||
|
async_add_entities([SwitchBotHumidifier(coordinator)])
|
||||||
|
|
||||||
|
|
||||||
|
class SwitchBotHumidifier(SwitchbotSwitchedEntity, HumidifierEntity):
|
||||||
|
"""Representation of a Switchbot humidifier."""
|
||||||
|
|
||||||
|
_attr_supported_features = HumidifierEntityFeature.MODES
|
||||||
|
_attr_device_class = HumidifierDeviceClass.HUMIDIFIER
|
||||||
|
_attr_available_modes = [MODE_NORMAL, MODE_AUTO]
|
||||||
|
_device: switchbot.SwitchbotHumidifier
|
||||||
|
_attr_min_humidity = 1
|
||||||
|
|
||||||
|
@property
|
||||||
|
def is_on(self) -> bool | None:
|
||||||
|
"""Return true if device is on."""
|
||||||
|
return self._device.is_on()
|
||||||
|
|
||||||
|
@property
|
||||||
|
def mode(self) -> str:
|
||||||
|
"""Return the humidity we try to reach."""
|
||||||
|
return MODE_AUTO if self._device.is_auto() else MODE_NORMAL
|
||||||
|
|
||||||
|
@property
|
||||||
|
def target_humidity(self) -> int | None:
|
||||||
|
"""Return the humidity we try to reach."""
|
||||||
|
return self._device.get_target_humidity()
|
||||||
|
|
||||||
|
async def async_set_humidity(self, humidity: int) -> None:
|
||||||
|
"""Set new target humidity."""
|
||||||
|
self._last_run_success = bool(await self._device.set_level(humidity))
|
||||||
|
self.async_write_ha_state()
|
||||||
|
|
||||||
|
async def async_set_mode(self, mode: str) -> None:
|
||||||
|
"""Set new target humidity."""
|
||||||
|
if mode == MODE_AUTO:
|
||||||
|
self._last_run_success = await self._device.async_set_auto()
|
||||||
|
else:
|
||||||
|
self._last_run_success = await self._device.async_set_manual()
|
||||||
|
self.async_write_ha_state()
|
@ -2,7 +2,7 @@
|
|||||||
"domain": "switchbot",
|
"domain": "switchbot",
|
||||||
"name": "SwitchBot",
|
"name": "SwitchBot",
|
||||||
"documentation": "https://www.home-assistant.io/integrations/switchbot",
|
"documentation": "https://www.home-assistant.io/integrations/switchbot",
|
||||||
"requirements": ["PySwitchbot==0.22.0"],
|
"requirements": ["PySwitchbot==0.23.1"],
|
||||||
"config_flow": true,
|
"config_flow": true,
|
||||||
"dependencies": ["bluetooth"],
|
"dependencies": ["bluetooth"],
|
||||||
"codeowners": [
|
"codeowners": [
|
||||||
|
@ -2,7 +2,6 @@
|
|||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
from typing import Any
|
|
||||||
|
|
||||||
import switchbot
|
import switchbot
|
||||||
|
|
||||||
@ -15,7 +14,7 @@ from homeassistant.helpers.restore_state import RestoreEntity
|
|||||||
|
|
||||||
from .const import DOMAIN
|
from .const import DOMAIN
|
||||||
from .coordinator import SwitchbotDataUpdateCoordinator
|
from .coordinator import SwitchbotDataUpdateCoordinator
|
||||||
from .entity import SwitchbotEntity
|
from .entity import SwitchbotSwitchedEntity
|
||||||
|
|
||||||
# Initialize the logger
|
# Initialize the logger
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
@ -32,7 +31,7 @@ async def async_setup_entry(
|
|||||||
async_add_entities([SwitchBotSwitch(coordinator)])
|
async_add_entities([SwitchBotSwitch(coordinator)])
|
||||||
|
|
||||||
|
|
||||||
class SwitchBotSwitch(SwitchbotEntity, SwitchEntity, RestoreEntity):
|
class SwitchBotSwitch(SwitchbotSwitchedEntity, SwitchEntity, RestoreEntity):
|
||||||
"""Representation of a Switchbot switch."""
|
"""Representation of a Switchbot switch."""
|
||||||
|
|
||||||
_attr_device_class = SwitchDeviceClass.SWITCH
|
_attr_device_class = SwitchDeviceClass.SWITCH
|
||||||
@ -51,24 +50,6 @@ class SwitchBotSwitch(SwitchbotEntity, SwitchEntity, RestoreEntity):
|
|||||||
self._attr_is_on = last_state.state == STATE_ON
|
self._attr_is_on = last_state.state == STATE_ON
|
||||||
self._last_run_success = last_state.attributes.get("last_run_success")
|
self._last_run_success = last_state.attributes.get("last_run_success")
|
||||||
|
|
||||||
async def async_turn_on(self, **kwargs: Any) -> None:
|
|
||||||
"""Turn device on."""
|
|
||||||
_LOGGER.info("Turn Switchbot bot on %s", self._address)
|
|
||||||
|
|
||||||
self._last_run_success = bool(await self._device.turn_on())
|
|
||||||
if self._last_run_success:
|
|
||||||
self._attr_is_on = True
|
|
||||||
self.async_write_ha_state()
|
|
||||||
|
|
||||||
async def async_turn_off(self, **kwargs: Any) -> None:
|
|
||||||
"""Turn device off."""
|
|
||||||
_LOGGER.info("Turn Switchbot bot off %s", self._address)
|
|
||||||
|
|
||||||
self._last_run_success = bool(await self._device.turn_off())
|
|
||||||
if self._last_run_success:
|
|
||||||
self._attr_is_on = False
|
|
||||||
self.async_write_ha_state()
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def assumed_state(self) -> bool:
|
def assumed_state(self) -> bool:
|
||||||
"""Return true if unable to access real state of entity."""
|
"""Return true if unable to access real state of entity."""
|
||||||
|
@ -37,7 +37,7 @@ PyRMVtransport==0.3.3
|
|||||||
PySocks==1.7.1
|
PySocks==1.7.1
|
||||||
|
|
||||||
# homeassistant.components.switchbot
|
# homeassistant.components.switchbot
|
||||||
PySwitchbot==0.22.0
|
PySwitchbot==0.23.1
|
||||||
|
|
||||||
# homeassistant.components.transport_nsw
|
# homeassistant.components.transport_nsw
|
||||||
PyTransportNSW==0.1.1
|
PyTransportNSW==0.1.1
|
||||||
|
@ -33,7 +33,7 @@ PyRMVtransport==0.3.3
|
|||||||
PySocks==1.7.1
|
PySocks==1.7.1
|
||||||
|
|
||||||
# homeassistant.components.switchbot
|
# homeassistant.components.switchbot
|
||||||
PySwitchbot==0.22.0
|
PySwitchbot==0.23.1
|
||||||
|
|
||||||
# homeassistant.components.transport_nsw
|
# homeassistant.components.transport_nsw
|
||||||
PyTransportNSW==0.1.1
|
PyTransportNSW==0.1.1
|
||||||
|
Loading…
x
Reference in New Issue
Block a user