mirror of
https://github.com/home-assistant/core.git
synced 2025-07-27 15:17:35 +00:00
Update typing 08 (#48058)
This commit is contained in:
parent
9e1a6610dc
commit
5cdd945f44
@ -1,6 +1,7 @@
|
|||||||
"""Config flow for habitica integration."""
|
"""Config flow for habitica integration."""
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
from typing import Dict
|
|
||||||
|
|
||||||
from aiohttp import ClientResponseError
|
from aiohttp import ClientResponseError
|
||||||
from habitipy.aio import HabitipyAsync
|
from habitipy.aio import HabitipyAsync
|
||||||
@ -25,8 +26,8 @@ _LOGGER = logging.getLogger(__name__)
|
|||||||
|
|
||||||
|
|
||||||
async def validate_input(
|
async def validate_input(
|
||||||
hass: core.HomeAssistant, data: Dict[str, str]
|
hass: core.HomeAssistant, data: dict[str, str]
|
||||||
) -> Dict[str, str]:
|
) -> dict[str, str]:
|
||||||
"""Validate the user input allows us to connect."""
|
"""Validate the user input allows us to connect."""
|
||||||
|
|
||||||
websession = async_get_clientsession(hass)
|
websession = async_get_clientsession(hass)
|
||||||
|
@ -1,9 +1,11 @@
|
|||||||
"""Support for Hass.io."""
|
"""Support for Hass.io."""
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
import asyncio
|
import asyncio
|
||||||
from datetime import timedelta
|
from datetime import timedelta
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
from typing import Any, Dict, List, Optional
|
from typing import Any
|
||||||
|
|
||||||
import voluptuous as vol
|
import voluptuous as vol
|
||||||
|
|
||||||
@ -236,7 +238,7 @@ async def async_set_addon_options(
|
|||||||
@bind_hass
|
@bind_hass
|
||||||
async def async_get_addon_discovery_info(
|
async def async_get_addon_discovery_info(
|
||||||
hass: HomeAssistantType, slug: str
|
hass: HomeAssistantType, slug: str
|
||||||
) -> Optional[dict]:
|
) -> dict | None:
|
||||||
"""Return discovery data for an add-on."""
|
"""Return discovery data for an add-on."""
|
||||||
hassio = hass.data[DOMAIN]
|
hassio = hass.data[DOMAIN]
|
||||||
data = await hassio.retrieve_discovery_messages()
|
data = await hassio.retrieve_discovery_messages()
|
||||||
@ -545,7 +547,7 @@ async def async_unload_entry(
|
|||||||
|
|
||||||
@callback
|
@callback
|
||||||
def async_register_addons_in_dev_reg(
|
def async_register_addons_in_dev_reg(
|
||||||
entry_id: str, dev_reg: DeviceRegistry, addons: List[Dict[str, Any]]
|
entry_id: str, dev_reg: DeviceRegistry, addons: list[dict[str, Any]]
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Register addons in the device registry."""
|
"""Register addons in the device registry."""
|
||||||
for addon in addons:
|
for addon in addons:
|
||||||
@ -564,7 +566,7 @@ def async_register_addons_in_dev_reg(
|
|||||||
|
|
||||||
@callback
|
@callback
|
||||||
def async_register_os_in_dev_reg(
|
def async_register_os_in_dev_reg(
|
||||||
entry_id: str, dev_reg: DeviceRegistry, os_dict: Dict[str, Any]
|
entry_id: str, dev_reg: DeviceRegistry, os_dict: dict[str, Any]
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Register OS in the device registry."""
|
"""Register OS in the device registry."""
|
||||||
params = {
|
params = {
|
||||||
@ -581,7 +583,7 @@ def async_register_os_in_dev_reg(
|
|||||||
|
|
||||||
@callback
|
@callback
|
||||||
def async_remove_addons_from_dev_reg(
|
def async_remove_addons_from_dev_reg(
|
||||||
dev_reg: DeviceRegistry, addons: List[Dict[str, Any]]
|
dev_reg: DeviceRegistry, addons: list[dict[str, Any]]
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Remove addons from the device registry."""
|
"""Remove addons from the device registry."""
|
||||||
for addon_slug in addons:
|
for addon_slug in addons:
|
||||||
@ -607,7 +609,7 @@ class HassioDataUpdateCoordinator(DataUpdateCoordinator):
|
|||||||
self.dev_reg = dev_reg
|
self.dev_reg = dev_reg
|
||||||
self.is_hass_os = "hassos" in get_info(self.hass)
|
self.is_hass_os = "hassos" in get_info(self.hass)
|
||||||
|
|
||||||
async def _async_update_data(self) -> Dict[str, Any]:
|
async def _async_update_data(self) -> dict[str, Any]:
|
||||||
"""Update data via library."""
|
"""Update data via library."""
|
||||||
new_data = {}
|
new_data = {}
|
||||||
addon_data = get_supervisor_info(self.hass)
|
addon_data = get_supervisor_info(self.hass)
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
"""Binary sensor platform for Hass.io addons."""
|
"""Binary sensor platform for Hass.io addons."""
|
||||||
from typing import Callable, List
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from typing import Callable
|
||||||
|
|
||||||
from homeassistant.components.binary_sensor import BinarySensorEntity
|
from homeassistant.components.binary_sensor import BinarySensorEntity
|
||||||
from homeassistant.config_entries import ConfigEntry
|
from homeassistant.config_entries import ConfigEntry
|
||||||
@ -14,7 +16,7 @@ from .entity import HassioAddonEntity, HassioOSEntity
|
|||||||
async def async_setup_entry(
|
async def async_setup_entry(
|
||||||
hass: HomeAssistant,
|
hass: HomeAssistant,
|
||||||
config_entry: ConfigEntry,
|
config_entry: ConfigEntry,
|
||||||
async_add_entities: Callable[[List[Entity], bool], None],
|
async_add_entities: Callable[[list[Entity], bool], None],
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Binary sensor set up for Hass.io config entry."""
|
"""Binary sensor set up for Hass.io config entry."""
|
||||||
coordinator = hass.data[ADDONS_COORDINATOR]
|
coordinator = hass.data[ADDONS_COORDINATOR]
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
"""Base for Hass.io entities."""
|
"""Base for Hass.io entities."""
|
||||||
from typing import Any, Dict
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from typing import Any
|
||||||
|
|
||||||
from homeassistant.const import ATTR_NAME
|
from homeassistant.const import ATTR_NAME
|
||||||
from homeassistant.helpers.update_coordinator import CoordinatorEntity
|
from homeassistant.helpers.update_coordinator import CoordinatorEntity
|
||||||
@ -14,7 +16,7 @@ class HassioAddonEntity(CoordinatorEntity):
|
|||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
coordinator: HassioDataUpdateCoordinator,
|
coordinator: HassioDataUpdateCoordinator,
|
||||||
addon: Dict[str, Any],
|
addon: dict[str, Any],
|
||||||
attribute_name: str,
|
attribute_name: str,
|
||||||
sensor_name: str,
|
sensor_name: str,
|
||||||
) -> None:
|
) -> None:
|
||||||
@ -27,7 +29,7 @@ class HassioAddonEntity(CoordinatorEntity):
|
|||||||
super().__init__(coordinator)
|
super().__init__(coordinator)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def addon_info(self) -> Dict[str, Any]:
|
def addon_info(self) -> dict[str, Any]:
|
||||||
"""Return add-on info."""
|
"""Return add-on info."""
|
||||||
return self.coordinator.data[self._data_key][self.addon_slug]
|
return self.coordinator.data[self._data_key][self.addon_slug]
|
||||||
|
|
||||||
@ -47,7 +49,7 @@ class HassioAddonEntity(CoordinatorEntity):
|
|||||||
return f"{self.addon_slug}_{self.attribute_name}"
|
return f"{self.addon_slug}_{self.attribute_name}"
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def device_info(self) -> Dict[str, Any]:
|
def device_info(self) -> dict[str, Any]:
|
||||||
"""Return device specific attributes."""
|
"""Return device specific attributes."""
|
||||||
return {"identifiers": {(DOMAIN, self.addon_slug)}}
|
return {"identifiers": {(DOMAIN, self.addon_slug)}}
|
||||||
|
|
||||||
@ -68,7 +70,7 @@ class HassioOSEntity(CoordinatorEntity):
|
|||||||
super().__init__(coordinator)
|
super().__init__(coordinator)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def os_info(self) -> Dict[str, Any]:
|
def os_info(self) -> dict[str, Any]:
|
||||||
"""Return OS info."""
|
"""Return OS info."""
|
||||||
return self.coordinator.data[self._data_key]
|
return self.coordinator.data[self._data_key]
|
||||||
|
|
||||||
@ -88,6 +90,6 @@ class HassioOSEntity(CoordinatorEntity):
|
|||||||
return f"home_assistant_os_{self.attribute_name}"
|
return f"home_assistant_os_{self.attribute_name}"
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def device_info(self) -> Dict[str, Any]:
|
def device_info(self) -> dict[str, Any]:
|
||||||
"""Return device specific attributes."""
|
"""Return device specific attributes."""
|
||||||
return {"identifiers": {(DOMAIN, "OS")}}
|
return {"identifiers": {(DOMAIN, "OS")}}
|
||||||
|
@ -1,9 +1,10 @@
|
|||||||
"""HTTP Support for Hass.io."""
|
"""HTTP Support for Hass.io."""
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
import asyncio
|
import asyncio
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
from typing import Dict, Union
|
|
||||||
|
|
||||||
import aiohttp
|
import aiohttp
|
||||||
from aiohttp import web
|
from aiohttp import web
|
||||||
@ -57,7 +58,7 @@ class HassIOView(HomeAssistantView):
|
|||||||
|
|
||||||
async def _handle(
|
async def _handle(
|
||||||
self, request: web.Request, path: str
|
self, request: web.Request, path: str
|
||||||
) -> Union[web.Response, web.StreamResponse]:
|
) -> web.Response | web.StreamResponse:
|
||||||
"""Route data to Hass.io."""
|
"""Route data to Hass.io."""
|
||||||
hass = request.app["hass"]
|
hass = request.app["hass"]
|
||||||
if _need_auth(hass, path) and not request[KEY_AUTHENTICATED]:
|
if _need_auth(hass, path) and not request[KEY_AUTHENTICATED]:
|
||||||
@ -71,7 +72,7 @@ class HassIOView(HomeAssistantView):
|
|||||||
|
|
||||||
async def _command_proxy(
|
async def _command_proxy(
|
||||||
self, path: str, request: web.Request
|
self, path: str, request: web.Request
|
||||||
) -> Union[web.Response, web.StreamResponse]:
|
) -> web.Response | web.StreamResponse:
|
||||||
"""Return a client request with proxy origin for Hass.io supervisor.
|
"""Return a client request with proxy origin for Hass.io supervisor.
|
||||||
|
|
||||||
This method is a coroutine.
|
This method is a coroutine.
|
||||||
@ -131,7 +132,7 @@ class HassIOView(HomeAssistantView):
|
|||||||
raise HTTPBadGateway()
|
raise HTTPBadGateway()
|
||||||
|
|
||||||
|
|
||||||
def _init_header(request: web.Request) -> Dict[str, str]:
|
def _init_header(request: web.Request) -> dict[str, str]:
|
||||||
"""Create initial header."""
|
"""Create initial header."""
|
||||||
headers = {
|
headers = {
|
||||||
X_HASSIO: os.environ.get("HASSIO_TOKEN", ""),
|
X_HASSIO: os.environ.get("HASSIO_TOKEN", ""),
|
||||||
|
@ -1,9 +1,10 @@
|
|||||||
"""Hass.io Add-on ingress service."""
|
"""Hass.io Add-on ingress service."""
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
import asyncio
|
import asyncio
|
||||||
from ipaddress import ip_address
|
from ipaddress import ip_address
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
from typing import Dict, Union
|
|
||||||
|
|
||||||
import aiohttp
|
import aiohttp
|
||||||
from aiohttp import hdrs, web
|
from aiohttp import hdrs, web
|
||||||
@ -46,7 +47,7 @@ class HassIOIngress(HomeAssistantView):
|
|||||||
|
|
||||||
async def _handle(
|
async def _handle(
|
||||||
self, request: web.Request, token: str, path: str
|
self, request: web.Request, token: str, path: str
|
||||||
) -> Union[web.Response, web.StreamResponse, web.WebSocketResponse]:
|
) -> web.Response | web.StreamResponse | web.WebSocketResponse:
|
||||||
"""Route data to Hass.io ingress service."""
|
"""Route data to Hass.io ingress service."""
|
||||||
try:
|
try:
|
||||||
# Websocket
|
# Websocket
|
||||||
@ -114,7 +115,7 @@ class HassIOIngress(HomeAssistantView):
|
|||||||
|
|
||||||
async def _handle_request(
|
async def _handle_request(
|
||||||
self, request: web.Request, token: str, path: str
|
self, request: web.Request, token: str, path: str
|
||||||
) -> Union[web.Response, web.StreamResponse]:
|
) -> web.Response | web.StreamResponse:
|
||||||
"""Ingress route for request."""
|
"""Ingress route for request."""
|
||||||
url = self._create_url(token, path)
|
url = self._create_url(token, path)
|
||||||
data = await request.read()
|
data = await request.read()
|
||||||
@ -159,9 +160,7 @@ class HassIOIngress(HomeAssistantView):
|
|||||||
return response
|
return response
|
||||||
|
|
||||||
|
|
||||||
def _init_header(
|
def _init_header(request: web.Request, token: str) -> CIMultiDict | dict[str, str]:
|
||||||
request: web.Request, token: str
|
|
||||||
) -> Union[CIMultiDict, Dict[str, str]]:
|
|
||||||
"""Create initial header."""
|
"""Create initial header."""
|
||||||
headers = {}
|
headers = {}
|
||||||
|
|
||||||
@ -208,7 +207,7 @@ def _init_header(
|
|||||||
return headers
|
return headers
|
||||||
|
|
||||||
|
|
||||||
def _response_header(response: aiohttp.ClientResponse) -> Dict[str, str]:
|
def _response_header(response: aiohttp.ClientResponse) -> dict[str, str]:
|
||||||
"""Create response header."""
|
"""Create response header."""
|
||||||
headers = {}
|
headers = {}
|
||||||
|
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
"""Sensor platform for Hass.io addons."""
|
"""Sensor platform for Hass.io addons."""
|
||||||
from typing import Callable, List
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from typing import Callable
|
||||||
|
|
||||||
from homeassistant.config_entries import ConfigEntry
|
from homeassistant.config_entries import ConfigEntry
|
||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant
|
||||||
@ -13,7 +15,7 @@ from .entity import HassioAddonEntity, HassioOSEntity
|
|||||||
async def async_setup_entry(
|
async def async_setup_entry(
|
||||||
hass: HomeAssistant,
|
hass: HomeAssistant,
|
||||||
config_entry: ConfigEntry,
|
config_entry: ConfigEntry,
|
||||||
async_add_entities: Callable[[List[Entity], bool], None],
|
async_add_entities: Callable[[list[Entity], bool], None],
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Sensor set up for Hass.io config entry."""
|
"""Sensor set up for Hass.io config entry."""
|
||||||
coordinator = hass.data[ADDONS_COORDINATOR]
|
coordinator = hass.data[ADDONS_COORDINATOR]
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
"""Support for the PRT Heatmiser themostats using the V3 protocol."""
|
"""Support for the PRT Heatmiser themostats using the V3 protocol."""
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
from typing import List
|
|
||||||
|
|
||||||
from heatmiserV3 import connection, heatmiser
|
from heatmiserV3 import connection, heatmiser
|
||||||
import voluptuous as vol
|
import voluptuous as vol
|
||||||
@ -103,7 +104,7 @@ class HeatmiserV3Thermostat(ClimateEntity):
|
|||||||
return self._hvac_mode
|
return self._hvac_mode
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def hvac_modes(self) -> List[str]:
|
def hvac_modes(self) -> list[str]:
|
||||||
"""Return the list of available hvac operation modes.
|
"""Return the list of available hvac operation modes.
|
||||||
|
|
||||||
Need to be a subset of HVAC_MODES.
|
Need to be a subset of HVAC_MODES.
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
"""Denon HEOS Media Player."""
|
"""Denon HEOS Media Player."""
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
import asyncio
|
import asyncio
|
||||||
from datetime import timedelta
|
from datetime import timedelta
|
||||||
import logging
|
import logging
|
||||||
from typing import Dict
|
|
||||||
|
|
||||||
from pyheos import Heos, HeosError, const as heos_const
|
from pyheos import Heos, HeosError, const as heos_const
|
||||||
import voluptuous as vol
|
import voluptuous as vol
|
||||||
@ -191,7 +192,7 @@ class ControllerManager:
|
|||||||
# Update players
|
# Update players
|
||||||
self._hass.helpers.dispatcher.async_dispatcher_send(SIGNAL_HEOS_UPDATED)
|
self._hass.helpers.dispatcher.async_dispatcher_send(SIGNAL_HEOS_UPDATED)
|
||||||
|
|
||||||
def update_ids(self, mapped_ids: Dict[int, int]):
|
def update_ids(self, mapped_ids: dict[int, int]):
|
||||||
"""Update the IDs in the device and entity registry."""
|
"""Update the IDs in the device and entity registry."""
|
||||||
# mapped_ids contains the mapped IDs (new:old)
|
# mapped_ids contains the mapped IDs (new:old)
|
||||||
for new_id, old_id in mapped_ids.items():
|
for new_id, old_id in mapped_ids.items():
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
"""Support for HERE travel time sensors."""
|
"""Support for HERE travel time sensors."""
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
from datetime import datetime, timedelta
|
from datetime import datetime, timedelta
|
||||||
import logging
|
import logging
|
||||||
from typing import Callable, Dict, Optional, Union
|
from typing import Callable
|
||||||
|
|
||||||
import herepy
|
import herepy
|
||||||
import voluptuous as vol
|
import voluptuous as vol
|
||||||
@ -143,9 +145,9 @@ PLATFORM_SCHEMA = vol.All(
|
|||||||
|
|
||||||
async def async_setup_platform(
|
async def async_setup_platform(
|
||||||
hass: HomeAssistant,
|
hass: HomeAssistant,
|
||||||
config: Dict[str, Union[str, bool]],
|
config: dict[str, str | bool],
|
||||||
async_add_entities: Callable,
|
async_add_entities: Callable,
|
||||||
discovery_info: Optional[DiscoveryInfoType] = None,
|
discovery_info: DiscoveryInfoType | None = None,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Set up the HERE travel time platform."""
|
"""Set up the HERE travel time platform."""
|
||||||
api_key = config[CONF_API_KEY]
|
api_key = config[CONF_API_KEY]
|
||||||
@ -255,7 +257,7 @@ class HERETravelTimeSensor(Entity):
|
|||||||
)
|
)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def state(self) -> Optional[str]:
|
def state(self) -> str | None:
|
||||||
"""Return the state of the sensor."""
|
"""Return the state of the sensor."""
|
||||||
if self._here_data.traffic_mode:
|
if self._here_data.traffic_mode:
|
||||||
if self._here_data.traffic_time is not None:
|
if self._here_data.traffic_time is not None:
|
||||||
@ -273,7 +275,7 @@ class HERETravelTimeSensor(Entity):
|
|||||||
@property
|
@property
|
||||||
def extra_state_attributes(
|
def extra_state_attributes(
|
||||||
self,
|
self,
|
||||||
) -> Optional[Dict[str, Union[None, float, str, bool]]]:
|
) -> dict[str, None | float | str | bool] | None:
|
||||||
"""Return the state attributes."""
|
"""Return the state attributes."""
|
||||||
if self._here_data.base_time is None:
|
if self._here_data.base_time is None:
|
||||||
return None
|
return None
|
||||||
@ -324,7 +326,7 @@ class HERETravelTimeSensor(Entity):
|
|||||||
|
|
||||||
await self.hass.async_add_executor_job(self._here_data.update)
|
await self.hass.async_add_executor_job(self._here_data.update)
|
||||||
|
|
||||||
async def _get_location_from_entity(self, entity_id: str) -> Optional[str]:
|
async def _get_location_from_entity(self, entity_id: str) -> str | None:
|
||||||
"""Get the location from the entity state or attributes."""
|
"""Get the location from the entity state or attributes."""
|
||||||
entity = self.hass.states.get(entity_id)
|
entity = self.hass.states.get(entity_id)
|
||||||
|
|
||||||
@ -480,7 +482,7 @@ class HERETravelTimeData:
|
|||||||
self.destination_name = waypoint[1]["mappedRoadName"]
|
self.destination_name = waypoint[1]["mappedRoadName"]
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _build_hass_attribution(source_attribution: Dict) -> Optional[str]:
|
def _build_hass_attribution(source_attribution: dict) -> str | None:
|
||||||
"""Build a hass frontend ready string out of the sourceAttribution."""
|
"""Build a hass frontend ready string out of the sourceAttribution."""
|
||||||
suppliers = source_attribution.get("supplier")
|
suppliers = source_attribution.get("supplier")
|
||||||
if suppliers is not None:
|
if suppliers is not None:
|
||||||
|
@ -1,11 +1,13 @@
|
|||||||
"""Provide pre-made queries on top of the recorder component."""
|
"""Provide pre-made queries on top of the recorder component."""
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
from collections import defaultdict
|
from collections import defaultdict
|
||||||
from datetime import datetime as dt, timedelta
|
from datetime import datetime as dt, timedelta
|
||||||
from itertools import groupby
|
from itertools import groupby
|
||||||
import json
|
import json
|
||||||
import logging
|
import logging
|
||||||
import time
|
import time
|
||||||
from typing import Iterable, Optional, cast
|
from typing import Iterable, cast
|
||||||
|
|
||||||
from aiohttp import web
|
from aiohttp import web
|
||||||
from sqlalchemy import and_, bindparam, func, not_, or_
|
from sqlalchemy import and_, bindparam, func, not_, or_
|
||||||
@ -462,7 +464,7 @@ class HistoryPeriodView(HomeAssistantView):
|
|||||||
self.use_include_order = use_include_order
|
self.use_include_order = use_include_order
|
||||||
|
|
||||||
async def get(
|
async def get(
|
||||||
self, request: web.Request, datetime: Optional[str] = None
|
self, request: web.Request, datetime: str | None = None
|
||||||
) -> web.Response:
|
) -> web.Response:
|
||||||
"""Return history over a period of time."""
|
"""Return history over a period of time."""
|
||||||
datetime_ = None
|
datetime_ = None
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
"""Allow users to set and activate scenes."""
|
"""Allow users to set and activate scenes."""
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
from collections import namedtuple
|
from collections import namedtuple
|
||||||
import logging
|
import logging
|
||||||
from typing import Any, List
|
from typing import Any
|
||||||
|
|
||||||
import voluptuous as vol
|
import voluptuous as vol
|
||||||
|
|
||||||
@ -118,7 +120,7 @@ _LOGGER = logging.getLogger(__name__)
|
|||||||
|
|
||||||
|
|
||||||
@callback
|
@callback
|
||||||
def scenes_with_entity(hass: HomeAssistant, entity_id: str) -> List[str]:
|
def scenes_with_entity(hass: HomeAssistant, entity_id: str) -> list[str]:
|
||||||
"""Return all scenes that reference the entity."""
|
"""Return all scenes that reference the entity."""
|
||||||
if DATA_PLATFORM not in hass.data:
|
if DATA_PLATFORM not in hass.data:
|
||||||
return []
|
return []
|
||||||
@ -133,7 +135,7 @@ def scenes_with_entity(hass: HomeAssistant, entity_id: str) -> List[str]:
|
|||||||
|
|
||||||
|
|
||||||
@callback
|
@callback
|
||||||
def entities_in_scene(hass: HomeAssistant, entity_id: str) -> List[str]:
|
def entities_in_scene(hass: HomeAssistant, entity_id: str) -> list[str]:
|
||||||
"""Return all entities in a scene."""
|
"""Return all entities in a scene."""
|
||||||
if DATA_PLATFORM not in hass.data:
|
if DATA_PLATFORM not in hass.data:
|
||||||
return []
|
return []
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
"""Offer state listening automation rules."""
|
"""Offer state listening automation rules."""
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
from datetime import timedelta
|
from datetime import timedelta
|
||||||
import logging
|
import logging
|
||||||
from typing import Any, Dict, Optional
|
from typing import Any
|
||||||
|
|
||||||
import voluptuous as vol
|
import voluptuous as vol
|
||||||
|
|
||||||
@ -79,7 +81,7 @@ async def async_attach_trigger(
|
|||||||
template.attach(hass, time_delta)
|
template.attach(hass, time_delta)
|
||||||
match_all = from_state == MATCH_ALL and to_state == MATCH_ALL
|
match_all = from_state == MATCH_ALL and to_state == MATCH_ALL
|
||||||
unsub_track_same = {}
|
unsub_track_same = {}
|
||||||
period: Dict[str, timedelta] = {}
|
period: dict[str, timedelta] = {}
|
||||||
match_from_state = process_state_match(from_state)
|
match_from_state = process_state_match(from_state)
|
||||||
match_to_state = process_state_match(to_state)
|
match_to_state = process_state_match(to_state)
|
||||||
attribute = config.get(CONF_ATTRIBUTE)
|
attribute = config.get(CONF_ATTRIBUTE)
|
||||||
@ -93,8 +95,8 @@ async def async_attach_trigger(
|
|||||||
def state_automation_listener(event: Event):
|
def state_automation_listener(event: Event):
|
||||||
"""Listen for state changes and calls action."""
|
"""Listen for state changes and calls action."""
|
||||||
entity: str = event.data["entity_id"]
|
entity: str = event.data["entity_id"]
|
||||||
from_s: Optional[State] = event.data.get("old_state")
|
from_s: State | None = event.data.get("old_state")
|
||||||
to_s: Optional[State] = event.data.get("new_state")
|
to_s: State | None = event.data.get("new_state")
|
||||||
|
|
||||||
if from_s is None:
|
if from_s is None:
|
||||||
old_value = None
|
old_value = None
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
"""Support for Homekit device discovery."""
|
"""Support for Homekit device discovery."""
|
||||||
from typing import Any, Dict
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from typing import Any
|
||||||
|
|
||||||
import aiohomekit
|
import aiohomekit
|
||||||
from aiohomekit.model import Accessory
|
from aiohomekit.model import Accessory
|
||||||
@ -77,7 +79,7 @@ class HomeKitEntity(Entity):
|
|||||||
signal_remove()
|
signal_remove()
|
||||||
self._signals.clear()
|
self._signals.clear()
|
||||||
|
|
||||||
async def async_put_characteristics(self, characteristics: Dict[str, Any]):
|
async def async_put_characteristics(self, characteristics: dict[str, Any]):
|
||||||
"""
|
"""
|
||||||
Write characteristics to the device.
|
Write characteristics to the device.
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
"""Provides device automations for homekit devices."""
|
"""Provides device automations for homekit devices."""
|
||||||
from typing import List
|
from __future__ import annotations
|
||||||
|
|
||||||
from aiohomekit.model.characteristics import CharacteristicsTypes
|
from aiohomekit.model.characteristics import CharacteristicsTypes
|
||||||
from aiohomekit.model.characteristics.const import InputEventValues
|
from aiohomekit.model.characteristics.const import InputEventValues
|
||||||
@ -226,7 +226,7 @@ def async_fire_triggers(conn, events):
|
|||||||
source.fire(iid, ev)
|
source.fire(iid, ev)
|
||||||
|
|
||||||
|
|
||||||
async def async_get_triggers(hass: HomeAssistant, device_id: str) -> List[dict]:
|
async def async_get_triggers(hass: HomeAssistant, device_id: str) -> list[dict]:
|
||||||
"""List device triggers for homekit devices."""
|
"""List device triggers for homekit devices."""
|
||||||
|
|
||||||
if device_id not in hass.data.get(TRIGGERS, {}):
|
if device_id not in hass.data.get(TRIGGERS, {}):
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
"""Support for HomeKit Controller humidifier."""
|
"""Support for HomeKit Controller humidifier."""
|
||||||
from typing import List, Optional
|
from __future__ import annotations
|
||||||
|
|
||||||
from aiohomekit.model.characteristics import CharacteristicsTypes
|
from aiohomekit.model.characteristics import CharacteristicsTypes
|
||||||
from aiohomekit.model.services import ServicesTypes
|
from aiohomekit.model.services import ServicesTypes
|
||||||
@ -69,14 +69,14 @@ class HomeKitHumidifier(HomeKitEntity, HumidifierEntity):
|
|||||||
await self.async_put_characteristics({CharacteristicsTypes.ACTIVE: False})
|
await self.async_put_characteristics({CharacteristicsTypes.ACTIVE: False})
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def target_humidity(self) -> Optional[int]:
|
def target_humidity(self) -> int | None:
|
||||||
"""Return the humidity we try to reach."""
|
"""Return the humidity we try to reach."""
|
||||||
return self.service.value(
|
return self.service.value(
|
||||||
CharacteristicsTypes.RELATIVE_HUMIDITY_HUMIDIFIER_THRESHOLD
|
CharacteristicsTypes.RELATIVE_HUMIDITY_HUMIDIFIER_THRESHOLD
|
||||||
)
|
)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def mode(self) -> Optional[str]:
|
def mode(self) -> str | None:
|
||||||
"""Return the current mode, e.g., home, auto, baby.
|
"""Return the current mode, e.g., home, auto, baby.
|
||||||
|
|
||||||
Requires SUPPORT_MODES.
|
Requires SUPPORT_MODES.
|
||||||
@ -87,7 +87,7 @@ class HomeKitHumidifier(HomeKitEntity, HumidifierEntity):
|
|||||||
return MODE_AUTO if mode == 1 else MODE_NORMAL
|
return MODE_AUTO if mode == 1 else MODE_NORMAL
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def available_modes(self) -> Optional[List[str]]:
|
def available_modes(self) -> list[str] | None:
|
||||||
"""Return a list of available modes.
|
"""Return a list of available modes.
|
||||||
|
|
||||||
Requires SUPPORT_MODES.
|
Requires SUPPORT_MODES.
|
||||||
@ -175,14 +175,14 @@ class HomeKitDehumidifier(HomeKitEntity, HumidifierEntity):
|
|||||||
await self.async_put_characteristics({CharacteristicsTypes.ACTIVE: False})
|
await self.async_put_characteristics({CharacteristicsTypes.ACTIVE: False})
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def target_humidity(self) -> Optional[int]:
|
def target_humidity(self) -> int | None:
|
||||||
"""Return the humidity we try to reach."""
|
"""Return the humidity we try to reach."""
|
||||||
return self.service.value(
|
return self.service.value(
|
||||||
CharacteristicsTypes.RELATIVE_HUMIDITY_DEHUMIDIFIER_THRESHOLD
|
CharacteristicsTypes.RELATIVE_HUMIDITY_DEHUMIDIFIER_THRESHOLD
|
||||||
)
|
)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def mode(self) -> Optional[str]:
|
def mode(self) -> str | None:
|
||||||
"""Return the current mode, e.g., home, auto, baby.
|
"""Return the current mode, e.g., home, auto, baby.
|
||||||
|
|
||||||
Requires SUPPORT_MODES.
|
Requires SUPPORT_MODES.
|
||||||
@ -193,7 +193,7 @@ class HomeKitDehumidifier(HomeKitEntity, HumidifierEntity):
|
|||||||
return MODE_AUTO if mode == 1 else MODE_NORMAL
|
return MODE_AUTO if mode == 1 else MODE_NORMAL
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def available_modes(self) -> Optional[List[str]]:
|
def available_modes(self) -> list[str] | None:
|
||||||
"""Return a list of available modes.
|
"""Return a list of available modes.
|
||||||
|
|
||||||
Requires SUPPORT_MODES.
|
Requires SUPPORT_MODES.
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
"""Support for HomematicIP Cloud alarm control panel."""
|
"""Support for HomematicIP Cloud alarm control panel."""
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
from typing import Any, Dict
|
from typing import Any
|
||||||
|
|
||||||
from homematicip.functionalHomes import SecurityAndAlarmHome
|
from homematicip.functionalHomes import SecurityAndAlarmHome
|
||||||
|
|
||||||
@ -44,7 +46,7 @@ class HomematicipAlarmControlPanelEntity(AlarmControlPanelEntity):
|
|||||||
_LOGGER.info("Setting up %s", self.name)
|
_LOGGER.info("Setting up %s", self.name)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def device_info(self) -> Dict[str, Any]:
|
def device_info(self) -> dict[str, Any]:
|
||||||
"""Return device specific attributes."""
|
"""Return device specific attributes."""
|
||||||
return {
|
return {
|
||||||
"identifiers": {(HMIPC_DOMAIN, f"ACP {self._home.id}")},
|
"identifiers": {(HMIPC_DOMAIN, f"ACP {self._home.id}")},
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
"""Support for HomematicIP Cloud binary sensor."""
|
"""Support for HomematicIP Cloud binary sensor."""
|
||||||
from typing import Any, Dict
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from typing import Any
|
||||||
|
|
||||||
from homematicip.aio.device import (
|
from homematicip.aio.device import (
|
||||||
AsyncAccelerationSensor,
|
AsyncAccelerationSensor,
|
||||||
@ -166,7 +168,7 @@ class HomematicipCloudConnectionSensor(HomematicipGenericEntity, BinarySensorEnt
|
|||||||
return name if not self._home.name else f"{self._home.name} {name}"
|
return name if not self._home.name else f"{self._home.name} {name}"
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def device_info(self) -> Dict[str, Any]:
|
def device_info(self) -> dict[str, Any]:
|
||||||
"""Return device specific attributes."""
|
"""Return device specific attributes."""
|
||||||
# Adds a sensor to the existing HAP device
|
# Adds a sensor to the existing HAP device
|
||||||
return {
|
return {
|
||||||
@ -210,7 +212,7 @@ class HomematicipBaseActionSensor(HomematicipGenericEntity, BinarySensorEntity):
|
|||||||
return self._device.accelerationSensorTriggered
|
return self._device.accelerationSensorTriggered
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def extra_state_attributes(self) -> Dict[str, Any]:
|
def extra_state_attributes(self) -> dict[str, Any]:
|
||||||
"""Return the state attributes of the acceleration sensor."""
|
"""Return the state attributes of the acceleration sensor."""
|
||||||
state_attr = super().extra_state_attributes
|
state_attr = super().extra_state_attributes
|
||||||
|
|
||||||
@ -285,7 +287,7 @@ class HomematicipShutterContact(HomematicipMultiContactInterface, BinarySensorEn
|
|||||||
return DEVICE_CLASS_DOOR
|
return DEVICE_CLASS_DOOR
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def extra_state_attributes(self) -> Dict[str, Any]:
|
def extra_state_attributes(self) -> dict[str, Any]:
|
||||||
"""Return the state attributes of the Shutter Contact."""
|
"""Return the state attributes of the Shutter Contact."""
|
||||||
state_attr = super().extra_state_attributes
|
state_attr = super().extra_state_attributes
|
||||||
|
|
||||||
@ -412,7 +414,7 @@ class HomematicipSunshineSensor(HomematicipGenericEntity, BinarySensorEntity):
|
|||||||
return self._device.sunshine
|
return self._device.sunshine
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def extra_state_attributes(self) -> Dict[str, Any]:
|
def extra_state_attributes(self) -> dict[str, Any]:
|
||||||
"""Return the state attributes of the illuminance sensor."""
|
"""Return the state attributes of the illuminance sensor."""
|
||||||
state_attr = super().extra_state_attributes
|
state_attr = super().extra_state_attributes
|
||||||
|
|
||||||
@ -482,7 +484,7 @@ class HomematicipSecurityZoneSensorGroup(HomematicipGenericEntity, BinarySensorE
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def extra_state_attributes(self) -> Dict[str, Any]:
|
def extra_state_attributes(self) -> dict[str, Any]:
|
||||||
"""Return the state attributes of the security zone group."""
|
"""Return the state attributes of the security zone group."""
|
||||||
state_attr = super().extra_state_attributes
|
state_attr = super().extra_state_attributes
|
||||||
|
|
||||||
@ -526,7 +528,7 @@ class HomematicipSecuritySensorGroup(
|
|||||||
super().__init__(hap, device, post="Sensors")
|
super().__init__(hap, device, post="Sensors")
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def extra_state_attributes(self) -> Dict[str, Any]:
|
def extra_state_attributes(self) -> dict[str, Any]:
|
||||||
"""Return the state attributes of the security group."""
|
"""Return the state attributes of the security group."""
|
||||||
state_attr = super().extra_state_attributes
|
state_attr = super().extra_state_attributes
|
||||||
|
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
"""Support for HomematicIP Cloud climate devices."""
|
"""Support for HomematicIP Cloud climate devices."""
|
||||||
from typing import Any, Dict, List, Optional, Union
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from typing import Any
|
||||||
|
|
||||||
from homematicip.aio.device import AsyncHeatingThermostat, AsyncHeatingThermostatCompact
|
from homematicip.aio.device import AsyncHeatingThermostat, AsyncHeatingThermostatCompact
|
||||||
from homematicip.aio.group import AsyncHeatingGroup
|
from homematicip.aio.group import AsyncHeatingGroup
|
||||||
@ -71,7 +73,7 @@ class HomematicipHeatingGroup(HomematicipGenericEntity, ClimateEntity):
|
|||||||
self._simple_heating = self._first_radiator_thermostat
|
self._simple_heating = self._first_radiator_thermostat
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def device_info(self) -> Dict[str, Any]:
|
def device_info(self) -> dict[str, Any]:
|
||||||
"""Return device specific attributes."""
|
"""Return device specific attributes."""
|
||||||
return {
|
return {
|
||||||
"identifiers": {(HMIPC_DOMAIN, self._device.id)},
|
"identifiers": {(HMIPC_DOMAIN, self._device.id)},
|
||||||
@ -121,7 +123,7 @@ class HomematicipHeatingGroup(HomematicipGenericEntity, ClimateEntity):
|
|||||||
return HVAC_MODE_AUTO
|
return HVAC_MODE_AUTO
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def hvac_modes(self) -> List[str]:
|
def hvac_modes(self) -> list[str]:
|
||||||
"""Return the list of available hvac operation modes."""
|
"""Return the list of available hvac operation modes."""
|
||||||
if self._disabled_by_cooling_mode and not self._has_switch:
|
if self._disabled_by_cooling_mode and not self._has_switch:
|
||||||
return [HVAC_MODE_OFF]
|
return [HVAC_MODE_OFF]
|
||||||
@ -133,7 +135,7 @@ class HomematicipHeatingGroup(HomematicipGenericEntity, ClimateEntity):
|
|||||||
)
|
)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def hvac_action(self) -> Optional[str]:
|
def hvac_action(self) -> str | None:
|
||||||
"""
|
"""
|
||||||
Return the current hvac_action.
|
Return the current hvac_action.
|
||||||
|
|
||||||
@ -151,7 +153,7 @@ class HomematicipHeatingGroup(HomematicipGenericEntity, ClimateEntity):
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def preset_mode(self) -> Optional[str]:
|
def preset_mode(self) -> str | None:
|
||||||
"""Return the current preset mode."""
|
"""Return the current preset mode."""
|
||||||
if self._device.boostMode:
|
if self._device.boostMode:
|
||||||
return PRESET_BOOST
|
return PRESET_BOOST
|
||||||
@ -174,7 +176,7 @@ class HomematicipHeatingGroup(HomematicipGenericEntity, ClimateEntity):
|
|||||||
)
|
)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def preset_modes(self) -> List[str]:
|
def preset_modes(self) -> list[str]:
|
||||||
"""Return a list of available preset modes incl. hmip profiles."""
|
"""Return a list of available preset modes incl. hmip profiles."""
|
||||||
# Boost is only available if a radiator thermostat is in the room,
|
# Boost is only available if a radiator thermostat is in the room,
|
||||||
# and heat mode is enabled.
|
# and heat mode is enabled.
|
||||||
@ -237,7 +239,7 @@ class HomematicipHeatingGroup(HomematicipGenericEntity, ClimateEntity):
|
|||||||
await self._device.set_active_profile(profile_idx)
|
await self._device.set_active_profile(profile_idx)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def extra_state_attributes(self) -> Dict[str, Any]:
|
def extra_state_attributes(self) -> dict[str, Any]:
|
||||||
"""Return the state attributes of the access point."""
|
"""Return the state attributes of the access point."""
|
||||||
state_attr = super().extra_state_attributes
|
state_attr = super().extra_state_attributes
|
||||||
|
|
||||||
@ -259,7 +261,7 @@ class HomematicipHeatingGroup(HomematicipGenericEntity, ClimateEntity):
|
|||||||
return self._home.get_functionalHome(IndoorClimateHome)
|
return self._home.get_functionalHome(IndoorClimateHome)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def _device_profiles(self) -> List[str]:
|
def _device_profiles(self) -> list[str]:
|
||||||
"""Return the relevant profiles."""
|
"""Return the relevant profiles."""
|
||||||
return [
|
return [
|
||||||
profile
|
profile
|
||||||
@ -270,7 +272,7 @@ class HomematicipHeatingGroup(HomematicipGenericEntity, ClimateEntity):
|
|||||||
]
|
]
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def _device_profile_names(self) -> List[str]:
|
def _device_profile_names(self) -> list[str]:
|
||||||
"""Return a collection of profile names."""
|
"""Return a collection of profile names."""
|
||||||
return [profile.name for profile in self._device_profiles]
|
return [profile.name for profile in self._device_profiles]
|
||||||
|
|
||||||
@ -298,7 +300,7 @@ class HomematicipHeatingGroup(HomematicipGenericEntity, ClimateEntity):
|
|||||||
)
|
)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def _relevant_profile_group(self) -> List[str]:
|
def _relevant_profile_group(self) -> list[str]:
|
||||||
"""Return the relevant profile groups."""
|
"""Return the relevant profile groups."""
|
||||||
if self._disabled_by_cooling_mode:
|
if self._disabled_by_cooling_mode:
|
||||||
return []
|
return []
|
||||||
@ -322,7 +324,7 @@ class HomematicipHeatingGroup(HomematicipGenericEntity, ClimateEntity):
|
|||||||
@property
|
@property
|
||||||
def _first_radiator_thermostat(
|
def _first_radiator_thermostat(
|
||||||
self,
|
self,
|
||||||
) -> Optional[Union[AsyncHeatingThermostat, AsyncHeatingThermostatCompact]]:
|
) -> AsyncHeatingThermostat | AsyncHeatingThermostatCompact | None:
|
||||||
"""Return the first radiator thermostat from the hmip heating group."""
|
"""Return the first radiator thermostat from the hmip heating group."""
|
||||||
for device in self._device.devices:
|
for device in self._device.devices:
|
||||||
if isinstance(
|
if isinstance(
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
"""Config flow to configure the HomematicIP Cloud component."""
|
"""Config flow to configure the HomematicIP Cloud component."""
|
||||||
from typing import Any, Dict
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from typing import Any
|
||||||
|
|
||||||
import voluptuous as vol
|
import voluptuous as vol
|
||||||
|
|
||||||
@ -27,11 +29,11 @@ class HomematicipCloudFlowHandler(config_entries.ConfigFlow):
|
|||||||
"""Initialize HomematicIP Cloud config flow."""
|
"""Initialize HomematicIP Cloud config flow."""
|
||||||
self.auth = None
|
self.auth = None
|
||||||
|
|
||||||
async def async_step_user(self, user_input=None) -> Dict[str, Any]:
|
async def async_step_user(self, user_input=None) -> dict[str, Any]:
|
||||||
"""Handle a flow initialized by the user."""
|
"""Handle a flow initialized by the user."""
|
||||||
return await self.async_step_init(user_input)
|
return await self.async_step_init(user_input)
|
||||||
|
|
||||||
async def async_step_init(self, user_input=None) -> Dict[str, Any]:
|
async def async_step_init(self, user_input=None) -> dict[str, Any]:
|
||||||
"""Handle a flow start."""
|
"""Handle a flow start."""
|
||||||
errors = {}
|
errors = {}
|
||||||
|
|
||||||
@ -62,7 +64,7 @@ class HomematicipCloudFlowHandler(config_entries.ConfigFlow):
|
|||||||
errors=errors,
|
errors=errors,
|
||||||
)
|
)
|
||||||
|
|
||||||
async def async_step_link(self, user_input=None) -> Dict[str, Any]:
|
async def async_step_link(self, user_input=None) -> dict[str, Any]:
|
||||||
"""Attempt to link with the HomematicIP Cloud access point."""
|
"""Attempt to link with the HomematicIP Cloud access point."""
|
||||||
errors = {}
|
errors = {}
|
||||||
|
|
||||||
@ -84,7 +86,7 @@ class HomematicipCloudFlowHandler(config_entries.ConfigFlow):
|
|||||||
|
|
||||||
return self.async_show_form(step_id="link", errors=errors)
|
return self.async_show_form(step_id="link", errors=errors)
|
||||||
|
|
||||||
async def async_step_import(self, import_info) -> Dict[str, Any]:
|
async def async_step_import(self, import_info) -> dict[str, Any]:
|
||||||
"""Import a new access point as a config entry."""
|
"""Import a new access point as a config entry."""
|
||||||
hapid = import_info[HMIPC_HAPID].replace("-", "").upper()
|
hapid = import_info[HMIPC_HAPID].replace("-", "").upper()
|
||||||
authtoken = import_info[HMIPC_AUTHTOKEN]
|
authtoken = import_info[HMIPC_AUTHTOKEN]
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
"""Support for HomematicIP Cloud cover devices."""
|
"""Support for HomematicIP Cloud cover devices."""
|
||||||
from typing import Optional
|
from __future__ import annotations
|
||||||
|
|
||||||
from homematicip.aio.device import (
|
from homematicip.aio.device import (
|
||||||
AsyncBlindModule,
|
AsyncBlindModule,
|
||||||
@ -95,7 +95,7 @@ class HomematicipBlindModule(HomematicipGenericEntity, CoverEntity):
|
|||||||
)
|
)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def is_closed(self) -> Optional[bool]:
|
def is_closed(self) -> bool | None:
|
||||||
"""Return if the cover is closed."""
|
"""Return if the cover is closed."""
|
||||||
if self._device.primaryShadingLevel is not None:
|
if self._device.primaryShadingLevel is not None:
|
||||||
return self._device.primaryShadingLevel == HMIP_COVER_CLOSED
|
return self._device.primaryShadingLevel == HMIP_COVER_CLOSED
|
||||||
@ -168,7 +168,7 @@ class HomematicipMultiCoverShutter(HomematicipGenericEntity, CoverEntity):
|
|||||||
await self._device.set_shutter_level(level, self._channel)
|
await self._device.set_shutter_level(level, self._channel)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def is_closed(self) -> Optional[bool]:
|
def is_closed(self) -> bool | None:
|
||||||
"""Return if the cover is closed."""
|
"""Return if the cover is closed."""
|
||||||
if self._device.functionalChannels[self._channel].shutterLevel is not None:
|
if self._device.functionalChannels[self._channel].shutterLevel is not None:
|
||||||
return (
|
return (
|
||||||
@ -265,7 +265,7 @@ class HomematicipGarageDoorModule(HomematicipGenericEntity, CoverEntity):
|
|||||||
return door_state_to_position.get(self._device.doorState)
|
return door_state_to_position.get(self._device.doorState)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def is_closed(self) -> Optional[bool]:
|
def is_closed(self) -> bool | None:
|
||||||
"""Return if the cover is closed."""
|
"""Return if the cover is closed."""
|
||||||
return self._device.doorState == DoorState.CLOSED
|
return self._device.doorState == DoorState.CLOSED
|
||||||
|
|
||||||
@ -305,7 +305,7 @@ class HomematicipCoverShutterGroup(HomematicipGenericEntity, CoverEntity):
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def is_closed(self) -> Optional[bool]:
|
def is_closed(self) -> bool | None:
|
||||||
"""Return if the cover is closed."""
|
"""Return if the cover is closed."""
|
||||||
if self._device.shutterLevel is not None:
|
if self._device.shutterLevel is not None:
|
||||||
return self._device.shutterLevel == HMIP_COVER_CLOSED
|
return self._device.shutterLevel == HMIP_COVER_CLOSED
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
"""Generic entity for the HomematicIP Cloud component."""
|
"""Generic entity for the HomematicIP Cloud component."""
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
from typing import Any, Dict, Optional
|
from typing import Any
|
||||||
|
|
||||||
from homematicip.aio.device import AsyncDevice
|
from homematicip.aio.device import AsyncDevice
|
||||||
from homematicip.aio.group import AsyncGroup
|
from homematicip.aio.group import AsyncGroup
|
||||||
@ -74,9 +76,9 @@ class HomematicipGenericEntity(Entity):
|
|||||||
self,
|
self,
|
||||||
hap: HomematicipHAP,
|
hap: HomematicipHAP,
|
||||||
device,
|
device,
|
||||||
post: Optional[str] = None,
|
post: str | None = None,
|
||||||
channel: Optional[int] = None,
|
channel: int | None = None,
|
||||||
is_multi_channel: Optional[bool] = False,
|
is_multi_channel: bool | None = False,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Initialize the generic entity."""
|
"""Initialize the generic entity."""
|
||||||
self._hap = hap
|
self._hap = hap
|
||||||
@ -90,7 +92,7 @@ class HomematicipGenericEntity(Entity):
|
|||||||
_LOGGER.info("Setting up %s (%s)", self.name, self._device.modelType)
|
_LOGGER.info("Setting up %s (%s)", self.name, self._device.modelType)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def device_info(self) -> Dict[str, Any]:
|
def device_info(self) -> dict[str, Any]:
|
||||||
"""Return device specific attributes."""
|
"""Return device specific attributes."""
|
||||||
# Only physical devices should be HA devices.
|
# Only physical devices should be HA devices.
|
||||||
if isinstance(self._device, AsyncDevice):
|
if isinstance(self._device, AsyncDevice):
|
||||||
@ -223,7 +225,7 @@ class HomematicipGenericEntity(Entity):
|
|||||||
return unique_id
|
return unique_id
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def icon(self) -> Optional[str]:
|
def icon(self) -> str | None:
|
||||||
"""Return the icon."""
|
"""Return the icon."""
|
||||||
for attr, icon in DEVICE_ATTRIBUTE_ICONS.items():
|
for attr, icon in DEVICE_ATTRIBUTE_ICONS.items():
|
||||||
if getattr(self._device, attr, None):
|
if getattr(self._device, attr, None):
|
||||||
@ -232,7 +234,7 @@ class HomematicipGenericEntity(Entity):
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def extra_state_attributes(self) -> Dict[str, Any]:
|
def extra_state_attributes(self) -> dict[str, Any]:
|
||||||
"""Return the state attributes of the generic entity."""
|
"""Return the state attributes of the generic entity."""
|
||||||
state_attr = {}
|
state_attr = {}
|
||||||
|
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
"""Support for HomematicIP Cloud lights."""
|
"""Support for HomematicIP Cloud lights."""
|
||||||
from typing import Any, Dict
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from typing import Any
|
||||||
|
|
||||||
from homematicip.aio.device import (
|
from homematicip.aio.device import (
|
||||||
AsyncBrandDimmer,
|
AsyncBrandDimmer,
|
||||||
@ -90,7 +92,7 @@ class HomematicipLightMeasuring(HomematicipLight):
|
|||||||
"""Representation of the HomematicIP measuring light."""
|
"""Representation of the HomematicIP measuring light."""
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def extra_state_attributes(self) -> Dict[str, Any]:
|
def extra_state_attributes(self) -> dict[str, Any]:
|
||||||
"""Return the state attributes of the light."""
|
"""Return the state attributes of the light."""
|
||||||
state_attr = super().extra_state_attributes
|
state_attr = super().extra_state_attributes
|
||||||
|
|
||||||
@ -206,7 +208,7 @@ class HomematicipNotificationLight(HomematicipGenericEntity, LightEntity):
|
|||||||
return self._color_switcher.get(simple_rgb_color, [0.0, 0.0])
|
return self._color_switcher.get(simple_rgb_color, [0.0, 0.0])
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def extra_state_attributes(self) -> Dict[str, Any]:
|
def extra_state_attributes(self) -> dict[str, Any]:
|
||||||
"""Return the state attributes of the notification light sensor."""
|
"""Return the state attributes of the notification light sensor."""
|
||||||
state_attr = super().extra_state_attributes
|
state_attr = super().extra_state_attributes
|
||||||
|
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
"""Support for HomematicIP Cloud sensors."""
|
"""Support for HomematicIP Cloud sensors."""
|
||||||
from typing import Any, Dict
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from typing import Any
|
||||||
|
|
||||||
from homematicip.aio.device import (
|
from homematicip.aio.device import (
|
||||||
AsyncBrandSwitchMeasuring,
|
AsyncBrandSwitchMeasuring,
|
||||||
@ -222,7 +224,7 @@ class HomematicipTemperatureSensor(HomematicipGenericEntity):
|
|||||||
return TEMP_CELSIUS
|
return TEMP_CELSIUS
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def extra_state_attributes(self) -> Dict[str, Any]:
|
def extra_state_attributes(self) -> dict[str, Any]:
|
||||||
"""Return the state attributes of the windspeed sensor."""
|
"""Return the state attributes of the windspeed sensor."""
|
||||||
state_attr = super().extra_state_attributes
|
state_attr = super().extra_state_attributes
|
||||||
|
|
||||||
@ -259,7 +261,7 @@ class HomematicipIlluminanceSensor(HomematicipGenericEntity):
|
|||||||
return LIGHT_LUX
|
return LIGHT_LUX
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def extra_state_attributes(self) -> Dict[str, Any]:
|
def extra_state_attributes(self) -> dict[str, Any]:
|
||||||
"""Return the state attributes of the wind speed sensor."""
|
"""Return the state attributes of the wind speed sensor."""
|
||||||
state_attr = super().extra_state_attributes
|
state_attr = super().extra_state_attributes
|
||||||
|
|
||||||
@ -312,7 +314,7 @@ class HomematicipWindspeedSensor(HomematicipGenericEntity):
|
|||||||
return SPEED_KILOMETERS_PER_HOUR
|
return SPEED_KILOMETERS_PER_HOUR
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def extra_state_attributes(self) -> Dict[str, Any]:
|
def extra_state_attributes(self) -> dict[str, Any]:
|
||||||
"""Return the state attributes of the wind speed sensor."""
|
"""Return the state attributes of the wind speed sensor."""
|
||||||
state_attr = super().extra_state_attributes
|
state_attr = super().extra_state_attributes
|
||||||
|
|
||||||
@ -354,7 +356,7 @@ class HomematicipPassageDetectorDeltaCounter(HomematicipGenericEntity):
|
|||||||
return self._device.leftRightCounterDelta
|
return self._device.leftRightCounterDelta
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def extra_state_attributes(self) -> Dict[str, Any]:
|
def extra_state_attributes(self) -> dict[str, Any]:
|
||||||
"""Return the state attributes of the delta counter."""
|
"""Return the state attributes of the delta counter."""
|
||||||
state_attr = super().extra_state_attributes
|
state_attr = super().extra_state_attributes
|
||||||
|
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
"""Support for HomematicIP Cloud devices."""
|
"""Support for HomematicIP Cloud devices."""
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import Optional
|
|
||||||
|
|
||||||
from homematicip.aio.device import AsyncSwitchMeasuring
|
from homematicip.aio.device import AsyncSwitchMeasuring
|
||||||
from homematicip.aio.group import AsyncHeatingGroup
|
from homematicip.aio.group import AsyncHeatingGroup
|
||||||
@ -342,7 +343,7 @@ async def _async_reset_energy_counter(
|
|||||||
await device.reset_energy_counter()
|
await device.reset_energy_counter()
|
||||||
|
|
||||||
|
|
||||||
def _get_home(hass: HomeAssistantType, hapid: str) -> Optional[AsyncHome]:
|
def _get_home(hass: HomeAssistantType, hapid: str) -> AsyncHome | None:
|
||||||
"""Return a HmIP home."""
|
"""Return a HmIP home."""
|
||||||
hap = hass.data[HMIPC_DOMAIN].get(hapid)
|
hap = hass.data[HMIPC_DOMAIN].get(hapid)
|
||||||
if hap:
|
if hap:
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
"""Support for HomematicIP Cloud switches."""
|
"""Support for HomematicIP Cloud switches."""
|
||||||
from typing import Any, Dict
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from typing import Any
|
||||||
|
|
||||||
from homematicip.aio.device import (
|
from homematicip.aio.device import (
|
||||||
AsyncBrandSwitchMeasuring,
|
AsyncBrandSwitchMeasuring,
|
||||||
@ -141,7 +143,7 @@ class HomematicipGroupSwitch(HomematicipGenericEntity, SwitchEntity):
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def extra_state_attributes(self) -> Dict[str, Any]:
|
def extra_state_attributes(self) -> dict[str, Any]:
|
||||||
"""Return the state attributes of the switch-group."""
|
"""Return the state attributes of the switch-group."""
|
||||||
state_attr = super().extra_state_attributes
|
state_attr = super().extra_state_attributes
|
||||||
|
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
"""Support for Honeywell (US) Total Connect Comfort climate systems."""
|
"""Support for Honeywell (US) Total Connect Comfort climate systems."""
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
import datetime
|
import datetime
|
||||||
import logging
|
import logging
|
||||||
from typing import Any, Dict, List, Optional
|
from typing import Any
|
||||||
|
|
||||||
import requests
|
import requests
|
||||||
import somecomfort
|
import somecomfort
|
||||||
@ -192,12 +194,12 @@ class HoneywellUSThermostat(ClimateEntity):
|
|||||||
self._supported_features |= SUPPORT_FAN_MODE
|
self._supported_features |= SUPPORT_FAN_MODE
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def name(self) -> Optional[str]:
|
def name(self) -> str | None:
|
||||||
"""Return the name of the honeywell, if any."""
|
"""Return the name of the honeywell, if any."""
|
||||||
return self._device.name
|
return self._device.name
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def extra_state_attributes(self) -> Dict[str, Any]:
|
def extra_state_attributes(self) -> dict[str, Any]:
|
||||||
"""Return the device specific state attributes."""
|
"""Return the device specific state attributes."""
|
||||||
data = {}
|
data = {}
|
||||||
data[ATTR_FAN_ACTION] = "running" if self._device.fan_running else "idle"
|
data[ATTR_FAN_ACTION] = "running" if self._device.fan_running else "idle"
|
||||||
@ -235,7 +237,7 @@ class HoneywellUSThermostat(ClimateEntity):
|
|||||||
return TEMP_CELSIUS if self._device.temperature_unit == "C" else TEMP_FAHRENHEIT
|
return TEMP_CELSIUS if self._device.temperature_unit == "C" else TEMP_FAHRENHEIT
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def current_humidity(self) -> Optional[int]:
|
def current_humidity(self) -> int | None:
|
||||||
"""Return the current humidity."""
|
"""Return the current humidity."""
|
||||||
return self._device.current_humidity
|
return self._device.current_humidity
|
||||||
|
|
||||||
@ -245,24 +247,24 @@ class HoneywellUSThermostat(ClimateEntity):
|
|||||||
return HW_MODE_TO_HVAC_MODE[self._device.system_mode]
|
return HW_MODE_TO_HVAC_MODE[self._device.system_mode]
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def hvac_modes(self) -> List[str]:
|
def hvac_modes(self) -> list[str]:
|
||||||
"""Return the list of available hvac operation modes."""
|
"""Return the list of available hvac operation modes."""
|
||||||
return list(self._hvac_mode_map)
|
return list(self._hvac_mode_map)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def hvac_action(self) -> Optional[str]:
|
def hvac_action(self) -> str | None:
|
||||||
"""Return the current running hvac operation if supported."""
|
"""Return the current running hvac operation if supported."""
|
||||||
if self.hvac_mode == HVAC_MODE_OFF:
|
if self.hvac_mode == HVAC_MODE_OFF:
|
||||||
return None
|
return None
|
||||||
return HW_MODE_TO_HA_HVAC_ACTION[self._device.equipment_output_status]
|
return HW_MODE_TO_HA_HVAC_ACTION[self._device.equipment_output_status]
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def current_temperature(self) -> Optional[float]:
|
def current_temperature(self) -> float | None:
|
||||||
"""Return the current temperature."""
|
"""Return the current temperature."""
|
||||||
return self._device.current_temperature
|
return self._device.current_temperature
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def target_temperature(self) -> Optional[float]:
|
def target_temperature(self) -> float | None:
|
||||||
"""Return the temperature we try to reach."""
|
"""Return the temperature we try to reach."""
|
||||||
if self.hvac_mode == HVAC_MODE_COOL:
|
if self.hvac_mode == HVAC_MODE_COOL:
|
||||||
return self._device.setpoint_cool
|
return self._device.setpoint_cool
|
||||||
@ -271,41 +273,41 @@ class HoneywellUSThermostat(ClimateEntity):
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def target_temperature_high(self) -> Optional[float]:
|
def target_temperature_high(self) -> float | None:
|
||||||
"""Return the highbound target temperature we try to reach."""
|
"""Return the highbound target temperature we try to reach."""
|
||||||
if self.hvac_mode == HVAC_MODE_HEAT_COOL:
|
if self.hvac_mode == HVAC_MODE_HEAT_COOL:
|
||||||
return self._device.setpoint_cool
|
return self._device.setpoint_cool
|
||||||
return None
|
return None
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def target_temperature_low(self) -> Optional[float]:
|
def target_temperature_low(self) -> float | None:
|
||||||
"""Return the lowbound target temperature we try to reach."""
|
"""Return the lowbound target temperature we try to reach."""
|
||||||
if self.hvac_mode == HVAC_MODE_HEAT_COOL:
|
if self.hvac_mode == HVAC_MODE_HEAT_COOL:
|
||||||
return self._device.setpoint_heat
|
return self._device.setpoint_heat
|
||||||
return None
|
return None
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def preset_mode(self) -> Optional[str]:
|
def preset_mode(self) -> str | None:
|
||||||
"""Return the current preset mode, e.g., home, away, temp."""
|
"""Return the current preset mode, e.g., home, away, temp."""
|
||||||
return PRESET_AWAY if self._away else None
|
return PRESET_AWAY if self._away else None
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def preset_modes(self) -> Optional[List[str]]:
|
def preset_modes(self) -> list[str] | None:
|
||||||
"""Return a list of available preset modes."""
|
"""Return a list of available preset modes."""
|
||||||
return [PRESET_NONE, PRESET_AWAY]
|
return [PRESET_NONE, PRESET_AWAY]
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def is_aux_heat(self) -> Optional[str]:
|
def is_aux_heat(self) -> str | None:
|
||||||
"""Return true if aux heater."""
|
"""Return true if aux heater."""
|
||||||
return self._device.system_mode == "emheat"
|
return self._device.system_mode == "emheat"
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def fan_mode(self) -> Optional[str]:
|
def fan_mode(self) -> str | None:
|
||||||
"""Return the fan setting."""
|
"""Return the fan setting."""
|
||||||
return HW_FAN_MODE_TO_HA[self._device.fan_mode]
|
return HW_FAN_MODE_TO_HA[self._device.fan_mode]
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def fan_modes(self) -> Optional[List[str]]:
|
def fan_modes(self) -> list[str] | None:
|
||||||
"""Return the list of available fan modes."""
|
"""Return the list of available fan modes."""
|
||||||
return list(self._fan_mode_map)
|
return list(self._fan_mode_map)
|
||||||
|
|
||||||
|
@ -1,10 +1,12 @@
|
|||||||
"""Support to serve the Home Assistant API as WSGI application."""
|
"""Support to serve the Home Assistant API as WSGI application."""
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
from contextvars import ContextVar
|
from contextvars import ContextVar
|
||||||
from ipaddress import ip_network
|
from ipaddress import ip_network
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
import ssl
|
import ssl
|
||||||
from typing import Dict, Optional, cast
|
from typing import Optional, cast
|
||||||
|
|
||||||
from aiohttp import web
|
from aiohttp import web
|
||||||
from aiohttp.web_exceptions import HTTPMovedPermanently
|
from aiohttp.web_exceptions import HTTPMovedPermanently
|
||||||
@ -102,7 +104,7 @@ CONFIG_SCHEMA = vol.Schema({DOMAIN: HTTP_SCHEMA}, extra=vol.ALLOW_EXTRA)
|
|||||||
|
|
||||||
|
|
||||||
@bind_hass
|
@bind_hass
|
||||||
async def async_get_last_config(hass: HomeAssistant) -> Optional[dict]:
|
async def async_get_last_config(hass: HomeAssistant) -> dict | None:
|
||||||
"""Return the last known working config."""
|
"""Return the last known working config."""
|
||||||
store = storage.Store(hass, STORAGE_VERSION, STORAGE_KEY)
|
store = storage.Store(hass, STORAGE_VERSION, STORAGE_KEY)
|
||||||
return cast(Optional[dict], await store.async_load())
|
return cast(Optional[dict], await store.async_load())
|
||||||
@ -115,7 +117,7 @@ class ApiConfig:
|
|||||||
self,
|
self,
|
||||||
local_ip: str,
|
local_ip: str,
|
||||||
host: str,
|
host: str,
|
||||||
port: Optional[int] = SERVER_PORT,
|
port: int | None = SERVER_PORT,
|
||||||
use_ssl: bool = False,
|
use_ssl: bool = False,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Initialize a new API config object."""
|
"""Initialize a new API config object."""
|
||||||
@ -379,7 +381,7 @@ class HomeAssistantHTTP:
|
|||||||
|
|
||||||
|
|
||||||
async def start_http_server_and_save_config(
|
async def start_http_server_and_save_config(
|
||||||
hass: HomeAssistant, conf: Dict, server: HomeAssistantHTTP
|
hass: HomeAssistant, conf: dict, server: HomeAssistantHTTP
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Startup the http server and save the config."""
|
"""Startup the http server and save the config."""
|
||||||
await server.start() # type: ignore
|
await server.start() # type: ignore
|
||||||
@ -395,6 +397,6 @@ async def start_http_server_and_save_config(
|
|||||||
await store.async_save(conf)
|
await store.async_save(conf)
|
||||||
|
|
||||||
|
|
||||||
current_request: ContextVar[Optional[web.Request]] = ContextVar(
|
current_request: ContextVar[web.Request | None] = ContextVar(
|
||||||
"current_request", default=None
|
"current_request", default=None
|
||||||
)
|
)
|
||||||
|
@ -1,10 +1,11 @@
|
|||||||
"""Ban logic for HTTP component."""
|
"""Ban logic for HTTP component."""
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
from collections import defaultdict
|
from collections import defaultdict
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from ipaddress import ip_address
|
from ipaddress import ip_address
|
||||||
import logging
|
import logging
|
||||||
from socket import gethostbyaddr, herror
|
from socket import gethostbyaddr, herror
|
||||||
from typing import List, Optional
|
|
||||||
|
|
||||||
from aiohttp.web import middleware
|
from aiohttp.web import middleware
|
||||||
from aiohttp.web_exceptions import HTTPForbidden, HTTPUnauthorized
|
from aiohttp.web_exceptions import HTTPForbidden, HTTPUnauthorized
|
||||||
@ -178,15 +179,15 @@ async def process_success_login(request):
|
|||||||
class IpBan:
|
class IpBan:
|
||||||
"""Represents banned IP address."""
|
"""Represents banned IP address."""
|
||||||
|
|
||||||
def __init__(self, ip_ban: str, banned_at: Optional[datetime] = None) -> None:
|
def __init__(self, ip_ban: str, banned_at: datetime | None = None) -> None:
|
||||||
"""Initialize IP Ban object."""
|
"""Initialize IP Ban object."""
|
||||||
self.ip_address = ip_address(ip_ban)
|
self.ip_address = ip_address(ip_ban)
|
||||||
self.banned_at = banned_at or dt_util.utcnow()
|
self.banned_at = banned_at or dt_util.utcnow()
|
||||||
|
|
||||||
|
|
||||||
async def async_load_ip_bans_config(hass: HomeAssistant, path: str) -> List[IpBan]:
|
async def async_load_ip_bans_config(hass: HomeAssistant, path: str) -> list[IpBan]:
|
||||||
"""Load list of banned IPs from config file."""
|
"""Load list of banned IPs from config file."""
|
||||||
ip_list: List[IpBan] = []
|
ip_list: list[IpBan] = []
|
||||||
|
|
||||||
try:
|
try:
|
||||||
list_ = await hass.async_add_executor_job(load_yaml_config_file, path)
|
list_ = await hass.async_add_executor_job(load_yaml_config_file, path)
|
||||||
|
@ -1,8 +1,10 @@
|
|||||||
"""Support for views."""
|
"""Support for views."""
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
import asyncio
|
import asyncio
|
||||||
import json
|
import json
|
||||||
import logging
|
import logging
|
||||||
from typing import Any, Callable, List, Optional
|
from typing import Any, Callable
|
||||||
|
|
||||||
from aiohttp import web
|
from aiohttp import web
|
||||||
from aiohttp.typedefs import LooseHeaders
|
from aiohttp.typedefs import LooseHeaders
|
||||||
@ -26,8 +28,8 @@ _LOGGER = logging.getLogger(__name__)
|
|||||||
class HomeAssistantView:
|
class HomeAssistantView:
|
||||||
"""Base view for all views."""
|
"""Base view for all views."""
|
||||||
|
|
||||||
url: Optional[str] = None
|
url: str | None = None
|
||||||
extra_urls: List[str] = []
|
extra_urls: list[str] = []
|
||||||
# Views inheriting from this class can override this
|
# Views inheriting from this class can override this
|
||||||
requires_auth = True
|
requires_auth = True
|
||||||
cors_allowed = False
|
cors_allowed = False
|
||||||
@ -45,7 +47,7 @@ class HomeAssistantView:
|
|||||||
def json(
|
def json(
|
||||||
result: Any,
|
result: Any,
|
||||||
status_code: int = HTTP_OK,
|
status_code: int = HTTP_OK,
|
||||||
headers: Optional[LooseHeaders] = None,
|
headers: LooseHeaders | None = None,
|
||||||
) -> web.Response:
|
) -> web.Response:
|
||||||
"""Return a JSON response."""
|
"""Return a JSON response."""
|
||||||
try:
|
try:
|
||||||
@ -66,8 +68,8 @@ class HomeAssistantView:
|
|||||||
self,
|
self,
|
||||||
message: str,
|
message: str,
|
||||||
status_code: int = HTTP_OK,
|
status_code: int = HTTP_OK,
|
||||||
message_code: Optional[str] = None,
|
message_code: str | None = None,
|
||||||
headers: Optional[LooseHeaders] = None,
|
headers: LooseHeaders | None = None,
|
||||||
) -> web.Response:
|
) -> web.Response:
|
||||||
"""Return a JSON message response."""
|
"""Return a JSON message response."""
|
||||||
data = {"message": message}
|
data = {"message": message}
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
"""HomeAssistant specific aiohttp Site."""
|
"""HomeAssistant specific aiohttp Site."""
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
import asyncio
|
import asyncio
|
||||||
from ssl import SSLContext
|
from ssl import SSLContext
|
||||||
from typing import List, Optional, Union
|
|
||||||
|
|
||||||
from aiohttp import web
|
from aiohttp import web
|
||||||
from yarl import URL
|
from yarl import URL
|
||||||
@ -25,14 +26,14 @@ class HomeAssistantTCPSite(web.BaseSite):
|
|||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
runner: "web.BaseRunner",
|
runner: "web.BaseRunner",
|
||||||
host: Union[None, str, List[str]],
|
host: None | str | list[str],
|
||||||
port: int,
|
port: int,
|
||||||
*,
|
*,
|
||||||
shutdown_timeout: float = 10.0,
|
shutdown_timeout: float = 10.0,
|
||||||
ssl_context: Optional[SSLContext] = None,
|
ssl_context: SSLContext | None = None,
|
||||||
backlog: int = 128,
|
backlog: int = 128,
|
||||||
reuse_address: Optional[bool] = None,
|
reuse_address: bool | None = None,
|
||||||
reuse_port: Optional[bool] = None,
|
reuse_port: bool | None = None,
|
||||||
) -> None: # noqa: D107
|
) -> None: # noqa: D107
|
||||||
super().__init__(
|
super().__init__(
|
||||||
runner,
|
runner,
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
"""Support for Huawei LTE routers."""
|
"""Support for Huawei LTE routers."""
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
from collections import defaultdict
|
from collections import defaultdict
|
||||||
from datetime import timedelta
|
from datetime import timedelta
|
||||||
@ -6,7 +7,7 @@ from functools import partial
|
|||||||
import ipaddress
|
import ipaddress
|
||||||
import logging
|
import logging
|
||||||
import time
|
import time
|
||||||
from typing import Any, Callable, Dict, List, Set, Tuple, cast
|
from typing import Any, Callable, cast
|
||||||
from urllib.parse import urlparse
|
from urllib.parse import urlparse
|
||||||
|
|
||||||
import attr
|
import attr
|
||||||
@ -138,13 +139,13 @@ class Router:
|
|||||||
mac: str = attr.ib()
|
mac: str = attr.ib()
|
||||||
signal_update: CALLBACK_TYPE = attr.ib()
|
signal_update: CALLBACK_TYPE = attr.ib()
|
||||||
|
|
||||||
data: Dict[str, Any] = attr.ib(init=False, factory=dict)
|
data: dict[str, Any] = attr.ib(init=False, factory=dict)
|
||||||
subscriptions: Dict[str, Set[str]] = attr.ib(
|
subscriptions: dict[str, set[str]] = attr.ib(
|
||||||
init=False,
|
init=False,
|
||||||
factory=lambda: defaultdict(set, ((x, {"initial_scan"}) for x in ALL_KEYS)),
|
factory=lambda: defaultdict(set, ((x, {"initial_scan"}) for x in ALL_KEYS)),
|
||||||
)
|
)
|
||||||
inflight_gets: Set[str] = attr.ib(init=False, factory=set)
|
inflight_gets: set[str] = attr.ib(init=False, factory=set)
|
||||||
unload_handlers: List[CALLBACK_TYPE] = attr.ib(init=False, factory=list)
|
unload_handlers: list[CALLBACK_TYPE] = attr.ib(init=False, factory=list)
|
||||||
client: Client
|
client: Client
|
||||||
suspended = attr.ib(init=False, default=False)
|
suspended = attr.ib(init=False, default=False)
|
||||||
notify_last_attempt: float = attr.ib(init=False, default=-1)
|
notify_last_attempt: float = attr.ib(init=False, default=-1)
|
||||||
@ -167,7 +168,7 @@ class Router:
|
|||||||
return DEFAULT_DEVICE_NAME
|
return DEFAULT_DEVICE_NAME
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def device_identifiers(self) -> Set[Tuple[str, str]]:
|
def device_identifiers(self) -> set[tuple[str, str]]:
|
||||||
"""Get router identifiers for device registry."""
|
"""Get router identifiers for device registry."""
|
||||||
try:
|
try:
|
||||||
return {(DOMAIN, self.data[KEY_DEVICE_INFORMATION]["SerialNumber"])}
|
return {(DOMAIN, self.data[KEY_DEVICE_INFORMATION]["SerialNumber"])}
|
||||||
@ -175,7 +176,7 @@ class Router:
|
|||||||
return set()
|
return set()
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def device_connections(self) -> Set[Tuple[str, str]]:
|
def device_connections(self) -> set[tuple[str, str]]:
|
||||||
"""Get router connections for device registry."""
|
"""Get router connections for device registry."""
|
||||||
return {(dr.CONNECTION_NETWORK_MAC, self.mac)} if self.mac else set()
|
return {(dr.CONNECTION_NETWORK_MAC, self.mac)} if self.mac else set()
|
||||||
|
|
||||||
@ -304,8 +305,8 @@ class HuaweiLteData:
|
|||||||
|
|
||||||
hass_config: dict = attr.ib()
|
hass_config: dict = attr.ib()
|
||||||
# Our YAML config, keyed by router URL
|
# Our YAML config, keyed by router URL
|
||||||
config: Dict[str, Dict[str, Any]] = attr.ib()
|
config: dict[str, dict[str, Any]] = attr.ib()
|
||||||
routers: Dict[str, Router] = attr.ib(init=False, factory=dict)
|
routers: dict[str, Router] = attr.ib(init=False, factory=dict)
|
||||||
|
|
||||||
|
|
||||||
async def async_setup_entry(hass: HomeAssistantType, config_entry: ConfigEntry) -> bool:
|
async def async_setup_entry(hass: HomeAssistantType, config_entry: ConfigEntry) -> bool:
|
||||||
@ -484,7 +485,7 @@ async def async_setup(hass: HomeAssistantType, config: ConfigType) -> bool:
|
|||||||
logging.getLogger("dicttoxml").setLevel(logging.WARNING)
|
logging.getLogger("dicttoxml").setLevel(logging.WARNING)
|
||||||
|
|
||||||
# Arrange our YAML config to dict with normalized URLs as keys
|
# Arrange our YAML config to dict with normalized URLs as keys
|
||||||
domain_config: Dict[str, Dict[str, Any]] = {}
|
domain_config: dict[str, dict[str, Any]] = {}
|
||||||
if DOMAIN not in hass.data:
|
if DOMAIN not in hass.data:
|
||||||
hass.data[DOMAIN] = HuaweiLteData(hass_config=config, config=domain_config)
|
hass.data[DOMAIN] = HuaweiLteData(hass_config=config, config=domain_config)
|
||||||
for router_config in config.get(DOMAIN, []):
|
for router_config in config.get(DOMAIN, []):
|
||||||
@ -588,7 +589,7 @@ class HuaweiLteBaseEntity(Entity):
|
|||||||
router: Router = attr.ib()
|
router: Router = attr.ib()
|
||||||
|
|
||||||
_available: bool = attr.ib(init=False, default=True)
|
_available: bool = attr.ib(init=False, default=True)
|
||||||
_unsub_handlers: List[Callable] = attr.ib(init=False, factory=list)
|
_unsub_handlers: list[Callable] = attr.ib(init=False, factory=list)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def _entity_name(self) -> str:
|
def _entity_name(self) -> str:
|
||||||
@ -620,7 +621,7 @@ class HuaweiLteBaseEntity(Entity):
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def device_info(self) -> Dict[str, Any]:
|
def device_info(self) -> dict[str, Any]:
|
||||||
"""Get info for matching with parent router."""
|
"""Get info for matching with parent router."""
|
||||||
return {
|
return {
|
||||||
"identifiers": self.router.device_identifiers,
|
"identifiers": self.router.device_identifiers,
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
"""Support for Huawei LTE binary sensors."""
|
"""Support for Huawei LTE binary sensors."""
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
from typing import Any, Callable, Dict, List, Optional
|
from typing import Any, Callable
|
||||||
|
|
||||||
import attr
|
import attr
|
||||||
from huawei_lte_api.enums.cradle import ConnectionStatusEnum
|
from huawei_lte_api.enums.cradle import ConnectionStatusEnum
|
||||||
@ -29,11 +30,11 @@ _LOGGER = logging.getLogger(__name__)
|
|||||||
async def async_setup_entry(
|
async def async_setup_entry(
|
||||||
hass: HomeAssistantType,
|
hass: HomeAssistantType,
|
||||||
config_entry: ConfigEntry,
|
config_entry: ConfigEntry,
|
||||||
async_add_entities: Callable[[List[Entity], bool], None],
|
async_add_entities: Callable[[list[Entity], bool], None],
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Set up from config entry."""
|
"""Set up from config entry."""
|
||||||
router = hass.data[DOMAIN].routers[config_entry.data[CONF_URL]]
|
router = hass.data[DOMAIN].routers[config_entry.data[CONF_URL]]
|
||||||
entities: List[Entity] = []
|
entities: list[Entity] = []
|
||||||
|
|
||||||
if router.data.get(KEY_MONITORING_STATUS):
|
if router.data.get(KEY_MONITORING_STATUS):
|
||||||
entities.append(HuaweiLteMobileConnectionBinarySensor(router))
|
entities.append(HuaweiLteMobileConnectionBinarySensor(router))
|
||||||
@ -53,7 +54,7 @@ class HuaweiLteBaseBinarySensor(HuaweiLteBaseEntity, BinarySensorEntity):
|
|||||||
|
|
||||||
key: str
|
key: str
|
||||||
item: str
|
item: str
|
||||||
_raw_state: Optional[str] = attr.ib(init=False, default=None)
|
_raw_state: str | None = attr.ib(init=False, default=None)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def entity_registry_enabled_default(self) -> bool:
|
def entity_registry_enabled_default(self) -> bool:
|
||||||
@ -142,7 +143,7 @@ class HuaweiLteMobileConnectionBinarySensor(HuaweiLteBaseBinarySensor):
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def extra_state_attributes(self) -> Optional[Dict[str, Any]]:
|
def extra_state_attributes(self) -> dict[str, Any] | None:
|
||||||
"""Get additional attributes related to connection status."""
|
"""Get additional attributes related to connection status."""
|
||||||
attributes = {}
|
attributes = {}
|
||||||
if self._raw_state in CONNECTION_STATE_ATTRIBUTES:
|
if self._raw_state in CONNECTION_STATE_ATTRIBUTES:
|
||||||
|
@ -3,7 +3,7 @@ from __future__ import annotations
|
|||||||
|
|
||||||
from collections import OrderedDict
|
from collections import OrderedDict
|
||||||
import logging
|
import logging
|
||||||
from typing import Any, Dict, Optional
|
from typing import Any
|
||||||
from urllib.parse import urlparse
|
from urllib.parse import urlparse
|
||||||
|
|
||||||
from huawei_lte_api.AuthorizedConnection import AuthorizedConnection
|
from huawei_lte_api.AuthorizedConnection import AuthorizedConnection
|
||||||
@ -55,9 +55,9 @@ class ConfigFlowHandler(config_entries.ConfigFlow, domain=DOMAIN):
|
|||||||
|
|
||||||
async def _async_show_user_form(
|
async def _async_show_user_form(
|
||||||
self,
|
self,
|
||||||
user_input: Optional[Dict[str, Any]] = None,
|
user_input: dict[str, Any] | None = None,
|
||||||
errors: Optional[Dict[str, str]] = None,
|
errors: dict[str, str] | None = None,
|
||||||
) -> Dict[str, Any]:
|
) -> dict[str, Any]:
|
||||||
if user_input is None:
|
if user_input is None:
|
||||||
user_input = {}
|
user_input = {}
|
||||||
return self.async_show_form(
|
return self.async_show_form(
|
||||||
@ -94,12 +94,12 @@ class ConfigFlowHandler(config_entries.ConfigFlow, domain=DOMAIN):
|
|||||||
)
|
)
|
||||||
|
|
||||||
async def async_step_import(
|
async def async_step_import(
|
||||||
self, user_input: Optional[Dict[str, Any]] = None
|
self, user_input: dict[str, Any] | None = None
|
||||||
) -> Dict[str, Any]:
|
) -> dict[str, Any]:
|
||||||
"""Handle import initiated config flow."""
|
"""Handle import initiated config flow."""
|
||||||
return await self.async_step_user(user_input)
|
return await self.async_step_user(user_input)
|
||||||
|
|
||||||
def _already_configured(self, user_input: Dict[str, Any]) -> bool:
|
def _already_configured(self, user_input: dict[str, Any]) -> bool:
|
||||||
"""See if we already have a router matching user input configured."""
|
"""See if we already have a router matching user input configured."""
|
||||||
existing_urls = {
|
existing_urls = {
|
||||||
url_normalize(entry.data[CONF_URL], default_scheme="http")
|
url_normalize(entry.data[CONF_URL], default_scheme="http")
|
||||||
@ -108,8 +108,8 @@ class ConfigFlowHandler(config_entries.ConfigFlow, domain=DOMAIN):
|
|||||||
return user_input[CONF_URL] in existing_urls
|
return user_input[CONF_URL] in existing_urls
|
||||||
|
|
||||||
async def async_step_user(
|
async def async_step_user(
|
||||||
self, user_input: Optional[Dict[str, Any]] = None
|
self, user_input: dict[str, Any] | None = None
|
||||||
) -> Dict[str, Any]:
|
) -> dict[str, Any]:
|
||||||
"""Handle user initiated config flow."""
|
"""Handle user initiated config flow."""
|
||||||
if user_input is None:
|
if user_input is None:
|
||||||
return await self._async_show_user_form()
|
return await self._async_show_user_form()
|
||||||
@ -129,7 +129,7 @@ class ConfigFlowHandler(config_entries.ConfigFlow, domain=DOMAIN):
|
|||||||
if self._already_configured(user_input):
|
if self._already_configured(user_input):
|
||||||
return self.async_abort(reason="already_configured")
|
return self.async_abort(reason="already_configured")
|
||||||
|
|
||||||
conn: Optional[Connection] = None
|
conn: Connection | None = None
|
||||||
|
|
||||||
def logout() -> None:
|
def logout() -> None:
|
||||||
if isinstance(conn, AuthorizedConnection):
|
if isinstance(conn, AuthorizedConnection):
|
||||||
@ -138,7 +138,7 @@ class ConfigFlowHandler(config_entries.ConfigFlow, domain=DOMAIN):
|
|||||||
except Exception: # pylint: disable=broad-except
|
except Exception: # pylint: disable=broad-except
|
||||||
_LOGGER.debug("Could not logout", exc_info=True)
|
_LOGGER.debug("Could not logout", exc_info=True)
|
||||||
|
|
||||||
def try_connect(user_input: Dict[str, Any]) -> Connection:
|
def try_connect(user_input: dict[str, Any]) -> Connection:
|
||||||
"""Try connecting with given credentials."""
|
"""Try connecting with given credentials."""
|
||||||
username = user_input.get(CONF_USERNAME)
|
username = user_input.get(CONF_USERNAME)
|
||||||
password = user_input.get(CONF_PASSWORD)
|
password = user_input.get(CONF_PASSWORD)
|
||||||
@ -222,8 +222,8 @@ class ConfigFlowHandler(config_entries.ConfigFlow, domain=DOMAIN):
|
|||||||
return self.async_create_entry(title=title, data=user_input)
|
return self.async_create_entry(title=title, data=user_input)
|
||||||
|
|
||||||
async def async_step_ssdp( # type: ignore # mypy says signature incompatible with supertype, but it's the same?
|
async def async_step_ssdp( # type: ignore # mypy says signature incompatible with supertype, but it's the same?
|
||||||
self, discovery_info: Dict[str, Any]
|
self, discovery_info: dict[str, Any]
|
||||||
) -> Dict[str, Any]:
|
) -> dict[str, Any]:
|
||||||
"""Handle SSDP initiated config flow."""
|
"""Handle SSDP initiated config flow."""
|
||||||
await self.async_set_unique_id(discovery_info[ssdp.ATTR_UPNP_UDN])
|
await self.async_set_unique_id(discovery_info[ssdp.ATTR_UPNP_UDN])
|
||||||
self._abort_if_unique_id_configured()
|
self._abort_if_unique_id_configured()
|
||||||
@ -263,8 +263,8 @@ class OptionsFlowHandler(config_entries.OptionsFlow):
|
|||||||
self.config_entry = config_entry
|
self.config_entry = config_entry
|
||||||
|
|
||||||
async def async_step_init(
|
async def async_step_init(
|
||||||
self, user_input: Optional[Dict[str, Any]] = None
|
self, user_input: dict[str, Any] | None = None
|
||||||
) -> Dict[str, Any]:
|
) -> dict[str, Any]:
|
||||||
"""Handle options flow."""
|
"""Handle options flow."""
|
||||||
|
|
||||||
# Recipients are persisted as a list, but handled as comma separated string in UI
|
# Recipients are persisted as a list, but handled as comma separated string in UI
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
"""Support for device tracking of Huawei LTE routers."""
|
"""Support for device tracking of Huawei LTE routers."""
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
import re
|
import re
|
||||||
from typing import Any, Callable, Dict, List, Optional, Set, cast
|
from typing import Any, Callable, cast
|
||||||
|
|
||||||
import attr
|
import attr
|
||||||
from stringcase import snakecase
|
from stringcase import snakecase
|
||||||
@ -31,7 +32,7 @@ _DEVICE_SCAN = f"{DEVICE_TRACKER_DOMAIN}/device_scan"
|
|||||||
async def async_setup_entry(
|
async def async_setup_entry(
|
||||||
hass: HomeAssistantType,
|
hass: HomeAssistantType,
|
||||||
config_entry: ConfigEntry,
|
config_entry: ConfigEntry,
|
||||||
async_add_entities: Callable[[List[Entity], bool], None],
|
async_add_entities: Callable[[list[Entity], bool], None],
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Set up from config entry."""
|
"""Set up from config entry."""
|
||||||
|
|
||||||
@ -46,9 +47,9 @@ async def async_setup_entry(
|
|||||||
return
|
return
|
||||||
|
|
||||||
# Initialize already tracked entities
|
# Initialize already tracked entities
|
||||||
tracked: Set[str] = set()
|
tracked: set[str] = set()
|
||||||
registry = await entity_registry.async_get_registry(hass)
|
registry = await entity_registry.async_get_registry(hass)
|
||||||
known_entities: List[Entity] = []
|
known_entities: list[Entity] = []
|
||||||
for entity in registry.entities.values():
|
for entity in registry.entities.values():
|
||||||
if (
|
if (
|
||||||
entity.domain == DEVICE_TRACKER_DOMAIN
|
entity.domain == DEVICE_TRACKER_DOMAIN
|
||||||
@ -82,8 +83,8 @@ async def async_setup_entry(
|
|||||||
def async_add_new_entities(
|
def async_add_new_entities(
|
||||||
hass: HomeAssistantType,
|
hass: HomeAssistantType,
|
||||||
router_url: str,
|
router_url: str,
|
||||||
async_add_entities: Callable[[List[Entity], bool], None],
|
async_add_entities: Callable[[list[Entity], bool], None],
|
||||||
tracked: Set[str],
|
tracked: set[str],
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Add new entities that are not already being tracked."""
|
"""Add new entities that are not already being tracked."""
|
||||||
router = hass.data[DOMAIN].routers[router_url]
|
router = hass.data[DOMAIN].routers[router_url]
|
||||||
@ -93,7 +94,7 @@ def async_add_new_entities(
|
|||||||
_LOGGER.debug("%s[%s][%s] not in data", KEY_WLAN_HOST_LIST, "Hosts", "Host")
|
_LOGGER.debug("%s[%s][%s] not in data", KEY_WLAN_HOST_LIST, "Hosts", "Host")
|
||||||
return
|
return
|
||||||
|
|
||||||
new_entities: List[Entity] = []
|
new_entities: list[Entity] = []
|
||||||
for host in (x for x in hosts if x.get("MacAddress")):
|
for host in (x for x in hosts if x.get("MacAddress")):
|
||||||
entity = HuaweiLteScannerEntity(router, host["MacAddress"])
|
entity = HuaweiLteScannerEntity(router, host["MacAddress"])
|
||||||
if entity.unique_id in tracked:
|
if entity.unique_id in tracked:
|
||||||
@ -125,8 +126,8 @@ class HuaweiLteScannerEntity(HuaweiLteBaseEntity, ScannerEntity):
|
|||||||
mac: str = attr.ib()
|
mac: str = attr.ib()
|
||||||
|
|
||||||
_is_connected: bool = attr.ib(init=False, default=False)
|
_is_connected: bool = attr.ib(init=False, default=False)
|
||||||
_hostname: Optional[str] = attr.ib(init=False, default=None)
|
_hostname: str | None = attr.ib(init=False, default=None)
|
||||||
_extra_state_attributes: Dict[str, Any] = attr.ib(init=False, factory=dict)
|
_extra_state_attributes: dict[str, Any] = attr.ib(init=False, factory=dict)
|
||||||
|
|
||||||
def __attrs_post_init__(self) -> None:
|
def __attrs_post_init__(self) -> None:
|
||||||
"""Initialize internal state."""
|
"""Initialize internal state."""
|
||||||
@ -151,7 +152,7 @@ class HuaweiLteScannerEntity(HuaweiLteBaseEntity, ScannerEntity):
|
|||||||
return self._is_connected
|
return self._is_connected
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def extra_state_attributes(self) -> Dict[str, Any]:
|
def extra_state_attributes(self) -> dict[str, Any]:
|
||||||
"""Get additional attributes related to entity state."""
|
"""Get additional attributes related to entity state."""
|
||||||
return self._extra_state_attributes
|
return self._extra_state_attributes
|
||||||
|
|
||||||
|
@ -3,7 +3,7 @@ from __future__ import annotations
|
|||||||
|
|
||||||
import logging
|
import logging
|
||||||
import time
|
import time
|
||||||
from typing import Any, Dict, List, Optional
|
from typing import Any
|
||||||
|
|
||||||
import attr
|
import attr
|
||||||
from huawei_lte_api.exceptions import ResponseErrorException
|
from huawei_lte_api.exceptions import ResponseErrorException
|
||||||
@ -20,9 +20,9 @@ _LOGGER = logging.getLogger(__name__)
|
|||||||
|
|
||||||
async def async_get_service(
|
async def async_get_service(
|
||||||
hass: HomeAssistantType,
|
hass: HomeAssistantType,
|
||||||
config: Dict[str, Any],
|
config: dict[str, Any],
|
||||||
discovery_info: Optional[Dict[str, Any]] = None,
|
discovery_info: dict[str, Any] | None = None,
|
||||||
) -> Optional[HuaweiLteSmsNotificationService]:
|
) -> HuaweiLteSmsNotificationService | None:
|
||||||
"""Get the notification service."""
|
"""Get the notification service."""
|
||||||
if discovery_info is None:
|
if discovery_info is None:
|
||||||
return None
|
return None
|
||||||
@ -38,7 +38,7 @@ class HuaweiLteSmsNotificationService(BaseNotificationService):
|
|||||||
"""Huawei LTE router SMS notification service."""
|
"""Huawei LTE router SMS notification service."""
|
||||||
|
|
||||||
router: Router = attr.ib()
|
router: Router = attr.ib()
|
||||||
default_targets: List[str] = attr.ib()
|
default_targets: list[str] = attr.ib()
|
||||||
|
|
||||||
def send_message(self, message: str = "", **kwargs: Any) -> None:
|
def send_message(self, message: str = "", **kwargs: Any) -> None:
|
||||||
"""Send message to target numbers."""
|
"""Send message to target numbers."""
|
||||||
|
@ -1,9 +1,10 @@
|
|||||||
"""Support for Huawei LTE sensors."""
|
"""Support for Huawei LTE sensors."""
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
from bisect import bisect
|
from bisect import bisect
|
||||||
import logging
|
import logging
|
||||||
import re
|
import re
|
||||||
from typing import Callable, Dict, List, NamedTuple, Optional, Pattern, Tuple, Union
|
from typing import Callable, NamedTuple, Pattern
|
||||||
|
|
||||||
import attr
|
import attr
|
||||||
|
|
||||||
@ -45,17 +46,17 @@ _LOGGER = logging.getLogger(__name__)
|
|||||||
class SensorMeta(NamedTuple):
|
class SensorMeta(NamedTuple):
|
||||||
"""Metadata for defining sensors."""
|
"""Metadata for defining sensors."""
|
||||||
|
|
||||||
name: Optional[str] = None
|
name: str | None = None
|
||||||
device_class: Optional[str] = None
|
device_class: str | None = None
|
||||||
icon: Union[str, Callable[[StateType], str], None] = None
|
icon: str | Callable[[StateType], str] | None = None
|
||||||
unit: Optional[str] = None
|
unit: str | None = None
|
||||||
enabled_default: bool = False
|
enabled_default: bool = False
|
||||||
include: Optional[Pattern[str]] = None
|
include: Pattern[str] | None = None
|
||||||
exclude: Optional[Pattern[str]] = None
|
exclude: Pattern[str] | None = None
|
||||||
formatter: Optional[Callable[[str], Tuple[StateType, Optional[str]]]] = None
|
formatter: Callable[[str], tuple[StateType, str | None]] | None = None
|
||||||
|
|
||||||
|
|
||||||
SENSOR_META: Dict[Union[str, Tuple[str, str]], SensorMeta] = {
|
SENSOR_META: dict[str | tuple[str, str], SensorMeta] = {
|
||||||
KEY_DEVICE_INFORMATION: SensorMeta(
|
KEY_DEVICE_INFORMATION: SensorMeta(
|
||||||
include=re.compile(r"^WanIP.*Address$", re.IGNORECASE)
|
include=re.compile(r"^WanIP.*Address$", re.IGNORECASE)
|
||||||
),
|
),
|
||||||
@ -329,11 +330,11 @@ SENSOR_META: Dict[Union[str, Tuple[str, str]], SensorMeta] = {
|
|||||||
async def async_setup_entry(
|
async def async_setup_entry(
|
||||||
hass: HomeAssistantType,
|
hass: HomeAssistantType,
|
||||||
config_entry: ConfigEntry,
|
config_entry: ConfigEntry,
|
||||||
async_add_entities: Callable[[List[Entity], bool], None],
|
async_add_entities: Callable[[list[Entity], bool], None],
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Set up from config entry."""
|
"""Set up from config entry."""
|
||||||
router = hass.data[DOMAIN].routers[config_entry.data[CONF_URL]]
|
router = hass.data[DOMAIN].routers[config_entry.data[CONF_URL]]
|
||||||
sensors: List[Entity] = []
|
sensors: list[Entity] = []
|
||||||
for key in SENSOR_KEYS:
|
for key in SENSOR_KEYS:
|
||||||
items = router.data.get(key)
|
items = router.data.get(key)
|
||||||
if not items:
|
if not items:
|
||||||
@ -354,7 +355,7 @@ async def async_setup_entry(
|
|||||||
async_add_entities(sensors, True)
|
async_add_entities(sensors, True)
|
||||||
|
|
||||||
|
|
||||||
def format_default(value: StateType) -> Tuple[StateType, Optional[str]]:
|
def format_default(value: StateType) -> tuple[StateType, str | None]:
|
||||||
"""Format value."""
|
"""Format value."""
|
||||||
unit = None
|
unit = None
|
||||||
if value is not None:
|
if value is not None:
|
||||||
@ -380,7 +381,7 @@ class HuaweiLteSensor(HuaweiLteBaseEntity):
|
|||||||
meta: SensorMeta = attr.ib()
|
meta: SensorMeta = attr.ib()
|
||||||
|
|
||||||
_state: StateType = attr.ib(init=False, default=STATE_UNKNOWN)
|
_state: StateType = attr.ib(init=False, default=STATE_UNKNOWN)
|
||||||
_unit: Optional[str] = attr.ib(init=False)
|
_unit: str | None = attr.ib(init=False)
|
||||||
|
|
||||||
async def async_added_to_hass(self) -> None:
|
async def async_added_to_hass(self) -> None:
|
||||||
"""Subscribe to needed data on add."""
|
"""Subscribe to needed data on add."""
|
||||||
@ -406,17 +407,17 @@ class HuaweiLteSensor(HuaweiLteBaseEntity):
|
|||||||
return self._state
|
return self._state
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def device_class(self) -> Optional[str]:
|
def device_class(self) -> str | None:
|
||||||
"""Return sensor device class."""
|
"""Return sensor device class."""
|
||||||
return self.meta.device_class
|
return self.meta.device_class
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def unit_of_measurement(self) -> Optional[str]:
|
def unit_of_measurement(self) -> str | None:
|
||||||
"""Return sensor's unit of measurement."""
|
"""Return sensor's unit of measurement."""
|
||||||
return self.meta.unit or self._unit
|
return self.meta.unit or self._unit
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def icon(self) -> Optional[str]:
|
def icon(self) -> str | None:
|
||||||
"""Return icon for sensor."""
|
"""Return icon for sensor."""
|
||||||
icon = self.meta.icon
|
icon = self.meta.icon
|
||||||
if callable(icon):
|
if callable(icon):
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
"""Support for Huawei LTE switches."""
|
"""Support for Huawei LTE switches."""
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
from typing import Any, Callable, List, Optional
|
from typing import Any, Callable
|
||||||
|
|
||||||
import attr
|
import attr
|
||||||
|
|
||||||
@ -24,11 +25,11 @@ _LOGGER = logging.getLogger(__name__)
|
|||||||
async def async_setup_entry(
|
async def async_setup_entry(
|
||||||
hass: HomeAssistantType,
|
hass: HomeAssistantType,
|
||||||
config_entry: ConfigEntry,
|
config_entry: ConfigEntry,
|
||||||
async_add_entities: Callable[[List[Entity], bool], None],
|
async_add_entities: Callable[[list[Entity], bool], None],
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Set up from config entry."""
|
"""Set up from config entry."""
|
||||||
router = hass.data[DOMAIN].routers[config_entry.data[CONF_URL]]
|
router = hass.data[DOMAIN].routers[config_entry.data[CONF_URL]]
|
||||||
switches: List[Entity] = []
|
switches: list[Entity] = []
|
||||||
|
|
||||||
if router.data.get(KEY_DIALUP_MOBILE_DATASWITCH):
|
if router.data.get(KEY_DIALUP_MOBILE_DATASWITCH):
|
||||||
switches.append(HuaweiLteMobileDataSwitch(router))
|
switches.append(HuaweiLteMobileDataSwitch(router))
|
||||||
@ -42,7 +43,7 @@ class HuaweiLteBaseSwitch(HuaweiLteBaseEntity, SwitchEntity):
|
|||||||
|
|
||||||
key: str
|
key: str
|
||||||
item: str
|
item: str
|
||||||
_raw_state: Optional[str] = attr.ib(init=False, default=None)
|
_raw_state: str | None = attr.ib(init=False, default=None)
|
||||||
|
|
||||||
def _turn(self, state: bool) -> None:
|
def _turn(self, state: bool) -> None:
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
"""Config flow to configure Philips Hue."""
|
"""Config flow to configure Philips Hue."""
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
import asyncio
|
import asyncio
|
||||||
from typing import Any, Dict, Optional
|
from typing import Any
|
||||||
from urllib.parse import urlparse
|
from urllib.parse import urlparse
|
||||||
|
|
||||||
import aiohue
|
import aiohue
|
||||||
@ -44,8 +46,8 @@ class HueFlowHandler(config_entries.ConfigFlow, domain=DOMAIN):
|
|||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
"""Initialize the Hue flow."""
|
"""Initialize the Hue flow."""
|
||||||
self.bridge: Optional[aiohue.Bridge] = None
|
self.bridge: aiohue.Bridge | None = None
|
||||||
self.discovered_bridges: Optional[Dict[str, aiohue.Bridge]] = None
|
self.discovered_bridges: dict[str, aiohue.Bridge] | None = None
|
||||||
|
|
||||||
async def async_step_user(self, user_input=None):
|
async def async_step_user(self, user_input=None):
|
||||||
"""Handle a flow initialized by the user."""
|
"""Handle a flow initialized by the user."""
|
||||||
@ -53,7 +55,7 @@ class HueFlowHandler(config_entries.ConfigFlow, domain=DOMAIN):
|
|||||||
return await self.async_step_init(user_input)
|
return await self.async_step_init(user_input)
|
||||||
|
|
||||||
@core.callback
|
@core.callback
|
||||||
def _async_get_bridge(self, host: str, bridge_id: Optional[str] = None):
|
def _async_get_bridge(self, host: str, bridge_id: str | None = None):
|
||||||
"""Return a bridge object."""
|
"""Return a bridge object."""
|
||||||
if bridge_id is not None:
|
if bridge_id is not None:
|
||||||
bridge_id = normalize_bridge_id(bridge_id)
|
bridge_id = normalize_bridge_id(bridge_id)
|
||||||
@ -114,8 +116,8 @@ class HueFlowHandler(config_entries.ConfigFlow, domain=DOMAIN):
|
|||||||
)
|
)
|
||||||
|
|
||||||
async def async_step_manual(
|
async def async_step_manual(
|
||||||
self, user_input: Optional[Dict[str, Any]] = None
|
self, user_input: dict[str, Any] | None = None
|
||||||
) -> Dict[str, Any]:
|
) -> dict[str, Any]:
|
||||||
"""Handle manual bridge setup."""
|
"""Handle manual bridge setup."""
|
||||||
if user_input is None:
|
if user_input is None:
|
||||||
return self.async_show_form(
|
return self.async_show_form(
|
||||||
@ -249,8 +251,8 @@ class HueOptionsFlowHandler(config_entries.OptionsFlow):
|
|||||||
self.config_entry = config_entry
|
self.config_entry = config_entry
|
||||||
|
|
||||||
async def async_step_init(
|
async def async_step_init(
|
||||||
self, user_input: Optional[Dict[str, Any]] = None
|
self, user_input: dict[str, Any] | None = None
|
||||||
) -> Dict[str, Any]:
|
) -> dict[str, Any]:
|
||||||
"""Manage Hue options."""
|
"""Manage Hue options."""
|
||||||
if user_input is not None:
|
if user_input is not None:
|
||||||
return self.async_create_entry(title="", data=user_input)
|
return self.async_create_entry(title="", data=user_input)
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
"""Provides functionality to interact with humidifier devices."""
|
"""Provides functionality to interact with humidifier devices."""
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
from datetime import timedelta
|
from datetime import timedelta
|
||||||
import logging
|
import logging
|
||||||
from typing import Any, Dict, List, Optional
|
from typing import Any
|
||||||
|
|
||||||
import voluptuous as vol
|
import voluptuous as vol
|
||||||
|
|
||||||
@ -100,7 +102,7 @@ class HumidifierEntity(ToggleEntity):
|
|||||||
"""Representation of a humidifier device."""
|
"""Representation of a humidifier device."""
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def capability_attributes(self) -> Dict[str, Any]:
|
def capability_attributes(self) -> dict[str, Any]:
|
||||||
"""Return capability attributes."""
|
"""Return capability attributes."""
|
||||||
supported_features = self.supported_features or 0
|
supported_features = self.supported_features or 0
|
||||||
data = {
|
data = {
|
||||||
@ -114,7 +116,7 @@ class HumidifierEntity(ToggleEntity):
|
|||||||
return data
|
return data
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def state_attributes(self) -> Dict[str, Any]:
|
def state_attributes(self) -> dict[str, Any]:
|
||||||
"""Return the optional state attributes."""
|
"""Return the optional state attributes."""
|
||||||
supported_features = self.supported_features or 0
|
supported_features = self.supported_features or 0
|
||||||
data = {}
|
data = {}
|
||||||
@ -128,12 +130,12 @@ class HumidifierEntity(ToggleEntity):
|
|||||||
return data
|
return data
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def target_humidity(self) -> Optional[int]:
|
def target_humidity(self) -> int | None:
|
||||||
"""Return the humidity we try to reach."""
|
"""Return the humidity we try to reach."""
|
||||||
return None
|
return None
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def mode(self) -> Optional[str]:
|
def mode(self) -> str | None:
|
||||||
"""Return the current mode, e.g., home, auto, baby.
|
"""Return the current mode, e.g., home, auto, baby.
|
||||||
|
|
||||||
Requires SUPPORT_MODES.
|
Requires SUPPORT_MODES.
|
||||||
@ -141,7 +143,7 @@ class HumidifierEntity(ToggleEntity):
|
|||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def available_modes(self) -> Optional[List[str]]:
|
def available_modes(self) -> list[str] | None:
|
||||||
"""Return a list of available modes.
|
"""Return a list of available modes.
|
||||||
|
|
||||||
Requires SUPPORT_MODES.
|
Requires SUPPORT_MODES.
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
"""Provides device actions for Humidifier."""
|
"""Provides device actions for Humidifier."""
|
||||||
from typing import List, Optional
|
from __future__ import annotations
|
||||||
|
|
||||||
import voluptuous as vol
|
import voluptuous as vol
|
||||||
|
|
||||||
@ -40,7 +40,7 @@ ONOFF_SCHEMA = toggle_entity.ACTION_SCHEMA.extend({vol.Required(CONF_DOMAIN): DO
|
|||||||
ACTION_SCHEMA = vol.Any(SET_HUMIDITY_SCHEMA, SET_MODE_SCHEMA, ONOFF_SCHEMA)
|
ACTION_SCHEMA = vol.Any(SET_HUMIDITY_SCHEMA, SET_MODE_SCHEMA, ONOFF_SCHEMA)
|
||||||
|
|
||||||
|
|
||||||
async def async_get_actions(hass: HomeAssistant, device_id: str) -> List[dict]:
|
async def async_get_actions(hass: HomeAssistant, device_id: str) -> list[dict]:
|
||||||
"""List device actions for Humidifier devices."""
|
"""List device actions for Humidifier devices."""
|
||||||
registry = await entity_registry.async_get_registry(hass)
|
registry = await entity_registry.async_get_registry(hass)
|
||||||
actions = await toggle_entity.async_get_actions(hass, device_id, DOMAIN)
|
actions = await toggle_entity.async_get_actions(hass, device_id, DOMAIN)
|
||||||
@ -79,7 +79,7 @@ async def async_get_actions(hass: HomeAssistant, device_id: str) -> List[dict]:
|
|||||||
|
|
||||||
|
|
||||||
async def async_call_action_from_config(
|
async def async_call_action_from_config(
|
||||||
hass: HomeAssistant, config: dict, variables: dict, context: Optional[Context]
|
hass: HomeAssistant, config: dict, variables: dict, context: Context | None
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Execute a device action."""
|
"""Execute a device action."""
|
||||||
config = ACTION_SCHEMA(config)
|
config = ACTION_SCHEMA(config)
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
"""Provide the device automations for Humidifier."""
|
"""Provide the device automations for Humidifier."""
|
||||||
from typing import Dict, List
|
from __future__ import annotations
|
||||||
|
|
||||||
import voluptuous as vol
|
import voluptuous as vol
|
||||||
|
|
||||||
@ -38,7 +38,7 @@ CONDITION_SCHEMA = vol.Any(TOGGLE_CONDITION, MODE_CONDITION)
|
|||||||
|
|
||||||
async def async_get_conditions(
|
async def async_get_conditions(
|
||||||
hass: HomeAssistant, device_id: str
|
hass: HomeAssistant, device_id: str
|
||||||
) -> List[Dict[str, str]]:
|
) -> list[dict[str, str]]:
|
||||||
"""List device conditions for Humidifier devices."""
|
"""List device conditions for Humidifier devices."""
|
||||||
registry = await entity_registry.async_get_registry(hass)
|
registry = await entity_registry.async_get_registry(hass)
|
||||||
conditions = await toggle_entity.async_get_conditions(hass, device_id, DOMAIN)
|
conditions = await toggle_entity.async_get_conditions(hass, device_id, DOMAIN)
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
"""Provides device automations for Climate."""
|
"""Provides device automations for Climate."""
|
||||||
from typing import List
|
from __future__ import annotations
|
||||||
|
|
||||||
import voluptuous as vol
|
import voluptuous as vol
|
||||||
|
|
||||||
@ -48,7 +48,7 @@ TOGGLE_TRIGGER_SCHEMA = toggle_entity.TRIGGER_SCHEMA.extend(
|
|||||||
TRIGGER_SCHEMA = vol.Any(TARGET_TRIGGER_SCHEMA, TOGGLE_TRIGGER_SCHEMA)
|
TRIGGER_SCHEMA = vol.Any(TARGET_TRIGGER_SCHEMA, TOGGLE_TRIGGER_SCHEMA)
|
||||||
|
|
||||||
|
|
||||||
async def async_get_triggers(hass: HomeAssistant, device_id: str) -> List[dict]:
|
async def async_get_triggers(hass: HomeAssistant, device_id: str) -> list[dict]:
|
||||||
"""List device triggers for Humidifier devices."""
|
"""List device triggers for Humidifier devices."""
|
||||||
registry = await entity_registry.async_get_registry(hass)
|
registry = await entity_registry.async_get_registry(hass)
|
||||||
triggers = await toggle_entity.async_get_triggers(hass, device_id, DOMAIN)
|
triggers = await toggle_entity.async_get_triggers(hass, device_id, DOMAIN)
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
"""Module that groups code required to handle state restore for component."""
|
"""Module that groups code required to handle state restore for component."""
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
import asyncio
|
import asyncio
|
||||||
import logging
|
import logging
|
||||||
from typing import Any, Dict, Iterable, Optional
|
from typing import Any, Iterable
|
||||||
|
|
||||||
from homeassistant.const import (
|
from homeassistant.const import (
|
||||||
ATTR_MODE,
|
ATTR_MODE,
|
||||||
@ -22,8 +24,8 @@ async def _async_reproduce_states(
|
|||||||
hass: HomeAssistantType,
|
hass: HomeAssistantType,
|
||||||
state: State,
|
state: State,
|
||||||
*,
|
*,
|
||||||
context: Optional[Context] = None,
|
context: Context | None = None,
|
||||||
reproduce_options: Optional[Dict[str, Any]] = None,
|
reproduce_options: dict[str, Any] | None = None,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Reproduce component states."""
|
"""Reproduce component states."""
|
||||||
cur_state = hass.states.get(state.entity_id)
|
cur_state = hass.states.get(state.entity_id)
|
||||||
@ -82,8 +84,8 @@ async def async_reproduce_states(
|
|||||||
hass: HomeAssistantType,
|
hass: HomeAssistantType,
|
||||||
states: Iterable[State],
|
states: Iterable[State],
|
||||||
*,
|
*,
|
||||||
context: Optional[Context] = None,
|
context: Context | None = None,
|
||||||
reproduce_options: Optional[Dict[str, Any]] = None,
|
reproduce_options: dict[str, Any] | None = None,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Reproduce component states."""
|
"""Reproduce component states."""
|
||||||
await asyncio.gather(
|
await asyncio.gather(
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
"""The Hyperion component."""
|
"""The Hyperion component."""
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
import asyncio
|
import asyncio
|
||||||
import logging
|
import logging
|
||||||
from typing import Any, Callable, Dict, List, Optional, Set, Tuple, cast
|
from typing import Any, Callable, cast
|
||||||
|
|
||||||
from awesomeversion import AwesomeVersion
|
from awesomeversion import AwesomeVersion
|
||||||
from hyperion import client, const as hyperion_const
|
from hyperion import client, const as hyperion_const
|
||||||
@ -70,7 +71,7 @@ def get_hyperion_unique_id(server_id: str, instance: int, name: str) -> str:
|
|||||||
return f"{server_id}_{instance}_{name}"
|
return f"{server_id}_{instance}_{name}"
|
||||||
|
|
||||||
|
|
||||||
def split_hyperion_unique_id(unique_id: str) -> Optional[Tuple[str, int, str]]:
|
def split_hyperion_unique_id(unique_id: str) -> tuple[str, int, str] | None:
|
||||||
"""Split a unique_id into a (server_id, instance, type) tuple."""
|
"""Split a unique_id into a (server_id, instance, type) tuple."""
|
||||||
data = tuple(unique_id.split("_", 2))
|
data = tuple(unique_id.split("_", 2))
|
||||||
if len(data) != 3:
|
if len(data) != 3:
|
||||||
@ -92,7 +93,7 @@ def create_hyperion_client(
|
|||||||
async def async_create_connect_hyperion_client(
|
async def async_create_connect_hyperion_client(
|
||||||
*args: Any,
|
*args: Any,
|
||||||
**kwargs: Any,
|
**kwargs: Any,
|
||||||
) -> Optional[client.HyperionClient]:
|
) -> client.HyperionClient | None:
|
||||||
"""Create and connect a Hyperion Client."""
|
"""Create and connect a Hyperion Client."""
|
||||||
hyperion_client = create_hyperion_client(*args, **kwargs)
|
hyperion_client = create_hyperion_client(*args, **kwargs)
|
||||||
|
|
||||||
@ -207,17 +208,17 @@ async def async_setup_entry(hass: HomeAssistant, config_entry: ConfigEntry) -> b
|
|||||||
CONF_ON_UNLOAD: [],
|
CONF_ON_UNLOAD: [],
|
||||||
}
|
}
|
||||||
|
|
||||||
async def async_instances_to_clients(response: Dict[str, Any]) -> None:
|
async def async_instances_to_clients(response: dict[str, Any]) -> None:
|
||||||
"""Convert instances to Hyperion clients."""
|
"""Convert instances to Hyperion clients."""
|
||||||
if not response or hyperion_const.KEY_DATA not in response:
|
if not response or hyperion_const.KEY_DATA not in response:
|
||||||
return
|
return
|
||||||
await async_instances_to_clients_raw(response[hyperion_const.KEY_DATA])
|
await async_instances_to_clients_raw(response[hyperion_const.KEY_DATA])
|
||||||
|
|
||||||
async def async_instances_to_clients_raw(instances: List[Dict[str, Any]]) -> None:
|
async def async_instances_to_clients_raw(instances: list[dict[str, Any]]) -> None:
|
||||||
"""Convert instances to Hyperion clients."""
|
"""Convert instances to Hyperion clients."""
|
||||||
registry = await async_get_registry(hass)
|
registry = await async_get_registry(hass)
|
||||||
running_instances: Set[int] = set()
|
running_instances: set[int] = set()
|
||||||
stopped_instances: Set[int] = set()
|
stopped_instances: set[int] = set()
|
||||||
existing_instances = hass.data[DOMAIN][config_entry.entry_id][
|
existing_instances = hass.data[DOMAIN][config_entry.entry_id][
|
||||||
CONF_INSTANCE_CLIENTS
|
CONF_INSTANCE_CLIENTS
|
||||||
]
|
]
|
||||||
|
@ -3,7 +3,7 @@ from __future__ import annotations
|
|||||||
|
|
||||||
import asyncio
|
import asyncio
|
||||||
import logging
|
import logging
|
||||||
from typing import Any, Dict, Optional
|
from typing import Any
|
||||||
from urllib.parse import urlparse
|
from urllib.parse import urlparse
|
||||||
|
|
||||||
from hyperion import client, const
|
from hyperion import client, const
|
||||||
@ -111,9 +111,9 @@ class HyperionConfigFlow(ConfigFlow, domain=DOMAIN):
|
|||||||
|
|
||||||
def __init__(self) -> None:
|
def __init__(self) -> None:
|
||||||
"""Instantiate config flow."""
|
"""Instantiate config flow."""
|
||||||
self._data: Dict[str, Any] = {}
|
self._data: dict[str, Any] = {}
|
||||||
self._request_token_task: Optional[asyncio.Task] = None
|
self._request_token_task: asyncio.Task | None = None
|
||||||
self._auth_id: Optional[str] = None
|
self._auth_id: str | None = None
|
||||||
self._require_confirm: bool = False
|
self._require_confirm: bool = False
|
||||||
self._port_ui: int = const.DEFAULT_PORT_UI
|
self._port_ui: int = const.DEFAULT_PORT_UI
|
||||||
|
|
||||||
@ -128,7 +128,7 @@ class HyperionConfigFlow(ConfigFlow, domain=DOMAIN):
|
|||||||
|
|
||||||
async def _advance_to_auth_step_if_necessary(
|
async def _advance_to_auth_step_if_necessary(
|
||||||
self, hyperion_client: client.HyperionClient
|
self, hyperion_client: client.HyperionClient
|
||||||
) -> Dict[str, Any]:
|
) -> dict[str, Any]:
|
||||||
"""Determine if auth is required."""
|
"""Determine if auth is required."""
|
||||||
auth_resp = await hyperion_client.async_is_auth_required()
|
auth_resp = await hyperion_client.async_is_auth_required()
|
||||||
|
|
||||||
@ -143,7 +143,7 @@ class HyperionConfigFlow(ConfigFlow, domain=DOMAIN):
|
|||||||
async def async_step_reauth(
|
async def async_step_reauth(
|
||||||
self,
|
self,
|
||||||
config_data: ConfigType,
|
config_data: ConfigType,
|
||||||
) -> Dict[str, Any]:
|
) -> dict[str, Any]:
|
||||||
"""Handle a reauthentication flow."""
|
"""Handle a reauthentication flow."""
|
||||||
self._data = dict(config_data)
|
self._data = dict(config_data)
|
||||||
async with self._create_client(raw_connection=True) as hyperion_client:
|
async with self._create_client(raw_connection=True) as hyperion_client:
|
||||||
@ -152,8 +152,8 @@ class HyperionConfigFlow(ConfigFlow, domain=DOMAIN):
|
|||||||
return await self._advance_to_auth_step_if_necessary(hyperion_client)
|
return await self._advance_to_auth_step_if_necessary(hyperion_client)
|
||||||
|
|
||||||
async def async_step_ssdp( # type: ignore[override]
|
async def async_step_ssdp( # type: ignore[override]
|
||||||
self, discovery_info: Dict[str, Any]
|
self, discovery_info: dict[str, Any]
|
||||||
) -> Dict[str, Any]:
|
) -> dict[str, Any]:
|
||||||
"""Handle a flow initiated by SSDP."""
|
"""Handle a flow initiated by SSDP."""
|
||||||
# Sample data provided by SSDP: {
|
# Sample data provided by SSDP: {
|
||||||
# 'ssdp_location': 'http://192.168.0.1:8090/description.xml',
|
# 'ssdp_location': 'http://192.168.0.1:8090/description.xml',
|
||||||
@ -223,8 +223,8 @@ class HyperionConfigFlow(ConfigFlow, domain=DOMAIN):
|
|||||||
|
|
||||||
async def async_step_user(
|
async def async_step_user(
|
||||||
self,
|
self,
|
||||||
user_input: Optional[ConfigType] = None,
|
user_input: ConfigType | None = None,
|
||||||
) -> Dict[str, Any]:
|
) -> dict[str, Any]:
|
||||||
"""Handle a flow initiated by the user."""
|
"""Handle a flow initiated by the user."""
|
||||||
errors = {}
|
errors = {}
|
||||||
if user_input:
|
if user_input:
|
||||||
@ -262,7 +262,7 @@ class HyperionConfigFlow(ConfigFlow, domain=DOMAIN):
|
|||||||
|
|
||||||
async def _request_token_task_func(self, auth_id: str) -> None:
|
async def _request_token_task_func(self, auth_id: str) -> None:
|
||||||
"""Send an async_request_token request."""
|
"""Send an async_request_token request."""
|
||||||
auth_resp: Optional[Dict[str, Any]] = None
|
auth_resp: dict[str, Any] | None = None
|
||||||
async with self._create_client(raw_connection=True) as hyperion_client:
|
async with self._create_client(raw_connection=True) as hyperion_client:
|
||||||
if hyperion_client:
|
if hyperion_client:
|
||||||
# The Hyperion-py client has a default timeout of 3 minutes on this request.
|
# The Hyperion-py client has a default timeout of 3 minutes on this request.
|
||||||
@ -283,7 +283,7 @@ class HyperionConfigFlow(ConfigFlow, domain=DOMAIN):
|
|||||||
# used to open a URL, that the user already knows the address of).
|
# used to open a URL, that the user already knows the address of).
|
||||||
return f"http://{self._data[CONF_HOST]}:{self._port_ui}"
|
return f"http://{self._data[CONF_HOST]}:{self._port_ui}"
|
||||||
|
|
||||||
async def _can_login(self) -> Optional[bool]:
|
async def _can_login(self) -> bool | None:
|
||||||
"""Verify login details."""
|
"""Verify login details."""
|
||||||
async with self._create_client(raw_connection=True) as hyperion_client:
|
async with self._create_client(raw_connection=True) as hyperion_client:
|
||||||
if not hyperion_client:
|
if not hyperion_client:
|
||||||
@ -296,8 +296,8 @@ class HyperionConfigFlow(ConfigFlow, domain=DOMAIN):
|
|||||||
|
|
||||||
async def async_step_auth(
|
async def async_step_auth(
|
||||||
self,
|
self,
|
||||||
user_input: Optional[ConfigType] = None,
|
user_input: ConfigType | None = None,
|
||||||
) -> Dict[str, Any]:
|
) -> dict[str, Any]:
|
||||||
"""Handle the auth step of a flow."""
|
"""Handle the auth step of a flow."""
|
||||||
errors = {}
|
errors = {}
|
||||||
if user_input:
|
if user_input:
|
||||||
@ -325,8 +325,8 @@ class HyperionConfigFlow(ConfigFlow, domain=DOMAIN):
|
|||||||
)
|
)
|
||||||
|
|
||||||
async def async_step_create_token(
|
async def async_step_create_token(
|
||||||
self, user_input: Optional[ConfigType] = None
|
self, user_input: ConfigType | None = None
|
||||||
) -> Dict[str, Any]:
|
) -> dict[str, Any]:
|
||||||
"""Send a request for a new token."""
|
"""Send a request for a new token."""
|
||||||
if user_input is None:
|
if user_input is None:
|
||||||
self._auth_id = client.generate_random_auth_id()
|
self._auth_id = client.generate_random_auth_id()
|
||||||
@ -351,8 +351,8 @@ class HyperionConfigFlow(ConfigFlow, domain=DOMAIN):
|
|||||||
)
|
)
|
||||||
|
|
||||||
async def async_step_create_token_external(
|
async def async_step_create_token_external(
|
||||||
self, auth_resp: Optional[ConfigType] = None
|
self, auth_resp: ConfigType | None = None
|
||||||
) -> Dict[str, Any]:
|
) -> dict[str, Any]:
|
||||||
"""Handle completion of the request for a new token."""
|
"""Handle completion of the request for a new token."""
|
||||||
if auth_resp is not None and client.ResponseOK(auth_resp):
|
if auth_resp is not None and client.ResponseOK(auth_resp):
|
||||||
token = auth_resp.get(const.KEY_INFO, {}).get(const.KEY_TOKEN)
|
token = auth_resp.get(const.KEY_INFO, {}).get(const.KEY_TOKEN)
|
||||||
@ -364,8 +364,8 @@ class HyperionConfigFlow(ConfigFlow, domain=DOMAIN):
|
|||||||
return self.async_external_step_done(next_step_id="create_token_fail")
|
return self.async_external_step_done(next_step_id="create_token_fail")
|
||||||
|
|
||||||
async def async_step_create_token_success(
|
async def async_step_create_token_success(
|
||||||
self, _: Optional[ConfigType] = None
|
self, _: ConfigType | None = None
|
||||||
) -> Dict[str, Any]:
|
) -> dict[str, Any]:
|
||||||
"""Create an entry after successful token creation."""
|
"""Create an entry after successful token creation."""
|
||||||
# Clean-up the request task.
|
# Clean-up the request task.
|
||||||
await self._cancel_request_token_task()
|
await self._cancel_request_token_task()
|
||||||
@ -380,16 +380,16 @@ class HyperionConfigFlow(ConfigFlow, domain=DOMAIN):
|
|||||||
return await self.async_step_confirm()
|
return await self.async_step_confirm()
|
||||||
|
|
||||||
async def async_step_create_token_fail(
|
async def async_step_create_token_fail(
|
||||||
self, _: Optional[ConfigType] = None
|
self, _: ConfigType | None = None
|
||||||
) -> Dict[str, Any]:
|
) -> dict[str, Any]:
|
||||||
"""Show an error on the auth form."""
|
"""Show an error on the auth form."""
|
||||||
# Clean-up the request task.
|
# Clean-up the request task.
|
||||||
await self._cancel_request_token_task()
|
await self._cancel_request_token_task()
|
||||||
return self.async_abort(reason="auth_new_token_not_granted_error")
|
return self.async_abort(reason="auth_new_token_not_granted_error")
|
||||||
|
|
||||||
async def async_step_confirm(
|
async def async_step_confirm(
|
||||||
self, user_input: Optional[ConfigType] = None
|
self, user_input: ConfigType | None = None
|
||||||
) -> Dict[str, Any]:
|
) -> dict[str, Any]:
|
||||||
"""Get final confirmation before entry creation."""
|
"""Get final confirmation before entry creation."""
|
||||||
if user_input is None and self._require_confirm:
|
if user_input is None and self._require_confirm:
|
||||||
return self.async_show_form(
|
return self.async_show_form(
|
||||||
@ -440,8 +440,8 @@ class HyperionOptionsFlow(OptionsFlow):
|
|||||||
self._config_entry = config_entry
|
self._config_entry = config_entry
|
||||||
|
|
||||||
async def async_step_init(
|
async def async_step_init(
|
||||||
self, user_input: Optional[Dict[str, Any]] = None
|
self, user_input: dict[str, Any] | None = None
|
||||||
) -> Dict[str, Any]:
|
) -> dict[str, Any]:
|
||||||
"""Manage the options."""
|
"""Manage the options."""
|
||||||
if user_input is not None:
|
if user_input is not None:
|
||||||
return self.async_create_entry(title="", data=user_input)
|
return self.async_create_entry(title="", data=user_input)
|
||||||
|
@ -4,7 +4,7 @@ from __future__ import annotations
|
|||||||
import functools
|
import functools
|
||||||
import logging
|
import logging
|
||||||
from types import MappingProxyType
|
from types import MappingProxyType
|
||||||
from typing import Any, Callable, Dict, List, Mapping, Optional, Sequence, Tuple
|
from typing import Any, Callable, Mapping, Sequence
|
||||||
|
|
||||||
from hyperion import client, const
|
from hyperion import client, const
|
||||||
|
|
||||||
@ -63,7 +63,7 @@ DEFAULT_EFFECT = KEY_EFFECT_SOLID
|
|||||||
DEFAULT_NAME = "Hyperion"
|
DEFAULT_NAME = "Hyperion"
|
||||||
DEFAULT_PORT = const.DEFAULT_PORT_JSON
|
DEFAULT_PORT = const.DEFAULT_PORT_JSON
|
||||||
DEFAULT_HDMI_PRIORITY = 880
|
DEFAULT_HDMI_PRIORITY = 880
|
||||||
DEFAULT_EFFECT_LIST: List[str] = []
|
DEFAULT_EFFECT_LIST: list[str] = []
|
||||||
|
|
||||||
SUPPORT_HYPERION = SUPPORT_COLOR | SUPPORT_BRIGHTNESS | SUPPORT_EFFECT
|
SUPPORT_HYPERION = SUPPORT_COLOR | SUPPORT_BRIGHTNESS | SUPPORT_EFFECT
|
||||||
|
|
||||||
@ -142,12 +142,12 @@ class HyperionBaseLight(LightEntity):
|
|||||||
self._rgb_color: Sequence[int] = DEFAULT_COLOR
|
self._rgb_color: Sequence[int] = DEFAULT_COLOR
|
||||||
self._effect: str = KEY_EFFECT_SOLID
|
self._effect: str = KEY_EFFECT_SOLID
|
||||||
|
|
||||||
self._static_effect_list: List[str] = [KEY_EFFECT_SOLID]
|
self._static_effect_list: list[str] = [KEY_EFFECT_SOLID]
|
||||||
if self._support_external_effects:
|
if self._support_external_effects:
|
||||||
self._static_effect_list += list(const.KEY_COMPONENTID_EXTERNAL_SOURCES)
|
self._static_effect_list += list(const.KEY_COMPONENTID_EXTERNAL_SOURCES)
|
||||||
self._effect_list: List[str] = self._static_effect_list[:]
|
self._effect_list: list[str] = self._static_effect_list[:]
|
||||||
|
|
||||||
self._client_callbacks: Mapping[str, Callable[[Dict[str, Any]], None]] = {
|
self._client_callbacks: Mapping[str, Callable[[dict[str, Any]], None]] = {
|
||||||
f"{const.KEY_ADJUSTMENT}-{const.KEY_UPDATE}": self._update_adjustment,
|
f"{const.KEY_ADJUSTMENT}-{const.KEY_UPDATE}": self._update_adjustment,
|
||||||
f"{const.KEY_COMPONENTS}-{const.KEY_UPDATE}": self._update_components,
|
f"{const.KEY_COMPONENTS}-{const.KEY_UPDATE}": self._update_components,
|
||||||
f"{const.KEY_EFFECTS}-{const.KEY_UPDATE}": self._update_effect_list,
|
f"{const.KEY_EFFECTS}-{const.KEY_UPDATE}": self._update_effect_list,
|
||||||
@ -176,7 +176,7 @@ class HyperionBaseLight(LightEntity):
|
|||||||
return self._brightness
|
return self._brightness
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def hs_color(self) -> Tuple[float, float]:
|
def hs_color(self) -> tuple[float, float]:
|
||||||
"""Return last color value set."""
|
"""Return last color value set."""
|
||||||
return color_util.color_RGB_to_hs(*self._rgb_color)
|
return color_util.color_RGB_to_hs(*self._rgb_color)
|
||||||
|
|
||||||
@ -196,7 +196,7 @@ class HyperionBaseLight(LightEntity):
|
|||||||
return self._effect
|
return self._effect
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def effect_list(self) -> List[str]:
|
def effect_list(self) -> list[str]:
|
||||||
"""Return the list of supported effects."""
|
"""Return the list of supported effects."""
|
||||||
return self._effect_list
|
return self._effect_list
|
||||||
|
|
||||||
@ -305,9 +305,9 @@ class HyperionBaseLight(LightEntity):
|
|||||||
|
|
||||||
def _set_internal_state(
|
def _set_internal_state(
|
||||||
self,
|
self,
|
||||||
brightness: Optional[int] = None,
|
brightness: int | None = None,
|
||||||
rgb_color: Optional[Sequence[int]] = None,
|
rgb_color: Sequence[int] | None = None,
|
||||||
effect: Optional[str] = None,
|
effect: str | None = None,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Set the internal state."""
|
"""Set the internal state."""
|
||||||
if brightness is not None:
|
if brightness is not None:
|
||||||
@ -318,12 +318,12 @@ class HyperionBaseLight(LightEntity):
|
|||||||
self._effect = effect
|
self._effect = effect
|
||||||
|
|
||||||
@callback
|
@callback
|
||||||
def _update_components(self, _: Optional[Dict[str, Any]] = None) -> None:
|
def _update_components(self, _: dict[str, Any] | None = None) -> None:
|
||||||
"""Update Hyperion components."""
|
"""Update Hyperion components."""
|
||||||
self.async_write_ha_state()
|
self.async_write_ha_state()
|
||||||
|
|
||||||
@callback
|
@callback
|
||||||
def _update_adjustment(self, _: Optional[Dict[str, Any]] = None) -> None:
|
def _update_adjustment(self, _: dict[str, Any] | None = None) -> None:
|
||||||
"""Update Hyperion adjustments."""
|
"""Update Hyperion adjustments."""
|
||||||
if self._client.adjustment:
|
if self._client.adjustment:
|
||||||
brightness_pct = self._client.adjustment[0].get(
|
brightness_pct = self._client.adjustment[0].get(
|
||||||
@ -337,7 +337,7 @@ class HyperionBaseLight(LightEntity):
|
|||||||
self.async_write_ha_state()
|
self.async_write_ha_state()
|
||||||
|
|
||||||
@callback
|
@callback
|
||||||
def _update_priorities(self, _: Optional[Dict[str, Any]] = None) -> None:
|
def _update_priorities(self, _: dict[str, Any] | None = None) -> None:
|
||||||
"""Update Hyperion priorities."""
|
"""Update Hyperion priorities."""
|
||||||
priority = self._get_priority_entry_that_dictates_state()
|
priority = self._get_priority_entry_that_dictates_state()
|
||||||
if priority and self._allow_priority_update(priority):
|
if priority and self._allow_priority_update(priority):
|
||||||
@ -361,11 +361,11 @@ class HyperionBaseLight(LightEntity):
|
|||||||
self.async_write_ha_state()
|
self.async_write_ha_state()
|
||||||
|
|
||||||
@callback
|
@callback
|
||||||
def _update_effect_list(self, _: Optional[Dict[str, Any]] = None) -> None:
|
def _update_effect_list(self, _: dict[str, Any] | None = None) -> None:
|
||||||
"""Update Hyperion effects."""
|
"""Update Hyperion effects."""
|
||||||
if not self._client.effects:
|
if not self._client.effects:
|
||||||
return
|
return
|
||||||
effect_list: List[str] = []
|
effect_list: list[str] = []
|
||||||
for effect in self._client.effects or []:
|
for effect in self._client.effects or []:
|
||||||
if const.KEY_NAME in effect:
|
if const.KEY_NAME in effect:
|
||||||
effect_list.append(effect[const.KEY_NAME])
|
effect_list.append(effect[const.KEY_NAME])
|
||||||
@ -391,7 +391,7 @@ class HyperionBaseLight(LightEntity):
|
|||||||
)
|
)
|
||||||
|
|
||||||
@callback
|
@callback
|
||||||
def _update_client(self, _: Optional[Dict[str, Any]] = None) -> None:
|
def _update_client(self, _: dict[str, Any] | None = None) -> None:
|
||||||
"""Update client connection state."""
|
"""Update client connection state."""
|
||||||
self.async_write_ha_state()
|
self.async_write_ha_state()
|
||||||
|
|
||||||
@ -419,18 +419,18 @@ class HyperionBaseLight(LightEntity):
|
|||||||
"""Whether or not to support setting external effects from the light entity."""
|
"""Whether or not to support setting external effects from the light entity."""
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def _get_priority_entry_that_dictates_state(self) -> Optional[Dict[str, Any]]:
|
def _get_priority_entry_that_dictates_state(self) -> dict[str, Any] | None:
|
||||||
"""Get the relevant Hyperion priority entry to consider."""
|
"""Get the relevant Hyperion priority entry to consider."""
|
||||||
# Return the visible priority (whether or not it is the HA priority).
|
# Return the visible priority (whether or not it is the HA priority).
|
||||||
|
|
||||||
# Explicit type specifier to ensure this works when the underlying (typed)
|
# Explicit type specifier to ensure this works when the underlying (typed)
|
||||||
# library is installed along with the tests. Casts would trigger a
|
# library is installed along with the tests. Casts would trigger a
|
||||||
# redundant-cast warning in this case.
|
# redundant-cast warning in this case.
|
||||||
priority: Optional[Dict[str, Any]] = self._client.visible_priority
|
priority: dict[str, Any] | None = self._client.visible_priority
|
||||||
return priority
|
return priority
|
||||||
|
|
||||||
# pylint: disable=no-self-use
|
# pylint: disable=no-self-use
|
||||||
def _allow_priority_update(self, priority: Optional[Dict[str, Any]] = None) -> bool:
|
def _allow_priority_update(self, priority: dict[str, Any] | None = None) -> bool:
|
||||||
"""Determine whether to allow a priority to update internal state."""
|
"""Determine whether to allow a priority to update internal state."""
|
||||||
return True
|
return True
|
||||||
|
|
||||||
@ -525,7 +525,7 @@ class HyperionPriorityLight(HyperionBaseLight):
|
|||||||
"""Whether or not to support setting external effects from the light entity."""
|
"""Whether or not to support setting external effects from the light entity."""
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def _get_priority_entry_that_dictates_state(self) -> Optional[Dict[str, Any]]:
|
def _get_priority_entry_that_dictates_state(self) -> dict[str, Any] | None:
|
||||||
"""Get the relevant Hyperion priority entry to consider."""
|
"""Get the relevant Hyperion priority entry to consider."""
|
||||||
# Return the active priority (if any) at the configured HA priority.
|
# Return the active priority (if any) at the configured HA priority.
|
||||||
for candidate in self._client.priorities or []:
|
for candidate in self._client.priorities or []:
|
||||||
@ -537,12 +537,12 @@ class HyperionPriorityLight(HyperionBaseLight):
|
|||||||
# Explicit type specifier to ensure this works when the underlying
|
# Explicit type specifier to ensure this works when the underlying
|
||||||
# (typed) library is installed along with the tests. Casts would trigger
|
# (typed) library is installed along with the tests. Casts would trigger
|
||||||
# a redundant-cast warning in this case.
|
# a redundant-cast warning in this case.
|
||||||
output: Dict[str, Any] = candidate
|
output: dict[str, Any] = candidate
|
||||||
return output
|
return output
|
||||||
return None
|
return None
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def _is_priority_entry_black(cls, priority: Optional[Dict[str, Any]]) -> bool:
|
def _is_priority_entry_black(cls, priority: dict[str, Any] | None) -> bool:
|
||||||
"""Determine if a given priority entry is the color black."""
|
"""Determine if a given priority entry is the color black."""
|
||||||
if not priority:
|
if not priority:
|
||||||
return False
|
return False
|
||||||
@ -552,7 +552,7 @@ class HyperionPriorityLight(HyperionBaseLight):
|
|||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def _allow_priority_update(self, priority: Optional[Dict[str, Any]] = None) -> bool:
|
def _allow_priority_update(self, priority: dict[str, Any] | None = None) -> bool:
|
||||||
"""Determine whether to allow a Hyperion priority to update entity attributes."""
|
"""Determine whether to allow a Hyperion priority to update entity attributes."""
|
||||||
# Black is treated as 'off' (and Home Assistant does not support selecting black
|
# Black is treated as 'off' (and Home Assistant does not support selecting black
|
||||||
# from the color selector). Do not set our internal attributes if the priority is
|
# from the color selector). Do not set our internal attributes if the priority is
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
"""Switch platform for Hyperion."""
|
"""Switch platform for Hyperion."""
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
import functools
|
import functools
|
||||||
from typing import Any, Callable, Dict, Optional
|
from typing import Any, Callable
|
||||||
|
|
||||||
from hyperion import client
|
from hyperion import client
|
||||||
from hyperion.const import (
|
from hyperion.const import (
|
||||||
@ -187,7 +188,7 @@ class HyperionComponentSwitch(SwitchEntity):
|
|||||||
await self._async_send_set_component(False)
|
await self._async_send_set_component(False)
|
||||||
|
|
||||||
@callback
|
@callback
|
||||||
def _update_components(self, _: Optional[Dict[str, Any]] = None) -> None:
|
def _update_components(self, _: dict[str, Any] | None = None) -> None:
|
||||||
"""Update Hyperion components."""
|
"""Update Hyperion components."""
|
||||||
self.async_write_ha_state()
|
self.async_write_ha_state()
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user