Add Switchbot hygrometers (#75325)

* Switchbot add support for hygrometers

* Update CODEOWNERS

* Improve debug

* Remove redundant mention to temp unit

* Adopt FlowResultType

* Modify SwitchBot data within coordinator

* Increase logging for switchbot sensor

* Revert "Increase logging for switchbot sensor"

This reverts commit d8b377429c.

Co-authored-by: J. Nick Koston <nick@koston.org>
pull/75630/head
Diogo F. Andrade Murteira 2022-07-22 17:03:02 +01:00 committed by GitHub
parent e9697872c8
commit 148f963510
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 91 additions and 6 deletions

View File

@ -1038,8 +1038,8 @@ build.json @home-assistant/supervisor
/tests/components/switch/ @home-assistant/core
/homeassistant/components/switch_as_x/ @home-assistant/core
/tests/components/switch_as_x/ @home-assistant/core
/homeassistant/components/switchbot/ @danielhiversen @RenierM26
/tests/components/switchbot/ @danielhiversen @RenierM26
/homeassistant/components/switchbot/ @danielhiversen @RenierM26 @murtas
/tests/components/switchbot/ @danielhiversen @RenierM26 @murtas
/homeassistant/components/switcher_kis/ @tomerfi @thecode
/tests/components/switcher_kis/ @tomerfi @thecode
/homeassistant/components/switchmate/ @danielhiversen

View File

@ -9,6 +9,7 @@ from homeassistant.core import HomeAssistant
from .const import (
ATTR_BOT,
ATTR_CURTAIN,
ATTR_HYGROMETER,
COMMON_OPTIONS,
CONF_RETRY_COUNT,
CONF_RETRY_TIMEOUT,
@ -26,6 +27,7 @@ from .coordinator import SwitchbotDataUpdateCoordinator
PLATFORMS_BY_TYPE = {
ATTR_BOT: [Platform.SWITCH, Platform.SENSOR],
ATTR_CURTAIN: [Platform.COVER, Platform.BINARY_SENSOR, Platform.SENSOR],
ATTR_HYGROMETER: [Platform.SENSOR],
}

View File

@ -87,6 +87,8 @@ class SwitchbotConfigFlow(ConfigFlow, domain=DOMAIN):
try:
self._discovered_devices = await self._get_switchbots()
for device in self._discovered_devices.values():
_LOGGER.debug("Found %s", device)
except NotConnectedError:
return self.async_abort(reason="cannot_connect")

View File

@ -5,8 +5,13 @@ MANUFACTURER = "switchbot"
# Config Attributes
ATTR_BOT = "bot"
ATTR_CURTAIN = "curtain"
ATTR_HYGROMETER = "hygrometer"
DEFAULT_NAME = "Switchbot"
SUPPORTED_MODEL_TYPES = {"WoHand": ATTR_BOT, "WoCurtain": ATTR_CURTAIN}
SUPPORTED_MODEL_TYPES = {
"WoHand": ATTR_BOT,
"WoCurtain": ATTR_CURTAIN,
"WoSensorTH": ATTR_HYGROMETER,
}
# Config Defaults
DEFAULT_RETRY_COUNT = 3

View File

@ -14,6 +14,14 @@ from .const import DOMAIN
_LOGGER = logging.getLogger(__name__)
def flatten_sensors_data(sensor):
"""Deconstruct SwitchBot library temp object C/Fº readings from dictionary."""
if "temp" in sensor["data"]:
sensor["data"]["temperature"] = sensor["data"]["temp"]["c"]
return sensor
class SwitchbotDataUpdateCoordinator(DataUpdateCoordinator):
"""Class to manage fetching switchbot data."""
@ -47,4 +55,7 @@ class SwitchbotDataUpdateCoordinator(DataUpdateCoordinator):
if not switchbot_data:
raise UpdateFailed("Unable to fetch switchbot services data")
return switchbot_data
return {
identifier: flatten_sensors_data(sensor)
for identifier, sensor in switchbot_data.items()
}

View File

@ -4,7 +4,7 @@
"documentation": "https://www.home-assistant.io/integrations/switchbot",
"requirements": ["PySwitchbot==0.14.1"],
"config_flow": true,
"codeowners": ["@danielhiversen", "@RenierM26"],
"codeowners": ["@danielhiversen", "@RenierM26", "@murtas"],
"bluetooth": [{ "service_uuid": "cba20d00-224d-11e6-9fb8-0002a5d5c51b" }],
"iot_class": "local_polling",
"loggers": ["switchbot"]

View File

@ -12,6 +12,7 @@ from homeassistant.const import (
CONF_NAME,
PERCENTAGE,
SIGNAL_STRENGTH_DECIBELS_MILLIWATT,
TEMP_CELSIUS,
)
from homeassistant.core import HomeAssistant
from homeassistant.exceptions import PlatformNotReady
@ -43,6 +44,16 @@ SENSOR_TYPES: dict[str, SensorEntityDescription] = {
native_unit_of_measurement="Level",
device_class=SensorDeviceClass.ILLUMINANCE,
),
"humidity": SensorEntityDescription(
key="humidity",
native_unit_of_measurement=PERCENTAGE,
device_class=SensorDeviceClass.HUMIDITY,
),
"temperature": SensorEntityDescription(
key="temperature",
native_unit_of_measurement=TEMP_CELSIUS,
device_class=SensorDeviceClass.TEMPERATURE,
),
}

View File

@ -26,6 +26,12 @@ USER_INPUT_CURTAIN = {
CONF_MAC: "e7:89:43:90:90:90",
}
USER_INPUT_SENSOR = {
CONF_NAME: "test-name",
CONF_PASSWORD: "test-password",
CONF_MAC: "c0:ce:b0:d4:26:be",
}
USER_INPUT_UNSUPPORTED_DEVICE = {
CONF_NAME: "test-name",
CONF_PASSWORD: "test-password",

View File

@ -72,6 +72,19 @@ class MocGetSwitchbotDevices:
},
"modelName": "WoCurtain",
}
self._sensor_data = {
"mac_address": "c0:ce:b0:d4:26:be",
"isEncrypted": False,
"data": {
"temp": {"c": 21.6, "f": 70.88},
"fahrenheit": False,
"humidity": 73,
"battery": 100,
"rssi": -58,
},
"model": "T",
"modelName": "WoSensorTH",
}
self._unsupported_device = {
"mac_address": "test",
"isEncrypted": False,
@ -97,6 +110,8 @@ class MocGetSwitchbotDevices:
return self._unsupported_device
if mac == "e7:89:43:90:90:90":
return self._curtain_all_services_data
if mac == "c0:ce:b0:d4:26:be":
return self._sensor_data
return None

View File

@ -11,7 +11,13 @@ from homeassistant.config_entries import SOURCE_USER
from homeassistant.const import CONF_MAC, CONF_NAME, CONF_PASSWORD, CONF_SENSOR_TYPE
from homeassistant.data_entry_flow import FlowResultType
from . import USER_INPUT, USER_INPUT_CURTAIN, init_integration, patch_async_setup_entry
from . import (
USER_INPUT,
USER_INPUT_CURTAIN,
USER_INPUT_SENSOR,
init_integration,
patch_async_setup_entry,
)
DOMAIN = "switchbot"
@ -71,6 +77,33 @@ async def test_user_form_valid_mac(hass):
assert len(mock_setup_entry.mock_calls) == 1
# test sensor device creation.
result = await hass.config_entries.flow.async_init(
DOMAIN, context={"source": SOURCE_USER}
)
assert result["type"] == FlowResultType.FORM
assert result["step_id"] == "user"
assert result["errors"] == {}
with patch_async_setup_entry() as mock_setup_entry:
result = await hass.config_entries.flow.async_configure(
result["flow_id"],
USER_INPUT_SENSOR,
)
await hass.async_block_till_done()
assert result["type"] == FlowResultType.CREATE_ENTRY
assert result["title"] == "test-name"
assert result["data"] == {
CONF_MAC: "c0:ce:b0:d4:26:be",
CONF_NAME: "test-name",
CONF_PASSWORD: "test-password",
CONF_SENSOR_TYPE: "hygrometer",
}
assert len(mock_setup_entry.mock_calls) == 1
# tests abort if no unconfigured devices are found.
result = await hass.config_entries.flow.async_init(