Add type annotations to Ambient PWS (#52596)

This commit is contained in:
Aaron Bach 2021-07-06 13:19:58 -05:00 committed by GitHub
parent 2f1af9a254
commit 9fb05736e4
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 62 additions and 36 deletions

View file

@ -1,4 +1,5 @@
"""Support for Ambient Weather Station Service.""" """Support for Ambient Weather Station Service."""
from __future__ import annotations
from aioambient import Client from aioambient import Client
from aioambient.errors import WebsocketError from aioambient.errors import WebsocketError
@ -8,6 +9,7 @@ from homeassistant.components.binary_sensor import (
DOMAIN as BINARY_SENSOR, DOMAIN as BINARY_SENSOR,
) )
from homeassistant.components.sensor import DOMAIN as SENSOR from homeassistant.components.sensor import DOMAIN as SENSOR
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import ( from homeassistant.const import (
ATTR_LOCATION, ATTR_LOCATION,
ATTR_NAME, ATTR_NAME,
@ -30,7 +32,7 @@ from homeassistant.const import (
SPEED_MILES_PER_HOUR, SPEED_MILES_PER_HOUR,
TEMP_FAHRENHEIT, TEMP_FAHRENHEIT,
) )
from homeassistant.core import callback from homeassistant.core import HomeAssistant, callback
from homeassistant.exceptions import ConfigEntryNotReady from homeassistant.exceptions import ConfigEntryNotReady
from homeassistant.helpers import aiohttp_client, config_validation as cv from homeassistant.helpers import aiohttp_client, config_validation as cv
from homeassistant.helpers.dispatcher import ( from homeassistant.helpers.dispatcher import (
@ -292,7 +294,7 @@ SENSOR_TYPES = {
CONFIG_SCHEMA = cv.deprecated(DOMAIN) CONFIG_SCHEMA = cv.deprecated(DOMAIN)
async def async_setup_entry(hass, config_entry): async def async_setup_entry(hass: HomeAssistant, config_entry: ConfigEntry) -> bool:
"""Set up the Ambient PWS as config entry.""" """Set up the Ambient PWS as config entry."""
hass.data.setdefault(DOMAIN, {DATA_CLIENT: {}}) hass.data.setdefault(DOMAIN, {DATA_CLIENT: {}})
@ -330,7 +332,7 @@ async def async_setup_entry(hass, config_entry):
return True return True
async def async_unload_entry(hass, config_entry): async def async_unload_entry(hass: HomeAssistant, config_entry: ConfigEntry) -> bool:
"""Unload an Ambient PWS config entry.""" """Unload an Ambient PWS config entry."""
ambient = hass.data[DOMAIN][DATA_CLIENT].pop(config_entry.entry_id) ambient = hass.data[DOMAIN][DATA_CLIENT].pop(config_entry.entry_id)
hass.async_create_task(ambient.ws_disconnect()) hass.async_create_task(ambient.ws_disconnect())
@ -338,7 +340,7 @@ async def async_unload_entry(hass, config_entry):
return await hass.config_entries.async_unload_platforms(config_entry, PLATFORMS) return await hass.config_entries.async_unload_platforms(config_entry, PLATFORMS)
async def async_migrate_entry(hass, config_entry): async def async_migrate_entry(hass: HomeAssistant, config_entry: ConfigEntry) -> bool:
"""Migrate old entry.""" """Migrate old entry."""
version = config_entry.version version = config_entry.version
@ -362,19 +364,21 @@ async def async_migrate_entry(hass, config_entry):
class AmbientStation: class AmbientStation:
"""Define a class to handle the Ambient websocket.""" """Define a class to handle the Ambient websocket."""
def __init__(self, hass, config_entry, client): def __init__(
self, hass: HomeAssistant, config_entry: ConfigEntry, client: Client
) -> None:
"""Initialize.""" """Initialize."""
self._config_entry = config_entry self._config_entry = config_entry
self._entry_setup_complete = False self._entry_setup_complete = False
self._hass = hass self._hass = hass
self._ws_reconnect_delay = DEFAULT_SOCKET_MIN_RETRY self._ws_reconnect_delay = DEFAULT_SOCKET_MIN_RETRY
self.client = client self.client = client
self.stations = {} self.stations: dict[str, dict] = {}
async def _attempt_connect(self): async def _attempt_connect(self) -> None:
"""Attempt to connect to the socket (retrying later on fail).""" """Attempt to connect to the socket (retrying later on fail)."""
async def connect(timestamp=None): async def connect(timestamp: int | None = None):
"""Connect.""" """Connect."""
await self.client.websocket.connect() await self.client.websocket.connect()
@ -385,14 +389,14 @@ class AmbientStation:
self._ws_reconnect_delay = min(2 * self._ws_reconnect_delay, 480) self._ws_reconnect_delay = min(2 * self._ws_reconnect_delay, 480)
async_call_later(self._hass, self._ws_reconnect_delay, connect) async_call_later(self._hass, self._ws_reconnect_delay, connect)
async def ws_connect(self): async def ws_connect(self) -> None:
"""Register handlers and connect to the websocket.""" """Register handlers and connect to the websocket."""
def on_connect(): def on_connect() -> None:
"""Define a handler to fire when the websocket is connected.""" """Define a handler to fire when the websocket is connected."""
LOGGER.info("Connected to websocket") LOGGER.info("Connected to websocket")
def on_data(data): def on_data(data: dict) -> None:
"""Define a handler to fire when the data is received.""" """Define a handler to fire when the data is received."""
mac_address = data["macAddress"] mac_address = data["macAddress"]
if data != self.stations[mac_address][ATTR_LAST_DATA]: if data != self.stations[mac_address][ATTR_LAST_DATA]:
@ -402,11 +406,11 @@ class AmbientStation:
self._hass, f"ambient_station_data_update_{mac_address}" self._hass, f"ambient_station_data_update_{mac_address}"
) )
def on_disconnect(): def on_disconnect() -> None:
"""Define a handler to fire when the websocket is disconnected.""" """Define a handler to fire when the websocket is disconnected."""
LOGGER.info("Disconnected from websocket") LOGGER.info("Disconnected from websocket")
def on_subscribed(data): def on_subscribed(data: dict) -> None:
"""Define a handler to fire when the subscription is set.""" """Define a handler to fire when the subscription is set."""
for station in data["devices"]: for station in data["devices"]:
if station["macAddress"] in self.stations: if station["macAddress"] in self.stations:
@ -447,7 +451,7 @@ class AmbientStation:
await self._attempt_connect() await self._attempt_connect()
async def ws_disconnect(self): async def ws_disconnect(self) -> None:
"""Disconnect from the websocket.""" """Disconnect from the websocket."""
await self.client.websocket.disconnect() await self.client.websocket.disconnect()
@ -456,8 +460,14 @@ class AmbientWeatherEntity(Entity):
"""Define a base Ambient PWS entity.""" """Define a base Ambient PWS entity."""
def __init__( def __init__(
self, ambient, mac_address, station_name, sensor_type, sensor_name, device_class self,
): ambient: AmbientStation,
mac_address: str,
station_name: str,
sensor_type: str,
sensor_name: str,
device_class: str | None,
) -> None:
"""Initialize the sensor.""" """Initialize the sensor."""
self._ambient = ambient self._ambient = ambient
self._attr_device_class = device_class self._attr_device_class = device_class
@ -472,11 +482,11 @@ class AmbientWeatherEntity(Entity):
self._mac_address = mac_address self._mac_address = mac_address
self._sensor_type = sensor_type self._sensor_type = sensor_type
async def async_added_to_hass(self): async def async_added_to_hass(self) -> None:
"""Register callbacks.""" """Register callbacks."""
@callback @callback
def update(): def update() -> None:
"""Update the state.""" """Update the state."""
if self._sensor_type == TYPE_SOLARRADIATION_LX: if self._sensor_type == TYPE_SOLARRADIATION_LX:
self._attr_available = ( self._attr_available = (
@ -505,6 +515,6 @@ class AmbientWeatherEntity(Entity):
self.update_from_latest_data() self.update_from_latest_data()
@callback @callback
def update_from_latest_data(self): def update_from_latest_data(self) -> None:
"""Update the entity from the latest data.""" """Update the entity from the latest data."""
raise NotImplementedError raise NotImplementedError

View file

@ -1,10 +1,14 @@
"""Support for Ambient Weather Station binary sensors.""" """Support for Ambient Weather Station binary sensors."""
from __future__ import annotations
from homeassistant.components.binary_sensor import ( from homeassistant.components.binary_sensor import (
DOMAIN as BINARY_SENSOR, DOMAIN as BINARY_SENSOR,
BinarySensorEntity, BinarySensorEntity,
) )
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import ATTR_NAME from homeassistant.const import ATTR_NAME
from homeassistant.core import callback from homeassistant.core import HomeAssistant, callback
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from . import ( from . import (
SENSOR_TYPES, SENSOR_TYPES,
@ -27,7 +31,9 @@ from . import (
from .const import ATTR_LAST_DATA, ATTR_MONITORED_CONDITIONS, DATA_CLIENT, DOMAIN from .const import ATTR_LAST_DATA, ATTR_MONITORED_CONDITIONS, DATA_CLIENT, DOMAIN
async def async_setup_entry(hass, entry, async_add_entities): async def async_setup_entry(
hass: HomeAssistant, entry: ConfigEntry, async_add_entities: AddEntitiesCallback
) -> None:
"""Set up Ambient PWS binary sensors based on a config entry.""" """Set up Ambient PWS binary sensors based on a config entry."""
ambient = hass.data[DOMAIN][DATA_CLIENT][entry.entry_id] ambient = hass.data[DOMAIN][DATA_CLIENT][entry.entry_id]
@ -54,7 +60,7 @@ class AmbientWeatherBinarySensor(AmbientWeatherEntity, BinarySensorEntity):
"""Define an Ambient binary sensor.""" """Define an Ambient binary sensor."""
@callback @callback
def update_from_latest_data(self): def update_from_latest_data(self) -> None:
"""Fetch new state data for the entity.""" """Fetch new state data for the entity."""
state = self._ambient.stations[self._mac_address][ATTR_LAST_DATA].get( state = self._ambient.stations[self._mac_address][ATTR_LAST_DATA].get(
self._sensor_type self._sensor_type

View file

@ -1,10 +1,13 @@
"""Config flow to configure the Ambient PWS component.""" """Config flow to configure the Ambient PWS component."""
from __future__ import annotations
from aioambient import Client from aioambient import Client
from aioambient.errors import AmbientError from aioambient.errors import AmbientError
import voluptuous as vol import voluptuous as vol
from homeassistant import config_entries from homeassistant import config_entries
from homeassistant.const import CONF_API_KEY from homeassistant.const import CONF_API_KEY
from homeassistant.data_entry_flow import FlowResult
from homeassistant.helpers import aiohttp_client from homeassistant.helpers import aiohttp_client
from .const import CONF_APP_KEY, DOMAIN from .const import CONF_APP_KEY, DOMAIN
@ -15,13 +18,13 @@ class AmbientStationFlowHandler(config_entries.ConfigFlow, domain=DOMAIN):
VERSION = 2 VERSION = 2
def __init__(self): def __init__(self) -> None:
"""Initialize the config flow.""" """Initialize the config flow."""
self.data_schema = vol.Schema( self.data_schema = vol.Schema(
{vol.Required(CONF_API_KEY): str, vol.Required(CONF_APP_KEY): str} {vol.Required(CONF_API_KEY): str, vol.Required(CONF_APP_KEY): str}
) )
async def _show_form(self, errors=None): async def _show_form(self, errors: dict | None = None) -> FlowResult:
"""Show the form to the user.""" """Show the form to the user."""
return self.async_show_form( return self.async_show_form(
step_id="user", step_id="user",
@ -29,7 +32,7 @@ class AmbientStationFlowHandler(config_entries.ConfigFlow, domain=DOMAIN):
errors=errors if errors else {}, errors=errors if errors else {},
) )
async def async_step_user(self, user_input=None): async def async_step_user(self, user_input: dict | None = None) -> FlowResult:
"""Handle the start of the config flow.""" """Handle the start of the config flow."""
if not user_input: if not user_input:
return await self._show_form() return await self._show_form()

View file

@ -1,18 +1,25 @@
"""Support for Ambient Weather Station sensors.""" """Support for Ambient Weather Station sensors."""
from __future__ import annotations
from homeassistant.components.sensor import DOMAIN as SENSOR, SensorEntity from homeassistant.components.sensor import DOMAIN as SENSOR, SensorEntity
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import ATTR_NAME from homeassistant.const import ATTR_NAME
from homeassistant.core import callback from homeassistant.core import HomeAssistant, callback
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from . import ( from . import (
SENSOR_TYPES, SENSOR_TYPES,
TYPE_SOLARRADIATION, TYPE_SOLARRADIATION,
TYPE_SOLARRADIATION_LX, TYPE_SOLARRADIATION_LX,
AmbientStation,
AmbientWeatherEntity, AmbientWeatherEntity,
) )
from .const import ATTR_LAST_DATA, ATTR_MONITORED_CONDITIONS, DATA_CLIENT, DOMAIN from .const import ATTR_LAST_DATA, ATTR_MONITORED_CONDITIONS, DATA_CLIENT, DOMAIN
async def async_setup_entry(hass, entry, async_add_entities): async def async_setup_entry(
hass: HomeAssistant, entry: ConfigEntry, async_add_entities: AddEntitiesCallback
) -> None:
"""Set up Ambient PWS sensors based on a config entry.""" """Set up Ambient PWS sensors based on a config entry."""
ambient = hass.data[DOMAIN][DATA_CLIENT][entry.entry_id] ambient = hass.data[DOMAIN][DATA_CLIENT][entry.entry_id]
@ -41,14 +48,14 @@ class AmbientWeatherSensor(AmbientWeatherEntity, SensorEntity):
def __init__( def __init__(
self, self,
ambient, ambient: AmbientStation,
mac_address, mac_address: str,
station_name, station_name: str,
sensor_type, sensor_type: str,
sensor_name, sensor_name: str,
device_class, device_class: str | None,
unit, unit: str | None,
): ) -> None:
"""Initialize the sensor.""" """Initialize the sensor."""
super().__init__( super().__init__(
ambient, mac_address, station_name, sensor_type, sensor_name, device_class ambient, mac_address, station_name, sensor_type, sensor_name, device_class
@ -57,7 +64,7 @@ class AmbientWeatherSensor(AmbientWeatherEntity, SensorEntity):
self._attr_unit_of_measurement = unit self._attr_unit_of_measurement = unit
@callback @callback
def update_from_latest_data(self): def update_from_latest_data(self) -> None:
"""Fetch new state data for the sensor.""" """Fetch new state data for the sensor."""
if self._sensor_type == TYPE_SOLARRADIATION_LX: if self._sensor_type == TYPE_SOLARRADIATION_LX:
# If the user requests the solarradiation_lx sensor, use the # If the user requests the solarradiation_lx sensor, use the