Refactoring

### Fix
* Refactoring
* Changed switch to follow a more homeassistant pattern and allow for easier addition of future switches
This commit is contained in:
RyanClark123
2024-10-10 11:23:30 +01:00
parent f63e0a6dfe
commit 91578464de
6 changed files with 136 additions and 104 deletions
+6 -15
View File
@@ -106,9 +106,11 @@ async def async_setup_entry(
sensors = []
for coordinator in coordinators:
for sensor in SENSORS:
if sensor.key in coordinator.sock.properties:
sensors.append(OwletBinarySensor(coordinator, sensor))
sensors = [
OwletBinarySensor(coordinator, sensor)
for sensor in SENSORS
if sensor.key in coordinator.sock.properties
]
if OwletAwakeSensor.entity_description.key in coordinator.sock.properties:
sensors.append(OwletAwakeSensor(coordinator))
@@ -140,13 +142,6 @@ class OwletBinarySensor(OwletBaseEntity, BinarySensorEntity):
@property
def is_on(self) -> bool:
"""Return true if the binary sensor is on."""
if self.entity_description.key == "sleep_state":
if self.sock.properties["charging"]:
return None
if state in [8, 15]:
state = False
else:
state = True
return self.sock.properties[self.entity_description.key]
@@ -171,8 +166,4 @@ class OwletAwakeSensor(OwletBinarySensor):
@property
def is_on(self) -> bool:
"""Return true if the binary sensor is on."""
return (
False
if self.sock.properties[self.entity_description.key] in [8, 15]
else True
)
return self.sock.properties[self.entity_description.key] not in [8, 15]
+12 -9
View File
@@ -1,4 +1,5 @@
"""Config flow for Owlet Smart Sock integration."""
from __future__ import annotations
from collections.abc import Mapping
@@ -15,19 +16,17 @@ from pyowletapi.exceptions import (
import voluptuous as vol
from homeassistant import config_entries, exceptions
from homeassistant.config_entries import ConfigEntry
from homeassistant.config_entries import ConfigEntry, ConfigFlowResult
from homeassistant.const import (
CONF_API_TOKEN,
CONF_PASSWORD,
CONF_REGION,
CONF_SCAN_INTERVAL,
CONF_USERNAME,
)
from homeassistant.core import callback
from homeassistant.data_entry_flow import FlowResult
from homeassistant.helpers.aiohttp_client import async_get_clientsession
from .const import CONF_OWLET_EXPIRY, CONF_OWLET_REFRESH, DOMAIN, POLLING_INTERVAL
from .const import DOMAIN, POLLING_INTERVAL
_LOGGER = logging.getLogger(__name__)
@@ -51,7 +50,7 @@ class OwletConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
async def async_step_user(
self, user_input: dict[str, Any] | None = None
) -> FlowResult:
) -> ConfigFlowResult:
"""Handle the initial step."""
errors: dict[str, str] = {}
if user_input is not None:
@@ -101,7 +100,9 @@ class OwletConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
"""Get the options flow for this handler."""
return OptionsFlowHandler(config_entry)
async def async_step_reauth(self, user_input: Mapping[str, Any]) -> FlowResult:
async def async_step_reauth(
self, user_input: Mapping[str, Any]
) -> ConfigFlowResult:
"""Handle reauth."""
self.reauth_entry = self.hass.config_entries.async_get_entry(
self.context["entry_id"]
@@ -110,7 +111,7 @@ class OwletConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
async def async_step_reauth_confirm(
self, user_input: dict[str, Any] | None = None
) -> FlowResult:
) -> ConfigFlowResult:
"""Dialog that informs the user that reauth is required."""
assert self.reauth_entry is not None
errors: dict[str, str] = {}
@@ -130,7 +131,9 @@ class OwletConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
self.reauth_entry, data={**entry_data, **token}
)
await self.hass.config_entries.async_reload(self.reauth_entry.entry_id)
await self.hass.config_entries.async_reload(
self.reauth_entry.entry_id
)
return self.async_abort(reason="reauth_successful")
@@ -155,7 +158,7 @@ class OptionsFlowHandler(config_entries.OptionsFlow):
async def async_step_init(
self, user_input: dict[str, Any] | None = None
) -> FlowResult:
) -> ConfigFlowResult:
"""Handle options flow."""
if user_input is not None:
return self.async_create_entry(title="", data=user_input)
+2 -2
View File
@@ -1,11 +1,11 @@
"""Base class for Owlet entities."""
from homeassistant.helpers.device_registry import DeviceInfo
from homeassistant.helpers.entity import Entity
from homeassistant.helpers.update_coordinator import CoordinatorEntity
from homeassistant.helpers.device_registry import DeviceInfo
from .coordinator import OwletCoordinator
from .const import DOMAIN, MANUFACTURER
from .coordinator import OwletCoordinator
class OwletBaseEntity(CoordinatorEntity[OwletCoordinator], Entity):
+5 -3
View File
@@ -115,9 +115,11 @@ async def async_setup_entry(
sensors = []
for coordinator in coordinators:
for sensor in SENSORS:
if sensor.key in coordinator.sock.properties:
sensors.append(OwletSensor(coordinator, sensor))
sensors = [
OwletSensor(coordinator, sensor)
for sensor in SENSORS
if sensor.key in coordinator.sock.properties
]
if OwletSleepSensor.entity_description.key in coordinator.sock.properties:
sensors.append(OwletSleepSensor(coordinator))
+47 -11
View File
@@ -2,12 +2,15 @@
from __future__ import annotations
from collections.abc import Callable, Coroutine
from dataclasses import dataclass
from datetime import timedelta
from typing import Any
from homeassistant.config_entries import ConfigEntry
from pyowletapi.sock import Sock
from homeassistant.components.switch import SwitchEntity, SwitchEntityDescription
from homeassistant.config_entries import ConfigEntry
from homeassistant.core import HomeAssistant
from homeassistant.helpers.entity_platform import AddEntitiesCallback
@@ -19,6 +22,26 @@ SCAN_INTERVAL = timedelta(seconds=5)
PARALLEL_UPDATES = 0
@dataclass(frozen=True, kw_only=True)
class OwletSwitchEntityDescription(SwitchEntityDescription):
"""Describes Owlet switch entity."""
turn_on_fn: Callable[[Sock], Callable[[bool], Coroutine[Any, Any, None]]]
turn_off_fn: Callable[[Sock], Callable[[bool], Coroutine[Any, Any, None]]]
available_during_charging: bool
SWITCHES: tuple[OwletSwitchEntityDescription, ...] = (
OwletSwitchEntityDescription(
key="base_station_on",
translation_key="base_on",
turn_on_fn=lambda sock: (lambda state: sock.control_base_station(state)),
turn_off_fn=lambda sock: (lambda state: sock.control_base_station(state)),
available_during_charging=False,
),
)
async def async_setup_entry(
hass: HomeAssistant,
config_entry: ConfigEntry,
@@ -29,30 +52,43 @@ async def async_setup_entry(
switches = []
for coordinator in coordinators:
switches.append(OwletBaseSwitch(coordinator))
switches = [OwletBaseSwitch(coordinator, switch) for switch in SWITCHES]
async_add_entities(switches)
class OwletBaseSwitch(OwletBaseEntity, SwitchEntity):
"""Defines a Owlet switch."""
_attr_has_entity_name = True
_attr_translation_key = "base_on"
entity_description: OwletSwitchEntityDescription
def __init__(self, coordinator: OwletCoordinator) -> None:
"""Initialize ecobee ventilator platform."""
def __init__(
self,
coordinator: OwletCoordinator,
description: OwletSwitchEntityDescription,
) -> None:
"""Initialize owlet switch platform."""
super().__init__(coordinator)
self._attr_unique_id = f"{self.sock.serial}-base_station_on"
self.entity_description = description
self._attr_unique_id = f"{self.sock.serial}-{description.key}"
self._attr_is_on = False
@property
def is_on(self):
return self.sock.properties["base_station_on"]
def available(self) -> bool:
"""Return if entity is available."""
return super().available and (
not self.sock.properties["charging"]
or self.entity_description.available_during_charging
)
@property
def is_on(self) -> bool:
"""Return if switch is on or off."""
return self.sock.properties[self.entity_description.key]
async def async_turn_on(self, **kwargs: Any) -> None:
"""Turn on the switch."""
await self.sock.control_base_station(True)
await self.entity_description.turn_on_fn(self.sock)(True)
async def async_turn_off(self, **kwargs: Any) -> None:
"""Turn off the switch."""
await self.sock.control_base_station(False)
await self.entity_description.turn_off_fn(self.sock)(False)
+63 -63
View File
@@ -1,87 +1,86 @@
{
"config": {
"step": {
"user": {
"data": {
"region": "Region",
"username": "Email",
"password": "Password"
}
},
"reauth_confirm": {
"title": "Reauthentiaction required for Owlet",
"data": {
"password": "Password"
}
}
},
"error": {
"cannot_connect": "Failed to connect",
"invalid_email": "Entered email address is incorrect",
"invalid_password": "Entered password is incorrect",
"invalid_credentials": "Entered credentials are incorrect",
"unknown": "Unknown error occured"
},
"abort": {
"already_configured": "Device already configured",
"reauth_successful": "Reauthentication successful"
}
},
"options": {
"error": {
"cannot_connect": "Failed to connect",
"invalid_credentials": "Entered credentials are incorrect",
"invalid_email": "Entered email address is incorrect",
"invalid_password": "Entered password is incorrect",
"unknown": "Unknown error occured"
},
"step": {
"init": {
"title": "Configure options for Owlet",
"reauth_confirm": {
"data": {
"pollinterval": "Polling interval in seconds, min 10"
"password": "Password"
},
"title": "Reauthentiaction required for Owlet"
},
"user": {
"data": {
"password": "Password",
"region": "Region",
"username": "Email"
}
}
}
},
"entity": {
"binary_sensor": {
"awake": {
"name": "Awake"
},
"charging": {
"name": "Charging"
},
"high_hr_alrt": {
"name": "High heart rate alert"
},
"low_hr_alrt": {
"name": "Low heart rate alert"
},
"high_ox_alrt": {
"name": "High oxygen alert"
},
"low_ox_alrt": {
"name": "Low oxygen alert"
},
"crit_ox_alrt": {
"name": "Critical oxygen alert"
},
"low_batt_alrt": {
"name": "Low battery alert"
},
"crit_batt_alrt": {
"name": "Critical battery alert"
},
"crit_ox_alrt": {
"name": "Critical oxygen alert"
},
"high_hr_alrt": {
"name": "High heart rate alert"
},
"high_ox_alrt": {
"name": "High oxygen alert"
},
"lost_pwr_alrt": {
"name": "Lost power alert"
},
"low_batt_alrt": {
"name": "Low battery alert"
},
"low_hr_alrt": {
"name": "Low heart rate alert"
},
"low_ox_alrt": {
"name": "Low oxygen alert"
},
"sock_discon_alrt": {
"name": "Sock disconnected alert"
},
"sock_off": {
"name": "Sock off"
},
"awake": {
"name": "Awake"
}
},
"sensor": {
"batterymin": {
"name": "Battery remaining"
},
"batterypercent": {
"name": "Battery percentage"
},
"signalstrength": {
"name": "Signal strength"
"heartrate": {
"name": "Heart rate"
},
"movement": {
"name": "Movement"
},
"movementbucket": {
"name": "Movement bucket"
},
"o2saturation": {
"name": "O2 saturation"
@@ -89,11 +88,8 @@
"o2saturation10a": {
"name": "O2 saturation 10 minute average"
},
"heartrate": {
"name": "Heart rate"
},
"batterymin": {
"name": "Battery remaining"
"signalstrength": {
"name": "Signal strength"
},
"skintemp": {
"name": "Skin temperature"
@@ -101,17 +97,11 @@
"sleepstate": {
"name": "Sleep state",
"state": {
"unknown": "Unknown",
"awake": "Awake",
"deep_sleep": "Deep sleep",
"light_sleep": "Light sleep",
"deep_sleep": "Deep sleep"
"unknown": "Unknown"
}
},
"movement": {
"name": "Movement"
},
"movementbucket": {
"name": "Movement bucket"
}
},
"switch": {
@@ -119,5 +109,15 @@
"name": "Base station on"
}
}
},
"options": {
"step": {
"init": {
"data": {
"pollinterval": "Polling interval in seconds, min 10"
},
"title": "Configure options for Owlet"
}
}
}
}