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
parent
e9697872c8
commit
148f963510
|
@ -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
|
||||
|
|
|
@ -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],
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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")
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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()
|
||||
}
|
||||
|
|
|
@ -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"]
|
||||
|
|
|
@ -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,
|
||||
),
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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(
|
||||
|
|
Loading…
Reference in New Issue