mirror of
https://github.com/home-assistant/core.git
synced 2026-06-25 08:05:21 +02:00
Compare commits
329 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 73967ec3b8 | |||
| 7e7c846c78 | |||
| 7ff7c45b18 | |||
| 4481e90ee6 | |||
| 7670dcb227 | |||
| db0f9d1f54 | |||
| f1535bf8a4 | |||
| c460100fa1 | |||
| 53e2a9341f | |||
| 0e713d549c | |||
| a068574fe2 | |||
| f57418ed60 | |||
| 8d1bf68045 | |||
| c5bfad9bfe | |||
| 679b0ac2aa | |||
| 22a583c83f | |||
| d966f71832 | |||
| 08569420f6 | |||
| c1bcbca520 | |||
| c73c647162 | |||
| b2f1c38b6f | |||
| e8824bedf5 | |||
| 27b107f4a5 | |||
| 7536e8647f | |||
| 75c6058396 | |||
| 77533e5af5 | |||
| 31a1e7c5e1 | |||
| 20f4e7306b | |||
| 5c1ac08c92 | |||
| 5631c68069 | |||
| 8648611278 | |||
| 971d15be1e | |||
| b6f2429ff3 | |||
| c676e2a806 | |||
| a27ea536db | |||
| 22e25d9ce2 | |||
| 1cb5e31901 | |||
| 4f414d0035 | |||
| 30b648ea6a | |||
| 18a259718f | |||
| 45de0f4b4a | |||
| 940bf5bf09 | |||
| 07e78b6dbf | |||
| abcb677b57 | |||
| 7e638f9d0c | |||
| 8aca6115f4 | |||
| dd688986f1 | |||
| c519b7ba07 | |||
| 158595464a | |||
| f81aff0a69 | |||
| 9f90e6ec22 | |||
| 31b311e17a | |||
| 7e07f2ab87 | |||
| 312f4c8c35 | |||
| ddeeba5f87 | |||
| 82a043bc47 | |||
| 629b9a5f9b | |||
| 9400c2e40e | |||
| 8a57bb0640 | |||
| ab8f1bf88e | |||
| b61ad539d9 | |||
| 283dcee830 | |||
| e61a3ac684 | |||
| 5595ba12fb | |||
| 1bfd4d1500 | |||
| 249c3bb5dd | |||
| 982fe7a370 | |||
| 035e7e0a38 | |||
| f6b0036ccc | |||
| b2a26afb14 | |||
| 231470f4dc | |||
| 8aeb5d63ab | |||
| d613591463 | |||
| dc6269f52d | |||
| 31690ac2d3 | |||
| ffe008c6b2 | |||
| dc48c3e30f | |||
| 448fd04137 | |||
| 41e7837bcf | |||
| 951062fa82 | |||
| f2ac5a4153 | |||
| 12832fe3cd | |||
| d35e58fdc7 | |||
| 3570cd0ee3 | |||
| 5a99cb4cca | |||
| d49a9c4780 | |||
| c330a983e4 | |||
| e47f58362a | |||
| 18f5998162 | |||
| e41d9d5447 | |||
| 9509bcb8e3 | |||
| eb50acfc26 | |||
| 3a880644bc | |||
| 0a39eb3f5d | |||
| 91f4168439 | |||
| e1c8f3da78 | |||
| c868f760d5 | |||
| 8965e2241e | |||
| b17e86d45c | |||
| 91e70bcc1a | |||
| 11f86f30ac | |||
| 75c490139d | |||
| 4ccd854225 | |||
| b7fbbf5a1f | |||
| 5e05f6f845 | |||
| 294d1cb726 | |||
| 7074c291a0 | |||
| 8bf668186d | |||
| 1d02788001 | |||
| 3cc975aae3 | |||
| 28294dfdfc | |||
| b2aa1c1b8d | |||
| fa13cedf83 | |||
| 0b7e2fa28b | |||
| 7edcbff62c | |||
| aeb020c60f | |||
| 9c2914d03a | |||
| 980d3c28fd | |||
| a7fb69cf3e | |||
| b24791fa71 | |||
| b6b8391cbf | |||
| dad7da0e3b | |||
| 87cdf3a0e3 | |||
| 634980b53f | |||
| e244b7f2b6 | |||
| 761f1f8a0e | |||
| a51c653797 | |||
| af6ae63eeb | |||
| 11b49607bd | |||
| 956e26196a | |||
| 3946162140 | |||
| c3f7a1d5b0 | |||
| c9a6502c16 | |||
| 708d5b46e8 | |||
| 49bd80541c | |||
| a8c42222a3 | |||
| 7e805f2f2a | |||
| 7e684dbcca | |||
| cdd063083d | |||
| 1e4e77465a | |||
| 16671e29d8 | |||
| b8dc091a21 | |||
| 66afd77a96 | |||
| 134519e97f | |||
| c1957f2f35 | |||
| 89e2b2b9fc | |||
| 9a1f40280b | |||
| 1518aaa82d | |||
| 6dd60a3723 | |||
| c6b4d5c7c3 | |||
| d782cd8289 | |||
| 2f633193e9 | |||
| 5ada338f13 | |||
| 5e6085f961 | |||
| 8198aa263b | |||
| 2abe5d23f4 | |||
| e8428ea639 | |||
| 81f7e53dfa | |||
| 151fd1409f | |||
| 690fb22c11 | |||
| 395c02ddb4 | |||
| 78f903d0f6 | |||
| ea7ccae927 | |||
| 2008551cc9 | |||
| 2b7cd9295a | |||
| a4131e128c | |||
| 05ec46906c | |||
| 06aa380e09 | |||
| 758c6c62b2 | |||
| 27d229b161 | |||
| 010b789026 | |||
| ee1d378574 | |||
| 324f08d00f | |||
| 957c24fcd7 | |||
| 97dbd59750 | |||
| 16c7ec30b0 | |||
| bd4cdeb510 | |||
| ac1f82d130 | |||
| a9393d777e | |||
| d28827a4f2 | |||
| 7e62ff35fd | |||
| 0a5c1ef8eb | |||
| a88093afd2 | |||
| 9fd90283b3 | |||
| 3159242b68 | |||
| f5985b03e4 | |||
| 040a3bcb10 | |||
| 5aaf6704a9 | |||
| 2fcd00b301 | |||
| 0b439e6e4c | |||
| d13a5b7eec | |||
| de49716ec1 | |||
| 67c6921847 | |||
| 002b638013 | |||
| 4b60ed30c7 | |||
| 6f1deec507 | |||
| 227ba8032f | |||
| 7da3ecf033 | |||
| 8b293a18d3 | |||
| 3dc077f280 | |||
| d368a95323 | |||
| 495f41a742 | |||
| 9f7529706d | |||
| 8f6b1dff9c | |||
| f260a1bb7b | |||
| 157e137ea9 | |||
| b2e1a296d4 | |||
| e78a2c9f01 | |||
| 9011225a42 | |||
| 81ef9b99c2 | |||
| fa0207698a | |||
| 275883a95a | |||
| ebd252a225 | |||
| 2de6c0281d | |||
| f95671f0f4 | |||
| 5fcae9ecf7 | |||
| 0b86cfa496 | |||
| d45bdf37d5 | |||
| a9205df4a3 | |||
| c333744fd2 | |||
| 2f64601990 | |||
| cbd35be271 | |||
| 92ac14f42a | |||
| 45e568c73e | |||
| a121b8d146 | |||
| a2bd7d5857 | |||
| a6e639377b | |||
| 2147a851c3 | |||
| 9034afd29e | |||
| 5c5d259f63 | |||
| cc16a9086f | |||
| 5d1f8f770c | |||
| cea6b9b0b7 | |||
| 77f7c26399 | |||
| 8e0a5b258c | |||
| f8b942818c | |||
| 9660d12c77 | |||
| 7f1533a6e1 | |||
| 336d9e9126 | |||
| 1dde2d918e | |||
| 34a6b0ca61 | |||
| e92286ecd6 | |||
| 82bb9748db | |||
| 68e5e58a1c | |||
| f3e8403e9a | |||
| 28076bcad6 | |||
| ff25428e56 | |||
| 608acd422f | |||
| c860e83ec9 | |||
| c9f3f4a265 | |||
| e346a801d1 | |||
| a5c193931f | |||
| d273350db1 | |||
| 45f27b8b6e | |||
| d3208a420f | |||
| d0d35e380f | |||
| 2735e58d7f | |||
| ad3eab80c3 | |||
| 18e5d284b4 | |||
| e5052eaf44 | |||
| 62c2e8d2fd | |||
| 1f505067dd | |||
| 72875b3b5e | |||
| 3be755e496 | |||
| 5285798052 | |||
| da49e37946 | |||
| 2f9de98f2d | |||
| 383a6426fc | |||
| 5ed60cd057 | |||
| a1250b7bfb | |||
| 240e5219ad | |||
| 418f352ce7 | |||
| 599967b1d8 | |||
| ad82729357 | |||
| 30d8bf4231 | |||
| 5436d8af9b | |||
| 88adf39ef3 | |||
| 14b14bddf1 | |||
| 3c4a30be6b | |||
| 2988eb4b19 | |||
| 00eef14558 | |||
| d02516dd09 | |||
| aabb6b3d04 | |||
| 50c2c7c4bc | |||
| e81dd426bb | |||
| c4c569c181 | |||
| 6182426132 | |||
| a073cc4f7d | |||
| 07ddc08d84 | |||
| 17673dcf55 | |||
| a864bc1c80 | |||
| a15d80daa2 | |||
| e123b29258 | |||
| 5669a7b602 | |||
| fe358a4a1f | |||
| 3a93d6370b | |||
| 89576f01e6 | |||
| f51895b0c9 | |||
| d0dcbfadaa | |||
| 5e0d3627c2 | |||
| 80c90732a3 | |||
| 16eca3909a | |||
| 1b471da31f | |||
| 7391209f48 | |||
| 0683344079 | |||
| 0b77cf9e4b | |||
| e0a87d966d | |||
| af53d2d082 | |||
| da7fa80e75 | |||
| 6cf1e7fb48 | |||
| 18fa0ac47d | |||
| 4afced1a49 | |||
| 74a4471160 | |||
| 857a3de066 | |||
| 06bf2ff6de | |||
| 6a5dae9cc3 | |||
| 475ebbc028 | |||
| 6e7643e997 | |||
| 1f954cda0d | |||
| 2961fca1b1 | |||
| 106b189206 | |||
| 0387034f4e | |||
| f81b6abca9 | |||
| 43f6e7977e | |||
| 706fea4ec5 | |||
| 74d23503e7 | |||
| 4ca5da2365 | |||
| 53c77ae2ef | |||
| 14968f9d67 |
@@ -53,3 +53,4 @@ This repository contains the core of Home Assistant, a Python 3 based home autom
|
||||
- When validation guarantees a dict key exists, prefer direct key access (`data["key"]`) instead of `.get("key")` so contract violations are surfaced instead of silently masked.
|
||||
- Keep comments concise. Prefer one short line stating the non-obvious constraint, or no comment at all.
|
||||
- Do not add comments that just restate the code on the following line(s) (e.g. `# Check if initialized` above `if self.initialized:`). Comments should only explain why (non-obvious constraints, surprising behavior, or workarounds), never what. Never add comments that justify a change by referencing what the code looked like before.
|
||||
- Do not add section or divider comments (e.g. `# --- XYZ Triggers ---`) inside or outside of functions, since those can easily become stale and be misleading.
|
||||
|
||||
@@ -8,15 +8,11 @@ name: Check requirements (deterministic)
|
||||
|
||||
# yamllint disable-line rule:truthy
|
||||
on:
|
||||
# Auto-trigger on PRs that touch tracked requirement files is disabled
|
||||
# for now while we iterate — testing the workflow_run handoff to the
|
||||
# agentic stage is hard with an auto-trigger. Re-enable once the chain
|
||||
# has been validated end-to-end.
|
||||
# pull_request:
|
||||
# types: [opened, synchronize, reopened]
|
||||
# paths:
|
||||
# - "**/requirements*.txt"
|
||||
# - "homeassistant/package_constraints.txt"
|
||||
pull_request:
|
||||
types: [opened, synchronize, reopened]
|
||||
paths:
|
||||
- "requirements*.txt"
|
||||
- "homeassistant/package_constraints.txt"
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
pull_request_number:
|
||||
|
||||
@@ -42,3 +42,4 @@ This repository contains the core of Home Assistant, a Python 3 based home autom
|
||||
- When validation guarantees a dict key exists, prefer direct key access (`data["key"]`) instead of `.get("key")` so contract violations are surfaced instead of silently masked.
|
||||
- Keep comments concise. Prefer one short line stating the non-obvious constraint, or no comment at all.
|
||||
- Do not add comments that just restate the code on the following line(s) (e.g. `# Check if initialized` above `if self.initialized:`). Comments should only explain why (non-obvious constraints, surprising behavior, or workarounds), never what. Never add comments that justify a change by referencing what the code looked like before.
|
||||
- Do not add section or divider comments (e.g. `# --- XYZ Triggers ---`) inside or outside of functions, since those can easily become stale and be misleading.
|
||||
|
||||
Generated
+6
-6
@@ -781,8 +781,8 @@ CLAUDE.md @home-assistant/core
|
||||
/tests/components/homevolt/ @danielhiversen @liudger
|
||||
/homeassistant/components/homewizard/ @DCSBL
|
||||
/tests/components/homewizard/ @DCSBL
|
||||
/homeassistant/components/honeywell/ @rdfurman @mkmer
|
||||
/tests/components/honeywell/ @rdfurman @mkmer
|
||||
/homeassistant/components/honeywell/ @mkmer
|
||||
/tests/components/honeywell/ @mkmer
|
||||
/homeassistant/components/honeywell_string_lights/ @balloob
|
||||
/tests/components/honeywell_string_lights/ @balloob
|
||||
/homeassistant/components/hr_energy_qube/ @MattieGit
|
||||
@@ -1558,7 +1558,8 @@ CLAUDE.md @home-assistant/core
|
||||
/tests/components/rympro/ @OnFreund @elad-bar @maorcc
|
||||
/homeassistant/components/sabnzbd/ @shaiu @jpbede
|
||||
/tests/components/sabnzbd/ @shaiu @jpbede
|
||||
/homeassistant/components/saj/ @fredericvl
|
||||
/homeassistant/components/saj/ @fredericvl @edurenye
|
||||
/tests/components/saj/ @fredericvl @edurenye
|
||||
/homeassistant/components/samsung_infrared/ @lmaertin
|
||||
/tests/components/samsung_infrared/ @lmaertin
|
||||
/homeassistant/components/samsungtv/ @chemelli74
|
||||
@@ -1711,8 +1712,8 @@ CLAUDE.md @home-assistant/core
|
||||
/tests/components/sql/ @gjohansson-ST @dougiteixeira
|
||||
/homeassistant/components/squeezebox/ @rajlaud @pssc @peteS-UK
|
||||
/tests/components/squeezebox/ @rajlaud @pssc @peteS-UK
|
||||
/homeassistant/components/srp_energy/ @briglx
|
||||
/tests/components/srp_energy/ @briglx
|
||||
/homeassistant/components/srp_energy/ @briglx @ammmze
|
||||
/tests/components/srp_energy/ @briglx @ammmze
|
||||
/homeassistant/components/starline/ @anonym-tsk
|
||||
/tests/components/starline/ @anonym-tsk
|
||||
/homeassistant/components/statistics/ @ThomDietrich @gjohansson-ST
|
||||
@@ -1899,7 +1900,6 @@ CLAUDE.md @home-assistant/core
|
||||
/tests/components/unifi_direct/ @tofuSCHNITZEL
|
||||
/homeassistant/components/unifi_discovery/ @RaHehl
|
||||
/tests/components/unifi_discovery/ @RaHehl
|
||||
/homeassistant/components/unifiled/ @florisvdk
|
||||
/homeassistant/components/unifiprotect/ @RaHehl
|
||||
/tests/components/unifiprotect/ @RaHehl
|
||||
/homeassistant/components/upb/ @gwww
|
||||
|
||||
@@ -6,7 +6,7 @@ from collections.abc import Mapping
|
||||
from datetime import datetime, timedelta
|
||||
from functools import partial
|
||||
import time
|
||||
from typing import Any, cast
|
||||
from typing import Any, cast, override
|
||||
|
||||
import jwt
|
||||
|
||||
@@ -109,6 +109,7 @@ class AuthManagerFlowManager(
|
||||
super().__init__(hass)
|
||||
self.auth_manager = auth_manager
|
||||
|
||||
@override
|
||||
async def async_create_flow(
|
||||
self,
|
||||
handler_key: tuple[str, str],
|
||||
@@ -122,6 +123,7 @@ class AuthManagerFlowManager(
|
||||
raise KeyError(f"Unknown auth provider {handler_key}")
|
||||
return await auth_provider.async_login_flow(context)
|
||||
|
||||
@override
|
||||
async def async_finish_flow(
|
||||
self,
|
||||
flow: FlowHandler[AuthFlowContext, AuthFlowResult, tuple[str, str]],
|
||||
|
||||
@@ -39,6 +39,7 @@ class _PyJWSWithLoadCache(PyJWS):
|
||||
# We only ever have a global instance of this class
|
||||
# so we do not have to worry about the LRU growing
|
||||
# each time we create a new instance.
|
||||
@override
|
||||
def _load(self, jwt: str | bytes) -> tuple[bytes, bytes, dict, bytes]:
|
||||
"""Load a JWS."""
|
||||
return super()._load(jwt)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
"""Example auth module."""
|
||||
|
||||
from typing import Any
|
||||
from typing import Any, override
|
||||
|
||||
import voluptuous as vol
|
||||
|
||||
@@ -35,6 +35,7 @@ class InsecureExampleModule(MultiFactorAuthModule):
|
||||
self._data = config["data"]
|
||||
|
||||
@property
|
||||
@override
|
||||
def input_schema(self) -> vol.Schema:
|
||||
"""Validate login flow input data."""
|
||||
return vol.Schema({vol.Required("pin"): str})
|
||||
@@ -44,6 +45,7 @@ class InsecureExampleModule(MultiFactorAuthModule):
|
||||
"""Validate async_setup_user input data."""
|
||||
return vol.Schema({vol.Required("pin"): str})
|
||||
|
||||
@override
|
||||
async def async_setup_flow(self, user_id: str) -> SetupFlow:
|
||||
"""Return a data entry flow handler for setup module.
|
||||
|
||||
@@ -51,6 +53,7 @@ class InsecureExampleModule(MultiFactorAuthModule):
|
||||
"""
|
||||
return SetupFlow(self, self.setup_schema, user_id)
|
||||
|
||||
@override
|
||||
async def async_setup_user(self, user_id: str, setup_data: Any) -> Any:
|
||||
"""Set up user to use mfa module."""
|
||||
# data shall has been validate in caller
|
||||
@@ -64,6 +67,7 @@ class InsecureExampleModule(MultiFactorAuthModule):
|
||||
|
||||
self._data.append({"user_id": user_id, "pin": pin})
|
||||
|
||||
@override
|
||||
async def async_depose_user(self, user_id: str) -> None:
|
||||
"""Remove user from mfa module."""
|
||||
found = None
|
||||
@@ -74,10 +78,12 @@ class InsecureExampleModule(MultiFactorAuthModule):
|
||||
if found:
|
||||
self._data.remove(found)
|
||||
|
||||
@override
|
||||
async def async_is_user_setup(self, user_id: str) -> bool:
|
||||
"""Return whether user is setup."""
|
||||
return any(data["user_id"] == user_id for data in self._data)
|
||||
|
||||
@override
|
||||
async def async_validate(self, user_id: str, user_input: dict[str, Any]) -> bool:
|
||||
"""Return True if validation passed."""
|
||||
return any(
|
||||
|
||||
@@ -5,7 +5,7 @@ Sending HOTP through notify service
|
||||
|
||||
import asyncio
|
||||
import logging
|
||||
from typing import Any, cast
|
||||
from typing import Any, cast, override
|
||||
|
||||
import attr
|
||||
import voluptuous as vol
|
||||
@@ -107,6 +107,7 @@ class NotifyAuthModule(MultiFactorAuthModule):
|
||||
self._init_lock = asyncio.Lock()
|
||||
|
||||
@property
|
||||
@override
|
||||
def input_schema(self) -> vol.Schema:
|
||||
"""Validate login flow input data."""
|
||||
return vol.Schema({vol.Required(INPUT_FIELD_CODE): str})
|
||||
@@ -159,6 +160,7 @@ class NotifyAuthModule(MultiFactorAuthModule):
|
||||
|
||||
return sorted(unordered_services)
|
||||
|
||||
@override
|
||||
async def async_setup_flow(self, user_id: str) -> NotifySetupFlow:
|
||||
"""Return a data entry flow handler for setup module.
|
||||
|
||||
@@ -168,6 +170,7 @@ class NotifyAuthModule(MultiFactorAuthModule):
|
||||
self, self.input_schema, user_id, self.aync_get_available_notify_services()
|
||||
)
|
||||
|
||||
@override
|
||||
async def async_setup_user(self, user_id: str, setup_data: Any) -> Any:
|
||||
"""Set up auth module for user."""
|
||||
if self._user_settings is None:
|
||||
@@ -181,6 +184,7 @@ class NotifyAuthModule(MultiFactorAuthModule):
|
||||
|
||||
await self._async_save()
|
||||
|
||||
@override
|
||||
async def async_depose_user(self, user_id: str) -> None:
|
||||
"""Depose auth module for user."""
|
||||
if self._user_settings is None:
|
||||
@@ -190,6 +194,7 @@ class NotifyAuthModule(MultiFactorAuthModule):
|
||||
if self._user_settings.pop(user_id, None):
|
||||
await self._async_save()
|
||||
|
||||
@override
|
||||
async def async_is_user_setup(self, user_id: str) -> bool:
|
||||
"""Return whether user is setup."""
|
||||
if self._user_settings is None:
|
||||
@@ -198,6 +203,7 @@ class NotifyAuthModule(MultiFactorAuthModule):
|
||||
|
||||
return user_id in self._user_settings
|
||||
|
||||
@override
|
||||
async def async_validate(self, user_id: str, user_input: dict[str, Any]) -> bool:
|
||||
"""Return True if validation passed."""
|
||||
if self._user_settings is None:
|
||||
@@ -283,6 +289,7 @@ class NotifySetupFlow(SetupFlow[NotifyAuthModule]):
|
||||
self._notify_service: str | None = None
|
||||
self._target: str | None = None
|
||||
|
||||
@override
|
||||
async def async_step_init(
|
||||
self, user_input: dict[str, str] | None = None
|
||||
) -> FlowResult:
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
import asyncio
|
||||
from io import BytesIO
|
||||
from typing import Any, cast
|
||||
from typing import Any, cast, override
|
||||
|
||||
import voluptuous as vol
|
||||
|
||||
@@ -87,6 +87,7 @@ class TotpAuthModule(MultiFactorAuthModule):
|
||||
self._init_lock = asyncio.Lock()
|
||||
|
||||
@property
|
||||
@override
|
||||
def input_schema(self) -> vol.Schema:
|
||||
"""Validate login flow input data."""
|
||||
return vol.Schema({vol.Required(INPUT_FIELD_CODE): str})
|
||||
@@ -115,6 +116,7 @@ class TotpAuthModule(MultiFactorAuthModule):
|
||||
self._users[user_id] = ota_secret # type: ignore[index]
|
||||
return ota_secret
|
||||
|
||||
@override
|
||||
async def async_setup_flow(self, user_id: str) -> TotpSetupFlow:
|
||||
"""Return a data entry flow handler for setup module.
|
||||
|
||||
@@ -124,6 +126,7 @@ class TotpAuthModule(MultiFactorAuthModule):
|
||||
assert user is not None
|
||||
return TotpSetupFlow(self, self.input_schema, user)
|
||||
|
||||
@override
|
||||
async def async_setup_user(self, user_id: str, setup_data: Any) -> str:
|
||||
"""Set up auth module for user."""
|
||||
if self._users is None:
|
||||
@@ -136,6 +139,7 @@ class TotpAuthModule(MultiFactorAuthModule):
|
||||
await self._async_save()
|
||||
return result
|
||||
|
||||
@override
|
||||
async def async_depose_user(self, user_id: str) -> None:
|
||||
"""Depose auth module for user."""
|
||||
if self._users is None:
|
||||
@@ -144,6 +148,7 @@ class TotpAuthModule(MultiFactorAuthModule):
|
||||
if self._users.pop(user_id, None): # type: ignore[union-attr]
|
||||
await self._async_save()
|
||||
|
||||
@override
|
||||
async def async_is_user_setup(self, user_id: str) -> bool:
|
||||
"""Return whether user is setup."""
|
||||
if self._users is None:
|
||||
@@ -151,6 +156,7 @@ class TotpAuthModule(MultiFactorAuthModule):
|
||||
|
||||
return user_id in self._users # type: ignore[operator]
|
||||
|
||||
@override
|
||||
async def async_validate(self, user_id: str, user_input: dict[str, Any]) -> bool:
|
||||
"""Return True if validation passed."""
|
||||
if self._users is None:
|
||||
@@ -189,6 +195,7 @@ class TotpSetupFlow(SetupFlow[TotpAuthModule]):
|
||||
super().__init__(auth_module, setup_schema, user.id)
|
||||
self._user = user
|
||||
|
||||
@override
|
||||
async def async_step_init(
|
||||
self, user_input: dict[str, str] | None = None
|
||||
) -> FlowResult:
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
"""Permissions for Home Assistant."""
|
||||
|
||||
from collections.abc import Callable, Iterable
|
||||
from typing import TYPE_CHECKING
|
||||
from typing import TYPE_CHECKING, override
|
||||
|
||||
import voluptuous as vol
|
||||
|
||||
@@ -68,14 +68,17 @@ class PolicyPermissions(AbstractPermissions):
|
||||
self._policy = policy
|
||||
self._perm_lookup = perm_lookup
|
||||
|
||||
@override
|
||||
def access_all_entities(self, key: str) -> bool:
|
||||
"""Check if we have a certain access to all entities."""
|
||||
return test_all(self._policy.get(CAT_ENTITIES), key)
|
||||
|
||||
@override
|
||||
def _entity_func(self) -> Callable[[str, str], bool]:
|
||||
"""Return a function that can test entity access."""
|
||||
return compile_entities(self._policy.get(CAT_ENTITIES), self._perm_lookup)
|
||||
|
||||
@override
|
||||
def __eq__(self, other: object) -> bool:
|
||||
"""Equals check."""
|
||||
return isinstance(other, PolicyPermissions) and other._policy == self._policy
|
||||
@@ -84,10 +87,12 @@ class PolicyPermissions(AbstractPermissions):
|
||||
class _OwnerPermissions(AbstractPermissions):
|
||||
"""Owner permissions."""
|
||||
|
||||
@override
|
||||
def access_all_entities(self, key: str) -> bool:
|
||||
"""Check if we have a certain access to all entities."""
|
||||
return True
|
||||
|
||||
@override
|
||||
def _entity_func(self) -> Callable[[str, str], bool]:
|
||||
"""Return a function that can test entity access."""
|
||||
return lambda entity_id, key: True
|
||||
|
||||
@@ -4,7 +4,7 @@ import asyncio
|
||||
from collections.abc import Mapping
|
||||
import logging
|
||||
import os
|
||||
from typing import Any
|
||||
from typing import Any, override
|
||||
|
||||
import voluptuous as vol
|
||||
|
||||
@@ -57,6 +57,7 @@ class CommandLineAuthProvider(AuthProvider):
|
||||
super().__init__(*args, **kwargs)
|
||||
self._user_meta: dict[str, dict[str, Any]] = {}
|
||||
|
||||
@override
|
||||
async def async_login_flow(
|
||||
self, context: AuthFlowContext | None
|
||||
) -> CommandLineLoginFlow:
|
||||
@@ -105,6 +106,7 @@ class CommandLineAuthProvider(AuthProvider):
|
||||
meta[key] = value
|
||||
self._user_meta[username] = meta
|
||||
|
||||
@override
|
||||
async def async_get_or_create_credentials(
|
||||
self, flow_result: Mapping[str, str]
|
||||
) -> Credentials:
|
||||
@@ -117,6 +119,7 @@ class CommandLineAuthProvider(AuthProvider):
|
||||
# Create new credentials.
|
||||
return self.async_create_credentials({"username": username})
|
||||
|
||||
@override
|
||||
async def async_user_meta_for_credentials(
|
||||
self, credentials: Credentials
|
||||
) -> UserMeta:
|
||||
@@ -136,6 +139,7 @@ class CommandLineAuthProvider(AuthProvider):
|
||||
class CommandLineLoginFlow(LoginFlow[CommandLineAuthProvider]):
|
||||
"""Handler for the login flow."""
|
||||
|
||||
@override
|
||||
async def async_step_init(
|
||||
self, user_input: dict[str, str] | None = None
|
||||
) -> AuthFlowResult:
|
||||
|
||||
@@ -4,7 +4,7 @@ import asyncio
|
||||
import base64
|
||||
from collections.abc import Mapping
|
||||
import logging
|
||||
from typing import Any, cast
|
||||
from typing import Any, cast, override
|
||||
|
||||
import bcrypt
|
||||
import voluptuous as vol
|
||||
@@ -302,6 +302,7 @@ class HassAuthProvider(AuthProvider):
|
||||
self.data: Data | None = None
|
||||
self._init_lock = asyncio.Lock()
|
||||
|
||||
@override
|
||||
async def async_initialize(self) -> None:
|
||||
"""Initialize the auth provider."""
|
||||
async with self._init_lock:
|
||||
@@ -312,6 +313,7 @@ class HassAuthProvider(AuthProvider):
|
||||
await data.async_load()
|
||||
self.data = data
|
||||
|
||||
@override
|
||||
async def async_login_flow(self, context: AuthFlowContext | None) -> HassLoginFlow:
|
||||
"""Return a flow to login."""
|
||||
return HassLoginFlow(self)
|
||||
@@ -369,6 +371,7 @@ class HassAuthProvider(AuthProvider):
|
||||
)
|
||||
await self.data.async_save()
|
||||
|
||||
@override
|
||||
async def async_get_or_create_credentials(
|
||||
self, flow_result: Mapping[str, str]
|
||||
) -> Credentials:
|
||||
@@ -387,6 +390,7 @@ class HassAuthProvider(AuthProvider):
|
||||
# Create new credentials.
|
||||
return self.async_create_credentials({"username": username})
|
||||
|
||||
@override
|
||||
async def async_user_meta_for_credentials(
|
||||
self, credentials: Credentials
|
||||
) -> UserMeta:
|
||||
@@ -410,6 +414,7 @@ class HassAuthProvider(AuthProvider):
|
||||
class HassLoginFlow(LoginFlow[HassAuthProvider]):
|
||||
"""Handler for the login flow."""
|
||||
|
||||
@override
|
||||
async def async_step_init(
|
||||
self, user_input: dict[str, str] | None = None
|
||||
) -> AuthFlowResult:
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
from collections.abc import Mapping
|
||||
import hmac
|
||||
from typing import override
|
||||
|
||||
import voluptuous as vol
|
||||
|
||||
@@ -33,6 +34,7 @@ class InvalidAuthError(HomeAssistantError):
|
||||
class ExampleAuthProvider(AuthProvider):
|
||||
"""Example auth provider based on hardcoded usernames and passwords."""
|
||||
|
||||
@override
|
||||
async def async_login_flow(
|
||||
self, context: AuthFlowContext | None
|
||||
) -> ExampleLoginFlow:
|
||||
@@ -61,6 +63,7 @@ class ExampleAuthProvider(AuthProvider):
|
||||
):
|
||||
raise InvalidAuthError
|
||||
|
||||
@override
|
||||
async def async_get_or_create_credentials(
|
||||
self, flow_result: Mapping[str, str]
|
||||
) -> Credentials:
|
||||
@@ -74,6 +77,7 @@ class ExampleAuthProvider(AuthProvider):
|
||||
# Create new credentials.
|
||||
return self.async_create_credentials({"username": username})
|
||||
|
||||
@override
|
||||
async def async_user_meta_for_credentials(
|
||||
self, credentials: Credentials
|
||||
) -> UserMeta:
|
||||
@@ -95,6 +99,7 @@ class ExampleAuthProvider(AuthProvider):
|
||||
class ExampleLoginFlow(LoginFlow[ExampleAuthProvider]):
|
||||
"""Handler for the login flow."""
|
||||
|
||||
@override
|
||||
async def async_step_init(
|
||||
self, user_input: dict[str, str] | None = None
|
||||
) -> AuthFlowResult:
|
||||
|
||||
@@ -13,7 +13,7 @@ from ipaddress import (
|
||||
ip_address,
|
||||
ip_network,
|
||||
)
|
||||
from typing import Any, cast
|
||||
from typing import Any, cast, override
|
||||
|
||||
import voluptuous as vol
|
||||
|
||||
@@ -98,10 +98,12 @@ class TrustedNetworksAuthProvider(AuthProvider):
|
||||
]
|
||||
|
||||
@property
|
||||
@override
|
||||
def support_mfa(self) -> bool:
|
||||
"""Trusted Networks auth provider does not support MFA."""
|
||||
return False
|
||||
|
||||
@override
|
||||
async def async_login_flow(
|
||||
self, context: AuthFlowContext | None
|
||||
) -> TrustedNetworksLoginFlow:
|
||||
@@ -144,6 +146,7 @@ class TrustedNetworksAuthProvider(AuthProvider):
|
||||
self.config[CONF_ALLOW_BYPASS_LOGIN],
|
||||
)
|
||||
|
||||
@override
|
||||
async def async_get_or_create_credentials(
|
||||
self, flow_result: Mapping[str, str]
|
||||
) -> Credentials:
|
||||
@@ -172,6 +175,7 @@ class TrustedNetworksAuthProvider(AuthProvider):
|
||||
# We only allow login as exist user
|
||||
raise InvalidUserError
|
||||
|
||||
@override
|
||||
async def async_user_meta_for_credentials(
|
||||
self, credentials: Credentials
|
||||
) -> UserMeta:
|
||||
@@ -203,6 +207,7 @@ class TrustedNetworksAuthProvider(AuthProvider):
|
||||
raise InvalidAuthError("Can't allow access from Home Assistant Cloud")
|
||||
|
||||
@callback
|
||||
@override
|
||||
def async_validate_refresh_token(
|
||||
self, refresh_token: RefreshToken, remote_ip: str | None = None
|
||||
) -> None:
|
||||
@@ -230,6 +235,7 @@ class TrustedNetworksLoginFlow(LoginFlow[TrustedNetworksAuthProvider]):
|
||||
self._ip_address = ip_addr
|
||||
self._allow_bypass_login = allow_bypass_login
|
||||
|
||||
@override
|
||||
async def async_step_init(
|
||||
self, user_input: dict[str, str] | None = None
|
||||
) -> AuthFlowResult:
|
||||
|
||||
@@ -14,7 +14,7 @@ import platform
|
||||
import sys
|
||||
import threading
|
||||
from time import monotonic
|
||||
from typing import TYPE_CHECKING, Any
|
||||
from typing import TYPE_CHECKING, Any, override
|
||||
|
||||
# Import cryptography early since import openssl is not thread-safe
|
||||
# _frozen_importlib._DeadlockError: deadlock detected by
|
||||
@@ -697,6 +697,7 @@ def _create_log_file(
|
||||
class _RotatingFileHandlerWithoutShouldRollOver(RotatingFileHandler):
|
||||
"""RotatingFileHandler that does not check if it should roll over on every log."""
|
||||
|
||||
@override
|
||||
def shouldRollover(self, record: logging.LogRecord) -> bool:
|
||||
"""Never roll over.
|
||||
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
"unifi_access",
|
||||
"unifi_direct",
|
||||
"unifi_discovery",
|
||||
"unifiled",
|
||||
"unifiprotect"
|
||||
]
|
||||
}
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
"""Support for Abode Security System alarm control panels."""
|
||||
|
||||
from typing import override
|
||||
|
||||
from jaraco.abode.devices.alarm import Alarm
|
||||
|
||||
from homeassistant.components.alarm_control_panel import (
|
||||
@@ -38,6 +40,7 @@ class AbodeAlarm(AbodeDevice, AlarmControlPanelEntity):
|
||||
_device: Alarm
|
||||
|
||||
@property
|
||||
@override
|
||||
def alarm_state(self) -> AlarmControlPanelState | None:
|
||||
"""Return the state of the device."""
|
||||
if self._device.is_standby:
|
||||
@@ -48,19 +51,23 @@ class AbodeAlarm(AbodeDevice, AlarmControlPanelEntity):
|
||||
return AlarmControlPanelState.ARMED_HOME
|
||||
return None
|
||||
|
||||
@override
|
||||
def alarm_disarm(self, code: str | None = None) -> None:
|
||||
"""Send disarm command."""
|
||||
self._device.set_standby()
|
||||
|
||||
@override
|
||||
def alarm_arm_home(self, code: str | None = None) -> None:
|
||||
"""Send arm home command."""
|
||||
self._device.set_home()
|
||||
|
||||
@override
|
||||
def alarm_arm_away(self, code: str | None = None) -> None:
|
||||
"""Send arm away command."""
|
||||
self._device.set_away()
|
||||
|
||||
@property
|
||||
@override
|
||||
def extra_state_attributes(self) -> dict[str, str]:
|
||||
"""Return the state attributes."""
|
||||
return {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
"""Support for Abode Security System binary sensors."""
|
||||
|
||||
from typing import cast
|
||||
from typing import cast, override
|
||||
|
||||
from jaraco.abode.devices.binary_sensor import BinarySensor
|
||||
|
||||
@@ -45,11 +45,13 @@ class AbodeBinarySensor(AbodeDevice, BinarySensorEntity):
|
||||
_device: BinarySensor
|
||||
|
||||
@property
|
||||
@override
|
||||
def is_on(self) -> bool:
|
||||
"""Return True if the binary sensor is on."""
|
||||
return cast(bool, self._device.is_on)
|
||||
|
||||
@property
|
||||
@override
|
||||
def device_class(self) -> BinarySensorDeviceClass | None:
|
||||
"""Return the class of the binary sensor."""
|
||||
if self._device.get_value("is_window") == "1":
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
"""Support for Abode Security System cameras."""
|
||||
|
||||
from datetime import timedelta
|
||||
from typing import Any, cast
|
||||
from typing import Any, cast, override
|
||||
|
||||
from jaraco.abode.devices.base import Device
|
||||
from jaraco.abode.devices.camera import Camera as AbodeCam
|
||||
@@ -49,6 +49,7 @@ class AbodeCamera(AbodeDevice, Camera):
|
||||
self._event = event
|
||||
self._response: Response | None = None
|
||||
|
||||
@override
|
||||
async def async_added_to_hass(self) -> None:
|
||||
"""Subscribe Abode events."""
|
||||
await super().async_added_to_hass()
|
||||
@@ -87,6 +88,7 @@ class AbodeCamera(AbodeDevice, Camera):
|
||||
else:
|
||||
self._response = None
|
||||
|
||||
@override
|
||||
def camera_image(
|
||||
self, width: int | None = None, height: int | None = None
|
||||
) -> bytes | None:
|
||||
@@ -98,10 +100,12 @@ class AbodeCamera(AbodeDevice, Camera):
|
||||
|
||||
return None
|
||||
|
||||
@override
|
||||
def turn_on(self) -> None:
|
||||
"""Turn on camera."""
|
||||
self._device.privacy_mode(False)
|
||||
|
||||
@override
|
||||
def turn_off(self) -> None:
|
||||
"""Turn off camera."""
|
||||
self._device.privacy_mode(True)
|
||||
@@ -113,6 +117,7 @@ class AbodeCamera(AbodeDevice, Camera):
|
||||
self.schedule_update_ha_state()
|
||||
|
||||
@property
|
||||
@override
|
||||
def is_on(self) -> bool:
|
||||
"""Return true if on."""
|
||||
return cast(bool, self._device.is_on)
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
from collections.abc import Mapping
|
||||
from http import HTTPStatus
|
||||
from typing import Any, cast
|
||||
from typing import Any, cast, override
|
||||
|
||||
from jaraco.abode.client import Client as Abode
|
||||
from jaraco.abode.exceptions import (
|
||||
@@ -106,6 +106,7 @@ class AbodeFlowHandler(ConfigFlow, domain=DOMAIN):
|
||||
title=cast(str, self._username), data=config_data
|
||||
)
|
||||
|
||||
@override
|
||||
async def async_step_user(
|
||||
self, user_input: dict[str, Any] | None = None
|
||||
) -> ConfigFlowResult:
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
"""Support for Abode Security System covers."""
|
||||
|
||||
from typing import Any
|
||||
from typing import Any, override
|
||||
|
||||
from jaraco.abode.devices.cover import Cover
|
||||
|
||||
@@ -33,14 +33,17 @@ class AbodeCover(AbodeDevice, CoverEntity):
|
||||
_attr_name = None
|
||||
|
||||
@property
|
||||
@override
|
||||
def is_closed(self) -> bool:
|
||||
"""Return true if cover is closed, else False."""
|
||||
return not self._device.is_open
|
||||
|
||||
@override
|
||||
def close_cover(self, **kwargs: Any) -> None:
|
||||
"""Issue close command to cover."""
|
||||
self._device.close_cover()
|
||||
|
||||
@override
|
||||
def open_cover(self, **kwargs: Any) -> None:
|
||||
"""Issue open command to cover."""
|
||||
self._device.open_cover()
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
"""Support for Abode Security System entities."""
|
||||
|
||||
from typing import override
|
||||
|
||||
from jaraco.abode.automation import Automation as AbodeAuto
|
||||
from jaraco.abode.devices.base import Device as AbodeDev
|
||||
|
||||
@@ -21,6 +23,7 @@ class AbodeEntity(Entity):
|
||||
self._data = data
|
||||
self._attr_should_poll = data.polling
|
||||
|
||||
@override
|
||||
async def async_added_to_hass(self) -> None:
|
||||
"""Subscribe to Abode connection status updates."""
|
||||
await self.hass.async_add_executor_job(
|
||||
@@ -31,6 +34,7 @@ class AbodeEntity(Entity):
|
||||
|
||||
self._data.entity_ids.add(self.entity_id)
|
||||
|
||||
@override
|
||||
async def async_will_remove_from_hass(self) -> None:
|
||||
"""Unsubscribe from Abode connection status updates."""
|
||||
await self.hass.async_add_executor_job(
|
||||
@@ -52,6 +56,7 @@ class AbodeDevice(AbodeEntity):
|
||||
self._device = device
|
||||
self._attr_unique_id = device.uuid
|
||||
|
||||
@override
|
||||
async def async_added_to_hass(self) -> None:
|
||||
"""Subscribe to device events."""
|
||||
await super().async_added_to_hass()
|
||||
@@ -61,6 +66,7 @@ class AbodeDevice(AbodeEntity):
|
||||
self._update_callback,
|
||||
)
|
||||
|
||||
@override
|
||||
async def async_will_remove_from_hass(self) -> None:
|
||||
"""Unsubscribe from device events."""
|
||||
await super().async_will_remove_from_hass()
|
||||
@@ -73,6 +79,7 @@ class AbodeDevice(AbodeEntity):
|
||||
self._device.refresh()
|
||||
|
||||
@property
|
||||
@override
|
||||
def extra_state_attributes(self) -> dict[str, str]:
|
||||
"""Return the state attributes."""
|
||||
return {
|
||||
@@ -83,6 +90,7 @@ class AbodeDevice(AbodeEntity):
|
||||
}
|
||||
|
||||
@property
|
||||
@override
|
||||
def device_info(self) -> DeviceInfo:
|
||||
"""Return device registry information for this entity."""
|
||||
return DeviceInfo(
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
"""Support for Abode Security System lights."""
|
||||
|
||||
from math import ceil
|
||||
from typing import Any
|
||||
from typing import Any, override
|
||||
|
||||
from jaraco.abode.devices.light import Light
|
||||
|
||||
@@ -43,6 +43,7 @@ class AbodeLight(AbodeDevice, LightEntity):
|
||||
_attr_max_color_temp_kelvin = DEFAULT_MAX_KELVIN
|
||||
_attr_min_color_temp_kelvin = DEFAULT_MIN_KELVIN
|
||||
|
||||
@override
|
||||
def turn_on(self, **kwargs: Any) -> None:
|
||||
"""Turn on the light."""
|
||||
if ATTR_COLOR_TEMP_KELVIN in kwargs and self._device.is_color_capable:
|
||||
@@ -61,16 +62,19 @@ class AbodeLight(AbodeDevice, LightEntity):
|
||||
|
||||
self._device.switch_on()
|
||||
|
||||
@override
|
||||
def turn_off(self, **kwargs: Any) -> None:
|
||||
"""Turn off the light."""
|
||||
self._device.switch_off()
|
||||
|
||||
@property
|
||||
@override
|
||||
def is_on(self) -> bool:
|
||||
"""Return true if device is on."""
|
||||
return bool(self._device.is_on)
|
||||
|
||||
@property
|
||||
@override
|
||||
def brightness(self) -> int | None:
|
||||
"""Return the brightness of the light."""
|
||||
if self._device.is_dimmable and self._device.has_brightness:
|
||||
@@ -81,6 +85,7 @@ class AbodeLight(AbodeDevice, LightEntity):
|
||||
return None
|
||||
|
||||
@property
|
||||
@override
|
||||
def color_temp_kelvin(self) -> int | None:
|
||||
"""Return the color temp of the light."""
|
||||
if self._device.has_color:
|
||||
@@ -88,6 +93,7 @@ class AbodeLight(AbodeDevice, LightEntity):
|
||||
return None
|
||||
|
||||
@property
|
||||
@override
|
||||
def hs_color(self) -> tuple[float, float] | None:
|
||||
"""Return the color of the light."""
|
||||
_hs = None
|
||||
@@ -96,6 +102,7 @@ class AbodeLight(AbodeDevice, LightEntity):
|
||||
return _hs
|
||||
|
||||
@property
|
||||
@override
|
||||
def color_mode(self) -> ColorMode:
|
||||
"""Return the color mode of the light."""
|
||||
if self._device.is_dimmable and self._device.is_color_capable:
|
||||
@@ -107,6 +114,7 @@ class AbodeLight(AbodeDevice, LightEntity):
|
||||
return ColorMode.ONOFF
|
||||
|
||||
@property
|
||||
@override
|
||||
def supported_color_modes(self) -> set[ColorMode]:
|
||||
"""Flag supported color modes."""
|
||||
if self._device.is_dimmable and self._device.is_color_capable:
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
"""Support for the Abode Security System locks."""
|
||||
|
||||
from typing import Any
|
||||
from typing import Any, override
|
||||
|
||||
from jaraco.abode.devices.lock import Lock
|
||||
|
||||
@@ -32,15 +32,18 @@ class AbodeLock(AbodeDevice, LockEntity):
|
||||
_device: Lock
|
||||
_attr_name = None
|
||||
|
||||
@override
|
||||
def lock(self, **kwargs: Any) -> None:
|
||||
"""Lock the device."""
|
||||
self._device.lock()
|
||||
|
||||
@override
|
||||
def unlock(self, **kwargs: Any) -> None:
|
||||
"""Unlock the device."""
|
||||
self._device.unlock()
|
||||
|
||||
@property
|
||||
@override
|
||||
def is_locked(self) -> bool:
|
||||
"""Return true if device is on."""
|
||||
return bool(self._device.is_locked)
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
from collections.abc import Callable
|
||||
from dataclasses import dataclass
|
||||
from typing import cast
|
||||
from typing import cast, override
|
||||
|
||||
from jaraco.abode.devices.sensor import Sensor
|
||||
|
||||
@@ -94,11 +94,13 @@ class AbodeSensor(AbodeDevice, SensorEntity):
|
||||
self._attr_unique_id = f"{device.uuid}-{description.key}"
|
||||
|
||||
@property
|
||||
@override
|
||||
def native_value(self) -> float:
|
||||
"""Return the state of the sensor."""
|
||||
return self.entity_description.value_fn(self._device)
|
||||
|
||||
@property
|
||||
@override
|
||||
def native_unit_of_measurement(self) -> str:
|
||||
"""Return the native unit of measurement."""
|
||||
return self.entity_description.native_unit_of_measurement_fn(self._device)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
"""Support for Abode Security System switches."""
|
||||
|
||||
from typing import Any, cast
|
||||
from typing import Any, cast, override
|
||||
|
||||
from jaraco.abode.devices.switch import Switch
|
||||
|
||||
@@ -43,15 +43,18 @@ class AbodeSwitch(AbodeDevice, SwitchEntity):
|
||||
_device: Switch
|
||||
_attr_name = None
|
||||
|
||||
@override
|
||||
def turn_on(self, **kwargs: Any) -> None:
|
||||
"""Turn on the device."""
|
||||
self._device.switch_on()
|
||||
|
||||
@override
|
||||
def turn_off(self, **kwargs: Any) -> None:
|
||||
"""Turn off the device."""
|
||||
self._device.switch_off()
|
||||
|
||||
@property
|
||||
@override
|
||||
def is_on(self) -> bool:
|
||||
"""Return true if device is on."""
|
||||
return cast(bool, self._device.is_on)
|
||||
@@ -62,6 +65,7 @@ class AbodeAutomationSwitch(AbodeAutomation, SwitchEntity):
|
||||
|
||||
_attr_translation_key = "automation"
|
||||
|
||||
@override
|
||||
async def async_added_to_hass(self) -> None:
|
||||
"""Set up trigger automation service."""
|
||||
await super().async_added_to_hass()
|
||||
@@ -69,11 +73,13 @@ class AbodeAutomationSwitch(AbodeAutomation, SwitchEntity):
|
||||
signal = f"abode_trigger_automation_{self.entity_id}"
|
||||
self.async_on_remove(async_dispatcher_connect(self.hass, signal, self.trigger))
|
||||
|
||||
@override
|
||||
def turn_on(self, **kwargs: Any) -> None:
|
||||
"""Enable the automation."""
|
||||
if self._automation.enable(True):
|
||||
self.schedule_update_ha_state()
|
||||
|
||||
@override
|
||||
def turn_off(self, **kwargs: Any) -> None:
|
||||
"""Disable the automation."""
|
||||
if self._automation.enable(False):
|
||||
@@ -84,6 +90,7 @@ class AbodeAutomationSwitch(AbodeAutomation, SwitchEntity):
|
||||
self._automation.trigger()
|
||||
|
||||
@property
|
||||
@override
|
||||
def is_on(self) -> bool:
|
||||
"""Return True if the automation is enabled."""
|
||||
return bool(self._automation.enabled)
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
from collections.abc import Callable
|
||||
from dataclasses import dataclass
|
||||
from typing import override
|
||||
|
||||
from aioacaia.acaiascale import AcaiaScale
|
||||
|
||||
@@ -56,6 +57,7 @@ class AcaiaBinarySensor(AcaiaEntity, BinarySensorEntity):
|
||||
entity_description: AcaiaBinarySensorEntityDescription
|
||||
|
||||
@property
|
||||
@override
|
||||
def is_on(self) -> bool:
|
||||
"""Return true if the binary sensor is on."""
|
||||
return self.entity_description.is_on_fn(self._scale)
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
from collections.abc import Callable, Coroutine
|
||||
from dataclasses import dataclass
|
||||
from typing import Any
|
||||
from typing import Any, override
|
||||
|
||||
from aioacaia.acaiascale import AcaiaScale
|
||||
|
||||
@@ -58,6 +58,7 @@ class AcaiaButton(AcaiaEntity, ButtonEntity):
|
||||
|
||||
entity_description: AcaiaButtonEntityDescription
|
||||
|
||||
@override
|
||||
async def async_press(self) -> None:
|
||||
"""Handle the button press."""
|
||||
await self.entity_description.press_fn(self._scale)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
"""Config flow for Acaia integration."""
|
||||
|
||||
import logging
|
||||
from typing import Any
|
||||
from typing import Any, override
|
||||
|
||||
from aioacaia.exceptions import AcaiaDeviceNotFound, AcaiaError, AcaiaUnknownDevice
|
||||
from aioacaia.helpers import is_new_scale
|
||||
@@ -34,6 +34,7 @@ class AcaiaConfigFlow(ConfigFlow, domain=DOMAIN):
|
||||
self._discovered: dict[str, Any] = {}
|
||||
self._discovered_devices: dict[str, str] = {}
|
||||
|
||||
@override
|
||||
async def async_step_user(
|
||||
self, user_input: dict[str, Any] | None = None
|
||||
) -> ConfigFlowResult:
|
||||
@@ -94,6 +95,7 @@ class AcaiaConfigFlow(ConfigFlow, domain=DOMAIN):
|
||||
errors=errors,
|
||||
)
|
||||
|
||||
@override
|
||||
async def async_step_bluetooth(
|
||||
self, discovery_info: BluetoothServiceInfoBleak
|
||||
) -> ConfigFlowResult:
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
from datetime import timedelta
|
||||
import logging
|
||||
from typing import override
|
||||
|
||||
from aioacaia.acaiascale import AcaiaScale
|
||||
from aioacaia.exceptions import AcaiaDeviceNotFound, AcaiaError
|
||||
@@ -59,6 +60,7 @@ class AcaiaCoordinator(DataUpdateCoordinator[None]):
|
||||
"""Return the scale object."""
|
||||
return self._scale
|
||||
|
||||
@override
|
||||
async def _async_update_data(self) -> None:
|
||||
"""Fetch data."""
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
"""Base class for Acaia entities."""
|
||||
|
||||
from dataclasses import dataclass
|
||||
from typing import override
|
||||
|
||||
from homeassistant.helpers.device_registry import (
|
||||
CONNECTION_BLUETOOTH,
|
||||
@@ -41,6 +42,7 @@ class AcaiaEntity(CoordinatorEntity[AcaiaCoordinator]):
|
||||
)
|
||||
|
||||
@property
|
||||
@override
|
||||
def available(self) -> bool:
|
||||
"""Returns whether entity is available."""
|
||||
return super().available and self._scale.connected
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
from collections.abc import Callable
|
||||
from dataclasses import dataclass
|
||||
from typing import override
|
||||
|
||||
from aioacaia.acaiascale import AcaiaDeviceState, AcaiaScale
|
||||
from aioacaia.const import UnitMass as AcaiaUnitOfMass
|
||||
@@ -98,6 +99,7 @@ class AcaiaSensor(AcaiaEntity, SensorEntity):
|
||||
entity_description: AcaiaDynamicUnitSensorEntityDescription
|
||||
|
||||
@property
|
||||
@override
|
||||
def native_unit_of_measurement(self) -> str | None:
|
||||
"""Return the unit of measurement of this entity."""
|
||||
if (
|
||||
@@ -108,6 +110,7 @@ class AcaiaSensor(AcaiaEntity, SensorEntity):
|
||||
return self.entity_description.native_unit_of_measurement
|
||||
|
||||
@property
|
||||
@override
|
||||
def native_value(self) -> int | float | None:
|
||||
"""Return the state of the entity."""
|
||||
return self.entity_description.value_fn(self._scale)
|
||||
@@ -119,6 +122,7 @@ class AcaiaRestoreSensor(AcaiaEntity, RestoreSensor):
|
||||
entity_description: AcaiaSensorEntityDescription
|
||||
_restored_data: SensorExtraStoredData | None = None
|
||||
|
||||
@override
|
||||
async def async_added_to_hass(self) -> None:
|
||||
"""Handle entity which will be added."""
|
||||
await super().async_added_to_hass()
|
||||
@@ -134,6 +138,7 @@ class AcaiaRestoreSensor(AcaiaEntity, RestoreSensor):
|
||||
self._attr_native_value = self.entity_description.value_fn(self._scale)
|
||||
|
||||
@callback
|
||||
@override
|
||||
def _handle_coordinator_update(self) -> None:
|
||||
"""Handle updated data from the coordinator."""
|
||||
if self._scale.device_state is not None:
|
||||
@@ -141,6 +146,7 @@ class AcaiaRestoreSensor(AcaiaEntity, RestoreSensor):
|
||||
self._async_write_ha_state()
|
||||
|
||||
@property
|
||||
@override
|
||||
def available(self) -> bool:
|
||||
"""Return True if entity is available."""
|
||||
return super().available or self.native_value is not None
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
from asyncio import timeout
|
||||
from collections.abc import Mapping
|
||||
from typing import TYPE_CHECKING, Any
|
||||
from typing import TYPE_CHECKING, Any, override
|
||||
|
||||
from accuweather import AccuWeather, ApiError, InvalidApiKeyError, RequestsExceededError
|
||||
from aiohttp import ClientError
|
||||
@@ -24,6 +24,7 @@ class AccuWeatherFlowHandler(ConfigFlow, domain=DOMAIN):
|
||||
_latitude: float | None = None
|
||||
_longitude: float | None = None
|
||||
|
||||
@override
|
||||
async def async_step_user(
|
||||
self, user_input: dict[str, Any] | None = None
|
||||
) -> ConfigFlowResult:
|
||||
|
||||
@@ -5,7 +5,7 @@ from collections.abc import Awaitable, Callable
|
||||
from dataclasses import dataclass
|
||||
from datetime import timedelta
|
||||
import logging
|
||||
from typing import TYPE_CHECKING, Any
|
||||
from typing import TYPE_CHECKING, Any, override
|
||||
|
||||
from accuweather import AccuWeather, ApiError, InvalidApiKeyError, RequestsExceededError
|
||||
from aiohttp.client_exceptions import ClientConnectorError
|
||||
@@ -77,6 +77,7 @@ class AccuWeatherObservationDataUpdateCoordinator(
|
||||
update_interval=UPDATE_INTERVAL_OBSERVATION,
|
||||
)
|
||||
|
||||
@override
|
||||
async def _async_update_data(self) -> dict[str, Any]:
|
||||
"""Update data via library."""
|
||||
try:
|
||||
@@ -135,6 +136,7 @@ class AccuWeatherForecastDataUpdateCoordinator(
|
||||
update_interval=update_interval,
|
||||
)
|
||||
|
||||
@override
|
||||
async def _async_update_data(self) -> list[dict[str, Any]]:
|
||||
"""Update forecast data via library."""
|
||||
try:
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
from collections.abc import Callable
|
||||
from dataclasses import dataclass
|
||||
from typing import Any, cast
|
||||
from typing import Any, cast, override
|
||||
|
||||
from homeassistant.components.sensor import (
|
||||
SensorDeviceClass,
|
||||
@@ -436,16 +436,19 @@ class AccuWeatherSensor(
|
||||
self._attr_device_info = coordinator.device_info
|
||||
|
||||
@property
|
||||
@override
|
||||
def native_value(self) -> str | int | float | None:
|
||||
"""Return the state."""
|
||||
return self.entity_description.value_fn(self._sensor_data)
|
||||
|
||||
@property
|
||||
@override
|
||||
def extra_state_attributes(self) -> dict[str, Any]:
|
||||
"""Return the state attributes."""
|
||||
return self.entity_description.attr_fn(self.coordinator.data)
|
||||
|
||||
@callback
|
||||
@override
|
||||
def _handle_coordinator_update(self) -> None:
|
||||
"""Handle data update."""
|
||||
self._sensor_data = self._get_sensor_data(
|
||||
@@ -495,16 +498,19 @@ class AccuWeatherForecastSensor(
|
||||
self.forecast_day = forecast_day
|
||||
|
||||
@property
|
||||
@override
|
||||
def native_value(self) -> str | int | float | None:
|
||||
"""Return the state."""
|
||||
return self.entity_description.value_fn(self._sensor_data)
|
||||
|
||||
@property
|
||||
@override
|
||||
def extra_state_attributes(self) -> dict[str, Any]:
|
||||
"""Return the state attributes."""
|
||||
return self.entity_description.attr_fn(self._sensor_data)
|
||||
|
||||
@callback
|
||||
@override
|
||||
def _handle_coordinator_update(self) -> None:
|
||||
"""Handle data update."""
|
||||
self._sensor_data = self._get_sensor_data(
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
"""Support for the AccuWeather service."""
|
||||
|
||||
from typing import cast
|
||||
from typing import cast, override
|
||||
|
||||
from homeassistant.components.weather import (
|
||||
ATTR_FORECAST_CLOUD_COVERAGE,
|
||||
@@ -96,16 +96,19 @@ class AccuWeatherEntity(
|
||||
self.hourly_coordinator = accuweather_data.coordinator_hourly_forecast
|
||||
|
||||
@property
|
||||
@override
|
||||
def condition(self) -> str | None:
|
||||
"""Return the current condition."""
|
||||
return CONDITION_MAP.get(self.observation_coordinator.data["WeatherIcon"])
|
||||
|
||||
@property
|
||||
@override
|
||||
def cloud_coverage(self) -> float:
|
||||
"""Return the Cloud coverage in %."""
|
||||
return cast(float, self.observation_coordinator.data["CloudCover"])
|
||||
|
||||
@property
|
||||
@override
|
||||
def native_apparent_temperature(self) -> float:
|
||||
"""Return the apparent temperature."""
|
||||
return cast(
|
||||
@@ -116,6 +119,7 @@ class AccuWeatherEntity(
|
||||
)
|
||||
|
||||
@property
|
||||
@override
|
||||
def native_temperature(self) -> float:
|
||||
"""Return the temperature."""
|
||||
return cast(
|
||||
@@ -124,6 +128,7 @@ class AccuWeatherEntity(
|
||||
)
|
||||
|
||||
@property
|
||||
@override
|
||||
def native_pressure(self) -> float:
|
||||
"""Return the pressure."""
|
||||
return cast(
|
||||
@@ -131,6 +136,7 @@ class AccuWeatherEntity(
|
||||
)
|
||||
|
||||
@property
|
||||
@override
|
||||
def native_dew_point(self) -> float:
|
||||
"""Return the dew point."""
|
||||
return cast(
|
||||
@@ -138,11 +144,13 @@ class AccuWeatherEntity(
|
||||
)
|
||||
|
||||
@property
|
||||
@override
|
||||
def humidity(self) -> int:
|
||||
"""Return the humidity."""
|
||||
return cast(int, self.observation_coordinator.data["RelativeHumidity"])
|
||||
|
||||
@property
|
||||
@override
|
||||
def native_wind_gust_speed(self) -> float:
|
||||
"""Return the wind gust speed."""
|
||||
return cast(
|
||||
@@ -153,6 +161,7 @@ class AccuWeatherEntity(
|
||||
)
|
||||
|
||||
@property
|
||||
@override
|
||||
def native_wind_speed(self) -> float:
|
||||
"""Return the wind speed."""
|
||||
return cast(
|
||||
@@ -163,6 +172,7 @@ class AccuWeatherEntity(
|
||||
)
|
||||
|
||||
@property
|
||||
@override
|
||||
def wind_bearing(self) -> int:
|
||||
"""Return the wind bearing."""
|
||||
return cast(
|
||||
@@ -170,6 +180,7 @@ class AccuWeatherEntity(
|
||||
)
|
||||
|
||||
@property
|
||||
@override
|
||||
def native_visibility(self) -> float:
|
||||
"""Return the visibility."""
|
||||
return cast(
|
||||
@@ -178,11 +189,13 @@ class AccuWeatherEntity(
|
||||
)
|
||||
|
||||
@property
|
||||
@override
|
||||
def uv_index(self) -> float:
|
||||
"""Return the UV index."""
|
||||
return cast(float, self.observation_coordinator.data["UVIndex"])
|
||||
|
||||
@callback
|
||||
@override
|
||||
def _async_forecast_daily(self) -> list[Forecast] | None:
|
||||
"""Return the daily forecast in native units."""
|
||||
return [
|
||||
@@ -213,6 +226,7 @@ class AccuWeatherEntity(
|
||||
]
|
||||
|
||||
@callback
|
||||
@override
|
||||
def _async_forecast_hourly(self) -> list[Forecast] | None:
|
||||
"""Return the hourly forecast in native units."""
|
||||
return [
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
import logging
|
||||
import re
|
||||
from typing import Any
|
||||
from typing import Any, override
|
||||
|
||||
from serialx import Serial, SerialException
|
||||
import voluptuous as vol
|
||||
@@ -140,12 +140,14 @@ class AcerSwitch(SwitchEntity):
|
||||
self._attributes[key] = awns
|
||||
self._attr_extra_state_attributes = self._attributes
|
||||
|
||||
@override
|
||||
def turn_on(self, **kwargs: Any) -> None:
|
||||
"""Turn the projector on."""
|
||||
msg = CMD_DICT[STATE_ON]
|
||||
self._write_read(msg)
|
||||
self._attr_is_on = True
|
||||
|
||||
@override
|
||||
def turn_off(self, **kwargs: Any) -> None:
|
||||
"""Turn the projector off."""
|
||||
msg = CMD_DICT[STATE_OFF]
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
from asyncio import timeout
|
||||
from contextlib import suppress
|
||||
from typing import Any
|
||||
from typing import Any, override
|
||||
|
||||
import aiopulse
|
||||
import voluptuous as vol
|
||||
@@ -22,6 +22,7 @@ class AcmedaFlowHandler(ConfigFlow, domain=DOMAIN):
|
||||
"""Initialize the config flow."""
|
||||
self.discovered_hubs: dict[str, aiopulse.Hub] | None = None
|
||||
|
||||
@override
|
||||
async def async_step_user(
|
||||
self, user_input: dict[str, Any] | None = None
|
||||
) -> ConfigFlowResult:
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
"""Support for Acmeda Roller Blinds."""
|
||||
|
||||
from typing import Any
|
||||
from typing import Any, override
|
||||
|
||||
from homeassistant.components.cover import (
|
||||
ATTR_POSITION,
|
||||
@@ -48,6 +48,7 @@ class AcmedaCover(AcmedaEntity, CoverEntity):
|
||||
_attr_name = None
|
||||
|
||||
@property
|
||||
@override
|
||||
def current_cover_position(self) -> int | None:
|
||||
"""Return the current position of the roller blind.
|
||||
|
||||
@@ -59,6 +60,7 @@ class AcmedaCover(AcmedaEntity, CoverEntity):
|
||||
return position
|
||||
|
||||
@property
|
||||
@override
|
||||
def current_cover_tilt_position(self) -> int | None:
|
||||
"""Return the current tilt of the roller blind.
|
||||
|
||||
@@ -70,6 +72,7 @@ class AcmedaCover(AcmedaEntity, CoverEntity):
|
||||
return position
|
||||
|
||||
@property
|
||||
@override
|
||||
def supported_features(self) -> CoverEntityFeature:
|
||||
"""Flag supported features."""
|
||||
supported_features = CoverEntityFeature(0)
|
||||
@@ -91,38 +94,47 @@ class AcmedaCover(AcmedaEntity, CoverEntity):
|
||||
return supported_features
|
||||
|
||||
@property
|
||||
@override
|
||||
def is_closed(self) -> bool:
|
||||
"""Return if the cover is closed."""
|
||||
return self.roller.closed_percent == 100 # type: ignore[no-any-return]
|
||||
|
||||
@override
|
||||
async def async_close_cover(self, **kwargs: Any) -> None:
|
||||
"""Close the roller."""
|
||||
await self.roller.move_down()
|
||||
|
||||
@override
|
||||
async def async_open_cover(self, **kwargs: Any) -> None:
|
||||
"""Open the roller."""
|
||||
await self.roller.move_up()
|
||||
|
||||
@override
|
||||
async def async_stop_cover(self, **kwargs: Any) -> None:
|
||||
"""Stop the roller."""
|
||||
await self.roller.move_stop()
|
||||
|
||||
@override
|
||||
async def async_set_cover_position(self, **kwargs: Any) -> None:
|
||||
"""Move the roller shutter to a specific position."""
|
||||
await self.roller.move_to(100 - kwargs[ATTR_POSITION])
|
||||
|
||||
@override
|
||||
async def async_close_cover_tilt(self, **kwargs: Any) -> None:
|
||||
"""Close the roller."""
|
||||
await self.roller.move_down()
|
||||
|
||||
@override
|
||||
async def async_open_cover_tilt(self, **kwargs: Any) -> None:
|
||||
"""Open the roller."""
|
||||
await self.roller.move_up()
|
||||
|
||||
@override
|
||||
async def async_stop_cover_tilt(self, **kwargs: Any) -> None:
|
||||
"""Stop the roller."""
|
||||
await self.roller.move_stop()
|
||||
|
||||
@override
|
||||
async def async_set_cover_tilt_position(self, **kwargs: Any) -> None:
|
||||
"""Tilt the roller shutter to a specific position."""
|
||||
await self.roller.move_to(100 - kwargs[ATTR_POSITION])
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
"""Base class for Acmeda Roller Blinds."""
|
||||
|
||||
from typing import override
|
||||
|
||||
import aiopulse
|
||||
|
||||
from homeassistant.core import callback
|
||||
@@ -40,6 +42,7 @@ class AcmedaEntity(entity.Entity):
|
||||
|
||||
await self.async_remove(force_remove=True)
|
||||
|
||||
@override
|
||||
async def async_added_to_hass(self) -> None:
|
||||
"""Entity has been added to hass."""
|
||||
self.roller.callback_subscribe(self.notify_update)
|
||||
@@ -52,6 +55,7 @@ class AcmedaEntity(entity.Entity):
|
||||
)
|
||||
)
|
||||
|
||||
@override
|
||||
async def async_will_remove_from_hass(self) -> None:
|
||||
"""Entity being removed from hass."""
|
||||
self.roller.callback_unsubscribe(self.notify_update)
|
||||
@@ -63,6 +67,7 @@ class AcmedaEntity(entity.Entity):
|
||||
self.async_write_ha_state()
|
||||
|
||||
@property
|
||||
@override
|
||||
def unique_id(self) -> str:
|
||||
"""Return the unique ID of this roller."""
|
||||
return str(self.roller.id)
|
||||
@@ -73,6 +78,7 @@ class AcmedaEntity(entity.Entity):
|
||||
return self.roller.id # type: ignore[no-any-return]
|
||||
|
||||
@property
|
||||
@override
|
||||
def device_info(self) -> dr.DeviceInfo:
|
||||
"""Return the device info."""
|
||||
return dr.DeviceInfo(
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
"""Support for Acmeda Roller Blind Batteries."""
|
||||
|
||||
from typing import override
|
||||
|
||||
from homeassistant.components.sensor import SensorDeviceClass, SensorEntity
|
||||
from homeassistant.const import PERCENTAGE
|
||||
from homeassistant.core import HomeAssistant, callback
|
||||
@@ -44,6 +46,7 @@ class AcmedaBattery(AcmedaEntity, SensorEntity):
|
||||
_attr_native_unit_of_measurement = PERCENTAGE
|
||||
|
||||
@property
|
||||
@override
|
||||
def native_value(self) -> float | int | None:
|
||||
"""Return the state of the device."""
|
||||
return self.roller.battery # type: ignore[no-any-return]
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
"""Support for Actiontec MI424WR (Verizon FIOS) routers."""
|
||||
|
||||
import logging
|
||||
from typing import Final
|
||||
from typing import Final, override
|
||||
|
||||
import telnetlib # pylint: disable=deprecated-module
|
||||
import voluptuous as vol
|
||||
@@ -50,11 +50,13 @@ class ActiontecDeviceScanner(DeviceScanner):
|
||||
data = self.get_actiontec_data()
|
||||
self.success_init = data is not None
|
||||
|
||||
@override
|
||||
def scan_devices(self) -> list[str]:
|
||||
"""Scan for new devices and return a list with found device IDs."""
|
||||
self._update_info()
|
||||
return [client.mac_address for client in self.last_results]
|
||||
|
||||
@override
|
||||
def get_device_name(self, device: str) -> str | None:
|
||||
"""Return the name of the given device or None if we don't know."""
|
||||
for client in self.last_results:
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
"""Climate platform for Actron Air integration."""
|
||||
|
||||
from typing import Any
|
||||
from typing import Any, override
|
||||
|
||||
from actron_neo_api import ActronAirStatus, ActronAirZone
|
||||
|
||||
@@ -94,6 +94,7 @@ class ActronSystemClimate(ActronAirAcEntity, ActronAirClimateEntity):
|
||||
self._attr_unique_id = self._serial_number
|
||||
|
||||
@property
|
||||
@override
|
||||
def hvac_modes(self) -> list[HVACMode]:
|
||||
"""Return the list of supported HVAC modes."""
|
||||
modes = [
|
||||
@@ -105,11 +106,13 @@ class ActronSystemClimate(ActronAirAcEntity, ActronAirClimateEntity):
|
||||
return modes
|
||||
|
||||
@property
|
||||
@override
|
||||
def min_temp(self) -> float:
|
||||
"""Return the minimum temperature that can be set."""
|
||||
return self._status.min_temp
|
||||
|
||||
@property
|
||||
@override
|
||||
def max_temp(self) -> float:
|
||||
"""Return the maximum temperature that can be set."""
|
||||
return self._status.max_temp
|
||||
@@ -120,6 +123,7 @@ class ActronSystemClimate(ActronAirAcEntity, ActronAirClimateEntity):
|
||||
return self.coordinator.data
|
||||
|
||||
@property
|
||||
@override
|
||||
def hvac_mode(self) -> HVACMode | None:
|
||||
"""Return the current HVAC mode."""
|
||||
if not self._status.user_aircon_settings.is_on:
|
||||
@@ -129,39 +133,46 @@ class ActronSystemClimate(ActronAirAcEntity, ActronAirClimateEntity):
|
||||
return HVAC_MODE_MAPPING_ACTRONAIR_TO_HA.get(mode)
|
||||
|
||||
@property
|
||||
@override
|
||||
def fan_mode(self) -> str | None:
|
||||
"""Return the current fan mode."""
|
||||
fan_mode = self._status.user_aircon_settings.base_fan_mode
|
||||
return FAN_MODE_MAPPING_ACTRONAIR_TO_HA.get(fan_mode)
|
||||
|
||||
@property
|
||||
@override
|
||||
def current_humidity(self) -> float:
|
||||
"""Return the current humidity."""
|
||||
return self._status.master_info.live_humidity_pc
|
||||
|
||||
@property
|
||||
@override
|
||||
def current_temperature(self) -> float:
|
||||
"""Return the current temperature."""
|
||||
return self._status.master_info.live_temp_c
|
||||
|
||||
@property
|
||||
@override
|
||||
def target_temperature(self) -> float:
|
||||
"""Return the target temperature."""
|
||||
return self._status.user_aircon_settings.current_setpoint
|
||||
|
||||
@actron_air_command
|
||||
@override
|
||||
async def async_set_fan_mode(self, fan_mode: str) -> None:
|
||||
"""Set a new fan mode."""
|
||||
api_fan_mode = FAN_MODE_MAPPING_HA_TO_ACTRONAIR[fan_mode]
|
||||
await self._status.user_aircon_settings.set_fan_mode(api_fan_mode)
|
||||
|
||||
@actron_air_command
|
||||
@override
|
||||
async def async_set_hvac_mode(self, hvac_mode: HVACMode) -> None:
|
||||
"""Set the HVAC mode."""
|
||||
ac_mode = HVAC_MODE_MAPPING_HA_TO_ACTRONAIR[hvac_mode]
|
||||
await self._status.ac_system.set_system_mode(ac_mode)
|
||||
|
||||
@actron_air_command
|
||||
@override
|
||||
async def async_set_temperature(self, **kwargs: Any) -> None:
|
||||
"""Set the temperature."""
|
||||
if (temperature := kwargs.get(ATTR_TEMPERATURE)) is None:
|
||||
@@ -191,6 +202,7 @@ class ActronZoneClimate(ActronAirZoneEntity, ActronAirClimateEntity):
|
||||
self._attr_unique_id: str = self._zone_identifier
|
||||
|
||||
@property
|
||||
@override
|
||||
def hvac_modes(self) -> list[HVACMode]:
|
||||
"""Return the list of supported HVAC modes."""
|
||||
status = self.coordinator.data
|
||||
@@ -203,11 +215,13 @@ class ActronZoneClimate(ActronAirZoneEntity, ActronAirClimateEntity):
|
||||
return modes
|
||||
|
||||
@property
|
||||
@override
|
||||
def min_temp(self) -> float:
|
||||
"""Return the minimum temperature that can be set."""
|
||||
return self._zone.min_temp
|
||||
|
||||
@property
|
||||
@override
|
||||
def max_temp(self) -> float:
|
||||
"""Return the maximum temperature that can be set."""
|
||||
return self._zone.max_temp
|
||||
@@ -219,6 +233,7 @@ class ActronZoneClimate(ActronAirZoneEntity, ActronAirClimateEntity):
|
||||
return status.zones[self._zone_id]
|
||||
|
||||
@property
|
||||
@override
|
||||
def hvac_mode(self) -> HVACMode | None:
|
||||
"""Return the current HVAC mode."""
|
||||
if self._zone.is_active:
|
||||
@@ -227,27 +242,32 @@ class ActronZoneClimate(ActronAirZoneEntity, ActronAirClimateEntity):
|
||||
return HVACMode.OFF
|
||||
|
||||
@property
|
||||
@override
|
||||
def current_humidity(self) -> float | None:
|
||||
"""Return the current humidity."""
|
||||
return self._zone.humidity
|
||||
|
||||
@property
|
||||
@override
|
||||
def current_temperature(self) -> float | None:
|
||||
"""Return the current temperature."""
|
||||
return self._zone.live_temp_c
|
||||
|
||||
@property
|
||||
@override
|
||||
def target_temperature(self) -> float | None:
|
||||
"""Return the target temperature."""
|
||||
return self._zone.current_setpoint
|
||||
|
||||
@actron_air_command
|
||||
@override
|
||||
async def async_set_hvac_mode(self, hvac_mode: HVACMode) -> None:
|
||||
"""Set the HVAC mode."""
|
||||
is_enabled = hvac_mode != HVACMode.OFF
|
||||
await self._zone.enable(is_enabled)
|
||||
|
||||
@actron_air_command
|
||||
@override
|
||||
async def async_set_temperature(self, **kwargs: Any) -> None:
|
||||
"""Set the temperature."""
|
||||
if (temperature := kwargs.get(ATTR_TEMPERATURE)) is None:
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
import asyncio
|
||||
from collections.abc import Mapping
|
||||
from typing import Any
|
||||
from typing import Any, override
|
||||
|
||||
from actron_neo_api import ActronAirAPI, ActronAirAuthError
|
||||
|
||||
@@ -30,6 +30,7 @@ class ActronAirConfigFlow(ConfigFlow, domain=DOMAIN):
|
||||
self._expires_minutes: str = "30"
|
||||
self.login_task: asyncio.Task[None] | None = None
|
||||
|
||||
@override
|
||||
async def async_step_user(
|
||||
self, user_input: dict[str, Any] | None = None
|
||||
) -> ConfigFlowResult:
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
from dataclasses import dataclass
|
||||
from datetime import timedelta
|
||||
from typing import override
|
||||
|
||||
from actron_neo_api import (
|
||||
ActronAirAPI,
|
||||
@@ -60,6 +61,7 @@ class ActronAirSystemCoordinator(DataUpdateCoordinator[ActronAirStatus]):
|
||||
self.status = self.api.state_manager.get_status(self.serial_number)
|
||||
self.last_seen = dt_util.utcnow()
|
||||
|
||||
@override
|
||||
async def _async_update_data(self) -> ActronAirStatus:
|
||||
"""Fetch updates and merge incremental changes into the full state."""
|
||||
try:
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
from collections.abc import Callable, Coroutine
|
||||
from functools import wraps
|
||||
from typing import Any, Concatenate
|
||||
from typing import Any, Concatenate, override
|
||||
|
||||
from actron_neo_api import ActronAirAPIError, ActronAirZone
|
||||
|
||||
@@ -50,6 +50,7 @@ class ActronAirEntity(CoordinatorEntity[ActronAirSystemCoordinator]):
|
||||
self._serial_number = coordinator.serial_number
|
||||
|
||||
@property
|
||||
@override
|
||||
def available(self) -> bool:
|
||||
"""Return True if entity is available."""
|
||||
return not self.coordinator.is_device_stale()
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
from collections.abc import Awaitable, Callable
|
||||
from dataclasses import dataclass
|
||||
from typing import Any
|
||||
from typing import Any, override
|
||||
|
||||
from homeassistant.components.switch import SwitchEntity, SwitchEntityDescription
|
||||
from homeassistant.const import EntityCategory
|
||||
@@ -101,16 +101,19 @@ class ActronAirSwitch(ActronAirAcEntity, SwitchEntity):
|
||||
self._attr_unique_id = f"{coordinator.serial_number}_{description.key}"
|
||||
|
||||
@property
|
||||
@override
|
||||
def is_on(self) -> bool:
|
||||
"""Return true if the switch is on."""
|
||||
return self.entity_description.is_on_fn(self.coordinator)
|
||||
|
||||
@actron_air_command
|
||||
@override
|
||||
async def async_turn_on(self, **kwargs: Any) -> None:
|
||||
"""Turn the switch on."""
|
||||
await self.entity_description.set_fn(self.coordinator, True)
|
||||
|
||||
@actron_air_command
|
||||
@override
|
||||
async def async_turn_off(self, **kwargs: Any) -> None:
|
||||
"""Turn the switch off."""
|
||||
await self.entity_description.set_fn(self.coordinator, False)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
"""Support for Adax wifi-enabled home heaters."""
|
||||
|
||||
from typing import Any, cast
|
||||
from typing import Any, cast, override
|
||||
|
||||
from adax import Adax
|
||||
from adax_local import Adax as AdaxLocal
|
||||
@@ -82,6 +82,7 @@ class AdaxDevice(CoordinatorEntity[AdaxCloudCoordinator], ClimateEntity):
|
||||
self._apply_data(self.room)
|
||||
|
||||
@property
|
||||
@override
|
||||
def available(self) -> bool:
|
||||
"""Whether the entity is available or not."""
|
||||
return super().available and self._device_id in self.coordinator.data
|
||||
@@ -91,6 +92,7 @@ class AdaxDevice(CoordinatorEntity[AdaxCloudCoordinator], ClimateEntity):
|
||||
"""Gets the data for this particular device."""
|
||||
return self.coordinator.data[self._device_id]
|
||||
|
||||
@override
|
||||
async def async_set_hvac_mode(self, hvac_mode: HVACMode) -> None:
|
||||
"""Set hvac mode."""
|
||||
if hvac_mode == HVACMode.HEAT:
|
||||
@@ -108,6 +110,7 @@ class AdaxDevice(CoordinatorEntity[AdaxCloudCoordinator], ClimateEntity):
|
||||
# Request data refresh from source to verify that update was successful
|
||||
await self.coordinator.async_request_refresh()
|
||||
|
||||
@override
|
||||
async def async_set_temperature(self, **kwargs: Any) -> None:
|
||||
"""Set new target temperature."""
|
||||
if (temperature := kwargs.get(ATTR_TEMPERATURE)) is None:
|
||||
@@ -117,6 +120,7 @@ class AdaxDevice(CoordinatorEntity[AdaxCloudCoordinator], ClimateEntity):
|
||||
)
|
||||
|
||||
@callback
|
||||
@override
|
||||
def _handle_coordinator_update(self) -> None:
|
||||
"""Handle updated data from the coordinator."""
|
||||
if room := self.room:
|
||||
@@ -161,6 +165,7 @@ class LocalAdaxDevice(CoordinatorEntity[AdaxLocalCoordinator], ClimateEntity):
|
||||
manufacturer="Adax",
|
||||
)
|
||||
|
||||
@override
|
||||
async def async_set_hvac_mode(self, hvac_mode: HVACMode) -> None:
|
||||
"""Set hvac mode."""
|
||||
if hvac_mode == HVACMode.HEAT:
|
||||
@@ -179,6 +184,7 @@ class LocalAdaxDevice(CoordinatorEntity[AdaxLocalCoordinator], ClimateEntity):
|
||||
self._attr_hvac_mode = hvac_mode
|
||||
self.async_write_ha_state()
|
||||
|
||||
@override
|
||||
async def async_set_temperature(self, **kwargs: Any) -> None:
|
||||
"""Set new target temperature."""
|
||||
if (temperature := kwargs.get(ATTR_TEMPERATURE)) is None:
|
||||
@@ -211,11 +217,13 @@ class LocalAdaxDevice(CoordinatorEntity[AdaxLocalCoordinator], ClimateEntity):
|
||||
self._attr_target_temperature = target_temp
|
||||
|
||||
@callback
|
||||
@override
|
||||
def _handle_coordinator_update(self) -> None:
|
||||
"""Handle updated data from the coordinator."""
|
||||
self._update_hvac_attributes()
|
||||
super()._handle_coordinator_update()
|
||||
|
||||
@override
|
||||
async def async_added_to_hass(self) -> None:
|
||||
"""When entity is added to hass."""
|
||||
await super().async_added_to_hass()
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
"""Config flow for Adax integration."""
|
||||
|
||||
import logging
|
||||
from typing import Any
|
||||
from typing import Any, override
|
||||
|
||||
import adax
|
||||
import adax_local
|
||||
@@ -39,6 +39,7 @@ class AdaxConfigFlow(ConfigFlow, domain=DOMAIN):
|
||||
|
||||
VERSION = 2
|
||||
|
||||
@override
|
||||
async def async_step_user(
|
||||
self, user_input: dict[str, Any] | None = None
|
||||
) -> ConfigFlowResult:
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
"""DataUpdateCoordinator for the Adax component."""
|
||||
|
||||
import logging
|
||||
from typing import Any, cast
|
||||
from typing import Any, cast, override
|
||||
|
||||
from adax import Adax
|
||||
from adax_local import Adax as AdaxLocal
|
||||
@@ -39,6 +39,7 @@ class AdaxCloudCoordinator(DataUpdateCoordinator[dict[str, dict[str, Any]]]):
|
||||
websession=async_get_clientsession(hass),
|
||||
)
|
||||
|
||||
@override
|
||||
async def _async_update_data(self) -> dict[str, dict[str, Any]]:
|
||||
"""Fetch data from the Adax."""
|
||||
try:
|
||||
@@ -87,6 +88,7 @@ class AdaxLocalCoordinator(DataUpdateCoordinator[dict[str, Any] | None]):
|
||||
websession=async_get_clientsession(hass, verify_ssl=False),
|
||||
)
|
||||
|
||||
@override
|
||||
async def _async_update_data(self) -> dict[str, Any]:
|
||||
"""Fetch data from the Adax."""
|
||||
if result := await self.adax_data_handler.get_status():
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
"""Support for Adax energy sensors."""
|
||||
|
||||
from dataclasses import dataclass
|
||||
from typing import cast
|
||||
from typing import cast, override
|
||||
|
||||
from homeassistant.components.sensor import (
|
||||
SensorDeviceClass,
|
||||
@@ -95,6 +95,7 @@ class AdaxSensor(CoordinatorEntity[AdaxCloudCoordinator], SensorEntity):
|
||||
)
|
||||
|
||||
@property
|
||||
@override
|
||||
def available(self) -> bool:
|
||||
"""Return True if entity is available."""
|
||||
return (
|
||||
@@ -104,6 +105,7 @@ class AdaxSensor(CoordinatorEntity[AdaxCloudCoordinator], SensorEntity):
|
||||
)
|
||||
|
||||
@property
|
||||
@override
|
||||
def native_value(self) -> int | float | None:
|
||||
"""Return the native value of the sensor."""
|
||||
return self.coordinator.data[self._device_id].get(
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
"""Config flow to configure the AdGuard Home integration."""
|
||||
|
||||
from typing import Any
|
||||
from typing import Any, override
|
||||
|
||||
from adguardhome import AdGuardHome, AdGuardHomeConnectionError
|
||||
import voluptuous as vol
|
||||
@@ -57,6 +57,7 @@ class AdGuardHomeFlowHandler(ConfigFlow, domain=DOMAIN):
|
||||
errors=errors or {},
|
||||
)
|
||||
|
||||
@override
|
||||
async def async_step_user(
|
||||
self, user_input: dict[str, Any] | None = None
|
||||
) -> ConfigFlowResult:
|
||||
@@ -102,6 +103,7 @@ class AdGuardHomeFlowHandler(ConfigFlow, domain=DOMAIN):
|
||||
},
|
||||
)
|
||||
|
||||
@override
|
||||
async def async_step_hassio(
|
||||
self, discovery_info: HassioServiceInfo
|
||||
) -> ConfigFlowResult:
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
"""AdGuard Home base entity."""
|
||||
|
||||
from typing import override
|
||||
|
||||
from adguardhome import AdGuardHomeError
|
||||
|
||||
from homeassistant.config_entries import SOURCE_HASSIO
|
||||
@@ -47,6 +49,7 @@ class AdGuardHomeEntity(Entity):
|
||||
raise NotImplementedError
|
||||
|
||||
@property
|
||||
@override
|
||||
def device_info(self) -> DeviceInfo:
|
||||
"""Return device information about this AdGuard Home instance."""
|
||||
if self._entry.source == SOURCE_HASSIO:
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
from collections.abc import Callable, Coroutine
|
||||
from dataclasses import dataclass
|
||||
from datetime import timedelta
|
||||
from typing import Any
|
||||
from typing import Any, override
|
||||
|
||||
from adguardhome import AdGuardHome
|
||||
|
||||
@@ -108,7 +108,7 @@ class AdGuardHomeSensor(AdGuardHomeEntity, SensorEntity):
|
||||
"""Initialize AdGuard Home sensor."""
|
||||
super().__init__(data, entry)
|
||||
self.entity_description = description
|
||||
self._attr_unique_id = "_".join(
|
||||
self._attr_unique_id = "_".join( # pylint: disable=home-assistant-entity-unique-id-redundant-domain
|
||||
[
|
||||
DOMAIN,
|
||||
self.adguard.host,
|
||||
@@ -118,6 +118,7 @@ class AdGuardHomeSensor(AdGuardHomeEntity, SensorEntity):
|
||||
]
|
||||
)
|
||||
|
||||
@override
|
||||
async def _adguard_update(self) -> None:
|
||||
"""Update AdGuard Home entity."""
|
||||
value = await self.entity_description.value_fn(self.adguard)
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
from collections.abc import Callable, Coroutine
|
||||
from dataclasses import dataclass
|
||||
from datetime import timedelta
|
||||
from typing import Any
|
||||
from typing import Any, override
|
||||
|
||||
from adguardhome import AdGuardHome, AdGuardHomeError
|
||||
|
||||
@@ -103,7 +103,7 @@ class AdGuardHomeSwitch(AdGuardHomeEntity, SwitchEntity):
|
||||
"""Initialize AdGuard Home switch."""
|
||||
super().__init__(data, entry)
|
||||
self.entity_description = description
|
||||
self._attr_unique_id = "_".join(
|
||||
self._attr_unique_id = "_".join( # pylint: disable=home-assistant-entity-unique-id-redundant-domain
|
||||
[
|
||||
DOMAIN,
|
||||
self.adguard.host,
|
||||
@@ -113,6 +113,7 @@ class AdGuardHomeSwitch(AdGuardHomeEntity, SwitchEntity):
|
||||
]
|
||||
)
|
||||
|
||||
@override
|
||||
async def async_turn_off(self, **kwargs: Any) -> None:
|
||||
"""Turn off the switch."""
|
||||
try:
|
||||
@@ -124,6 +125,7 @@ class AdGuardHomeSwitch(AdGuardHomeEntity, SwitchEntity):
|
||||
translation_key="error_while_turn_off",
|
||||
) from err
|
||||
|
||||
@override
|
||||
async def async_turn_on(self, **kwargs: Any) -> None:
|
||||
"""Turn on the switch."""
|
||||
try:
|
||||
@@ -135,6 +137,7 @@ class AdGuardHomeSwitch(AdGuardHomeEntity, SwitchEntity):
|
||||
translation_key="error_while_turn_on",
|
||||
) from err
|
||||
|
||||
@override
|
||||
async def _adguard_update(self) -> None:
|
||||
"""Update AdGuard Home entity."""
|
||||
self._attr_is_on = await self.entity_description.is_on_fn(self.adguard)()
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
"""AdGuard Home Update platform."""
|
||||
|
||||
from datetime import timedelta
|
||||
from typing import Any
|
||||
from typing import Any, override
|
||||
|
||||
from adguardhome import AdGuardHomeError
|
||||
|
||||
@@ -46,10 +46,11 @@ class AdGuardHomeUpdate(AdGuardHomeEntity, UpdateEntity):
|
||||
"""Initialize AdGuard Home update."""
|
||||
super().__init__(data, entry)
|
||||
|
||||
self._attr_unique_id = "_".join(
|
||||
self._attr_unique_id = "_".join( # pylint: disable=home-assistant-entity-unique-id-redundant-domain
|
||||
[DOMAIN, self.adguard.host, str(self.adguard.port), "update"]
|
||||
)
|
||||
|
||||
@override
|
||||
async def _adguard_update(self) -> None:
|
||||
"""Update AdGuard Home entity."""
|
||||
value = await self.adguard.update.update_available()
|
||||
@@ -58,6 +59,7 @@ class AdGuardHomeUpdate(AdGuardHomeEntity, UpdateEntity):
|
||||
self._attr_release_summary = value.announcement
|
||||
self._attr_release_url = value.announcement_url
|
||||
|
||||
@override
|
||||
async def async_install(
|
||||
self, version: str | None, backup: bool, **kwargs: Any
|
||||
) -> None:
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
"""Support for ADS binary sensors."""
|
||||
|
||||
from typing import override
|
||||
|
||||
import pyads
|
||||
import voluptuous as vol
|
||||
|
||||
@@ -60,11 +62,13 @@ class AdsBinarySensor(AdsEntity, BinarySensorEntity):
|
||||
super().__init__(ads_hub, name, ads_var)
|
||||
self._attr_device_class = device_class or BinarySensorDeviceClass.MOVING
|
||||
|
||||
@override
|
||||
async def async_added_to_hass(self) -> None:
|
||||
"""Register device notification."""
|
||||
await self.async_initialize_device(self._ads_var, pyads.PLCTYPE_BOOL)
|
||||
|
||||
@property
|
||||
@override
|
||||
def is_on(self) -> bool:
|
||||
"""Return True if the entity is on."""
|
||||
return self._state_dict[STATE_KEY_STATE]
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
"""Support for ADS covers."""
|
||||
|
||||
from typing import Any
|
||||
from typing import Any, override
|
||||
|
||||
import pyads
|
||||
import voluptuous as vol
|
||||
@@ -122,6 +122,7 @@ class AdsCover(AdsEntity, CoverEntity):
|
||||
if ads_var_pos_set is not None:
|
||||
self._attr_supported_features |= CoverEntityFeature.SET_POSITION
|
||||
|
||||
@override
|
||||
async def async_added_to_hass(self) -> None:
|
||||
"""Register device notification."""
|
||||
if self._ads_var is not None:
|
||||
@@ -133,6 +134,7 @@ class AdsCover(AdsEntity, CoverEntity):
|
||||
)
|
||||
|
||||
@property
|
||||
@override
|
||||
def is_closed(self) -> bool | None:
|
||||
"""Return if the cover is closed."""
|
||||
if self._ads_var is not None:
|
||||
@@ -142,15 +144,18 @@ class AdsCover(AdsEntity, CoverEntity):
|
||||
return None
|
||||
|
||||
@property
|
||||
@override
|
||||
def current_cover_position(self) -> int:
|
||||
"""Return current position of cover."""
|
||||
return self._state_dict[STATE_KEY_POSITION]
|
||||
|
||||
@override
|
||||
def stop_cover(self, **kwargs: Any) -> None:
|
||||
"""Fire the stop action."""
|
||||
if self._ads_var_stop:
|
||||
self._ads_hub.write_by_name(self._ads_var_stop, True, pyads.PLCTYPE_BOOL)
|
||||
|
||||
@override
|
||||
def set_cover_position(self, **kwargs: Any) -> None:
|
||||
"""Set cover position."""
|
||||
position = kwargs[ATTR_POSITION]
|
||||
@@ -159,6 +164,7 @@ class AdsCover(AdsEntity, CoverEntity):
|
||||
self._ads_var_pos_set, position, pyads.PLCTYPE_BYTE
|
||||
)
|
||||
|
||||
@override
|
||||
def open_cover(self, **kwargs: Any) -> None:
|
||||
"""Move the cover up."""
|
||||
if self._ads_var_open is not None:
|
||||
@@ -166,6 +172,7 @@ class AdsCover(AdsEntity, CoverEntity):
|
||||
elif self._ads_var_pos_set is not None:
|
||||
self.set_cover_position(position=100)
|
||||
|
||||
@override
|
||||
def close_cover(self, **kwargs: Any) -> None:
|
||||
"""Move the cover down."""
|
||||
if self._ads_var_close is not None:
|
||||
@@ -174,6 +181,7 @@ class AdsCover(AdsEntity, CoverEntity):
|
||||
self.set_cover_position(position=0)
|
||||
|
||||
@property
|
||||
@override
|
||||
def available(self) -> bool:
|
||||
"""Return False if state has not been updated yet."""
|
||||
if self._ads_var is not None or self._ads_var_position is not None:
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
import asyncio
|
||||
from asyncio import timeout
|
||||
import logging
|
||||
from typing import Any
|
||||
from typing import Any, override
|
||||
|
||||
from homeassistant.helpers.entity import Entity
|
||||
|
||||
@@ -65,6 +65,7 @@ class AdsEntity(Entity):
|
||||
_LOGGER.debug("Variable %s: Timeout during first update", ads_var)
|
||||
|
||||
@property
|
||||
@override
|
||||
def available(self) -> bool:
|
||||
"""Return False if state has not been updated yet."""
|
||||
return self._state_dict[STATE_KEY_STATE] is not None
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
"""Support for ADS light sources."""
|
||||
|
||||
from typing import Any
|
||||
from typing import Any, override
|
||||
|
||||
import pyads
|
||||
import voluptuous as vol
|
||||
@@ -120,6 +120,7 @@ class AdsLight(AdsEntity, LightEntity):
|
||||
else DEFAULT_MAX_KELVIN
|
||||
)
|
||||
|
||||
@override
|
||||
async def async_added_to_hass(self) -> None:
|
||||
"""Register device notification."""
|
||||
await self.async_initialize_device(self._ads_var, pyads.PLCTYPE_BOOL)
|
||||
@@ -139,20 +140,24 @@ class AdsLight(AdsEntity, LightEntity):
|
||||
)
|
||||
|
||||
@property
|
||||
@override
|
||||
def brightness(self) -> int | None:
|
||||
"""Return the brightness of the light (0..255)."""
|
||||
return self._state_dict[STATE_KEY_BRIGHTNESS]
|
||||
|
||||
@property
|
||||
@override
|
||||
def color_temp_kelvin(self) -> int | None:
|
||||
"""Return the color temperature in Kelvin."""
|
||||
return self._state_dict[STATE_KEY_COLOR_TEMP_KELVIN]
|
||||
|
||||
@property
|
||||
@override
|
||||
def is_on(self) -> bool:
|
||||
"""Return True if the entity is on."""
|
||||
return self._state_dict[STATE_KEY_STATE]
|
||||
|
||||
@override
|
||||
def turn_on(self, **kwargs: Any) -> None:
|
||||
"""Turn the light on or set a specific dimmer value."""
|
||||
brightness = kwargs.get(ATTR_BRIGHTNESS)
|
||||
@@ -170,6 +175,7 @@ class AdsLight(AdsEntity, LightEntity):
|
||||
self._ads_var_color_temp_kelvin, color_temp, pyads.PLCTYPE_UINT
|
||||
)
|
||||
|
||||
@override
|
||||
def turn_off(self, **kwargs: Any) -> None:
|
||||
"""Turn the light off."""
|
||||
self._ads_hub.write_by_name(self._ads_var, False, pyads.PLCTYPE_BOOL)
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
"""Support for ADS select entities."""
|
||||
|
||||
from typing import override
|
||||
|
||||
import pyads
|
||||
import voluptuous as vol
|
||||
|
||||
@@ -61,6 +63,7 @@ class AdsSelect(AdsEntity, SelectEntity):
|
||||
self._attr_options = options
|
||||
self._attr_current_option = None
|
||||
|
||||
@override
|
||||
async def async_added_to_hass(self) -> None:
|
||||
"""Register device notification."""
|
||||
await self.async_initialize_device(self._ads_var, pyads.PLCTYPE_INT)
|
||||
@@ -68,6 +71,7 @@ class AdsSelect(AdsEntity, SelectEntity):
|
||||
self._ads_var, pyads.PLCTYPE_INT, self._handle_ads_value
|
||||
)
|
||||
|
||||
@override
|
||||
def select_option(self, option: str) -> None:
|
||||
"""Change the selected option."""
|
||||
if option in self._attr_options:
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
"""Support for ADS sensors."""
|
||||
|
||||
from typing import override
|
||||
|
||||
import voluptuous as vol
|
||||
|
||||
from homeassistant.components.sensor import (
|
||||
@@ -108,6 +110,7 @@ class AdsSensor(AdsEntity, SensorEntity):
|
||||
self._attr_state_class = state_class
|
||||
self._attr_native_unit_of_measurement = unit_of_measurement
|
||||
|
||||
@override
|
||||
async def async_added_to_hass(self) -> None:
|
||||
"""Register device notification."""
|
||||
await self.async_initialize_device(
|
||||
@@ -118,6 +121,7 @@ class AdsSensor(AdsEntity, SensorEntity):
|
||||
)
|
||||
|
||||
@property
|
||||
@override
|
||||
def native_value(self) -> StateType:
|
||||
"""Return the state of the device."""
|
||||
return self._state_dict[STATE_KEY_STATE]
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
"""Support for ADS switch platform."""
|
||||
|
||||
from typing import Any
|
||||
from typing import Any, override
|
||||
|
||||
import pyads
|
||||
import voluptuous as vol
|
||||
@@ -46,19 +46,23 @@ def setup_platform(
|
||||
class AdsSwitch(AdsEntity, SwitchEntity):
|
||||
"""Representation of an ADS switch device."""
|
||||
|
||||
@override
|
||||
async def async_added_to_hass(self) -> None:
|
||||
"""Register device notification."""
|
||||
await self.async_initialize_device(self._ads_var, pyads.PLCTYPE_BOOL)
|
||||
|
||||
@property
|
||||
@override
|
||||
def is_on(self) -> bool:
|
||||
"""Return True if the entity is on."""
|
||||
return self._state_dict[STATE_KEY_STATE]
|
||||
|
||||
@override
|
||||
def turn_on(self, **kwargs: Any) -> None:
|
||||
"""Turn the switch on."""
|
||||
self._ads_hub.write_by_name(self._ads_var, True, pyads.PLCTYPE_BOOL)
|
||||
|
||||
@override
|
||||
def turn_off(self, **kwargs: Any) -> None:
|
||||
"""Turn the switch off."""
|
||||
self._ads_hub.write_by_name(self._ads_var, False, pyads.PLCTYPE_BOOL)
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
"""Support for ADS valves."""
|
||||
|
||||
from typing import override
|
||||
|
||||
import pyads
|
||||
import voluptuous as vol
|
||||
|
||||
@@ -67,15 +69,18 @@ class AdsValve(AdsEntity, ValveEntity):
|
||||
self._attr_reports_position = False
|
||||
self._attr_is_closed = True
|
||||
|
||||
@override
|
||||
async def async_added_to_hass(self) -> None:
|
||||
"""Register device notification."""
|
||||
await self.async_initialize_device(self._ads_var, pyads.PLCTYPE_BOOL)
|
||||
|
||||
@override
|
||||
def open_valve(self, **kwargs) -> None:
|
||||
"""Open the valve."""
|
||||
self._ads_hub.write_by_name(self._ads_var, True, pyads.PLCTYPE_BOOL)
|
||||
self._attr_is_closed = False
|
||||
|
||||
@override
|
||||
def close_valve(self, **kwargs) -> None:
|
||||
"""Close the valve."""
|
||||
self._ads_hub.write_by_name(self._ads_var, False, pyads.PLCTYPE_BOOL)
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
"""Binary Sensor platform for Advantage Air integration."""
|
||||
|
||||
from typing import override
|
||||
|
||||
from homeassistant.components.binary_sensor import (
|
||||
BinarySensorDeviceClass,
|
||||
BinarySensorEntity,
|
||||
@@ -55,6 +57,7 @@ class AdvantageAirFilter(AdvantageAirAcEntity, BinarySensorEntity):
|
||||
self._attr_unique_id += "-filter"
|
||||
|
||||
@property
|
||||
@override
|
||||
def is_on(self) -> bool:
|
||||
"""Return if filter needs cleaning."""
|
||||
return self._ac["filterCleanStatus"]
|
||||
@@ -74,6 +77,7 @@ class AdvantageAirZoneMotion(AdvantageAirZoneEntity, BinarySensorEntity):
|
||||
self._attr_unique_id += "-motion"
|
||||
|
||||
@property
|
||||
@override
|
||||
def is_on(self) -> bool:
|
||||
"""Return if motion is detect."""
|
||||
return self._zone["motion"] == 20
|
||||
@@ -94,6 +98,7 @@ class AdvantageAirZoneMyZone(AdvantageAirZoneEntity, BinarySensorEntity):
|
||||
self._attr_unique_id += "-myzone"
|
||||
|
||||
@property
|
||||
@override
|
||||
def is_on(self) -> bool:
|
||||
"""Return if this zone is the myZone."""
|
||||
return self._zone["number"] == self._ac["myZone"]
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
from decimal import Decimal
|
||||
import logging
|
||||
from typing import Any
|
||||
from typing import Any, override
|
||||
|
||||
from homeassistant.components.climate import (
|
||||
ATTR_TARGET_TEMP_HIGH,
|
||||
@@ -156,12 +156,14 @@ class AdvantageAirAC(AdvantageAirAcEntity, ClimateEntity):
|
||||
)
|
||||
|
||||
@callback
|
||||
@override
|
||||
def _handle_coordinator_update(self) -> None:
|
||||
"""Handle updated data from the coordinator."""
|
||||
self._async_configure_preset()
|
||||
super()._handle_coordinator_update()
|
||||
|
||||
@property
|
||||
@override
|
||||
def current_temperature(self) -> float | None:
|
||||
"""Return the selected zones current temperature."""
|
||||
if self._myzone:
|
||||
@@ -169,6 +171,7 @@ class AdvantageAirAC(AdvantageAirAcEntity, ClimateEntity):
|
||||
return None
|
||||
|
||||
@property
|
||||
@override
|
||||
def target_temperature(self) -> float | None:
|
||||
"""Return the current target temperature."""
|
||||
# If the system is in MyZone mode, and a zone is set,
|
||||
@@ -178,6 +181,7 @@ class AdvantageAirAC(AdvantageAirAcEntity, ClimateEntity):
|
||||
return self._ac["setTemp"]
|
||||
|
||||
@property
|
||||
@override
|
||||
def hvac_mode(self) -> HVACMode | None:
|
||||
"""Return the current HVAC modes."""
|
||||
if self._ac["state"] == ADVANTAGE_AIR_STATE_ON:
|
||||
@@ -185,6 +189,7 @@ class AdvantageAirAC(AdvantageAirAcEntity, ClimateEntity):
|
||||
return HVACMode.OFF
|
||||
|
||||
@property
|
||||
@override
|
||||
def hvac_action(self) -> HVACAction | None:
|
||||
"""Return the current running HVAC action."""
|
||||
if self._ac["state"] == ADVANTAGE_AIR_STATE_OFF:
|
||||
@@ -196,24 +201,29 @@ class AdvantageAirAC(AdvantageAirAcEntity, ClimateEntity):
|
||||
return HVAC_ACTIONS.get(self._ac["mode"])
|
||||
|
||||
@property
|
||||
@override
|
||||
def fan_mode(self) -> str | None:
|
||||
"""Return the current fan modes."""
|
||||
return FAN_AUTO if self._ac["fan"] == ADVANTAGE_AIR_MYFAN else self._ac["fan"]
|
||||
|
||||
@property
|
||||
@override
|
||||
def target_temperature_high(self) -> float | None:
|
||||
"""Return the temperature cool mode is enabled."""
|
||||
return self._ac.get(ADVANTAGE_AIR_COOL_TARGET)
|
||||
|
||||
@property
|
||||
@override
|
||||
def target_temperature_low(self) -> float | None:
|
||||
"""Return the temperature heat mode is enabled."""
|
||||
return self._ac.get(ADVANTAGE_AIR_HEAT_TARGET)
|
||||
|
||||
@override
|
||||
async def async_turn_on(self) -> None:
|
||||
"""Set the HVAC State to on."""
|
||||
await self.async_update_ac({"state": ADVANTAGE_AIR_STATE_ON})
|
||||
|
||||
@override
|
||||
async def async_turn_off(self) -> None:
|
||||
"""Set the HVAC State to off."""
|
||||
await self.async_update_ac(
|
||||
@@ -222,6 +232,7 @@ class AdvantageAirAC(AdvantageAirAcEntity, ClimateEntity):
|
||||
}
|
||||
)
|
||||
|
||||
@override
|
||||
async def async_set_hvac_mode(self, hvac_mode: HVACMode) -> None:
|
||||
"""Set the HVAC Mode and State."""
|
||||
if hvac_mode == HVACMode.OFF:
|
||||
@@ -236,6 +247,7 @@ class AdvantageAirAC(AdvantageAirAcEntity, ClimateEntity):
|
||||
}
|
||||
)
|
||||
|
||||
@override
|
||||
async def async_set_fan_mode(self, fan_mode: str) -> None:
|
||||
"""Set the Fan Mode."""
|
||||
if fan_mode == FAN_AUTO and self._ac.get(ADVANTAGE_AIR_AUTOFAN_ENABLED):
|
||||
@@ -244,6 +256,7 @@ class AdvantageAirAC(AdvantageAirAcEntity, ClimateEntity):
|
||||
mode = fan_mode
|
||||
await self.async_update_ac({"fan": mode})
|
||||
|
||||
@override
|
||||
async def async_set_temperature(self, **kwargs: Any) -> None:
|
||||
"""Set the Temperature."""
|
||||
if ATTR_TEMPERATURE in kwargs:
|
||||
@@ -256,6 +269,7 @@ class AdvantageAirAC(AdvantageAirAcEntity, ClimateEntity):
|
||||
}
|
||||
)
|
||||
|
||||
@override
|
||||
async def async_set_preset_mode(self, preset_mode: str) -> None:
|
||||
"""Set the preset mode."""
|
||||
change = {}
|
||||
@@ -289,6 +303,7 @@ class AdvantageAirZone(AdvantageAirZoneEntity, ClimateEntity):
|
||||
self._attr_name = self._zone["name"]
|
||||
|
||||
@property
|
||||
@override
|
||||
def hvac_mode(self) -> HVACMode:
|
||||
"""Return the current state as HVAC mode."""
|
||||
if self._zone["state"] == ADVANTAGE_AIR_STATE_OPEN:
|
||||
@@ -296,6 +311,7 @@ class AdvantageAirZone(AdvantageAirZoneEntity, ClimateEntity):
|
||||
return HVACMode.OFF
|
||||
|
||||
@property
|
||||
@override
|
||||
def hvac_action(self) -> HVACAction | None:
|
||||
"""Return the HVAC action.
|
||||
|
||||
@@ -316,23 +332,28 @@ class AdvantageAirZone(AdvantageAirZoneEntity, ClimateEntity):
|
||||
return HVACAction.OFF
|
||||
|
||||
@property
|
||||
@override
|
||||
def current_temperature(self) -> float | None:
|
||||
"""Return the current temperature."""
|
||||
return self._zone["measuredTemp"]
|
||||
|
||||
@property
|
||||
@override
|
||||
def target_temperature(self) -> float:
|
||||
"""Return the target temperature."""
|
||||
return self._zone["setTemp"]
|
||||
|
||||
@override
|
||||
async def async_turn_on(self) -> None:
|
||||
"""Set the HVAC State to on."""
|
||||
await self.async_update_zone({"state": ADVANTAGE_AIR_STATE_OPEN})
|
||||
|
||||
@override
|
||||
async def async_turn_off(self) -> None:
|
||||
"""Set the HVAC State to off."""
|
||||
await self.async_update_zone({"state": ADVANTAGE_AIR_STATE_CLOSE})
|
||||
|
||||
@override
|
||||
async def async_set_hvac_mode(self, hvac_mode: HVACMode) -> None:
|
||||
"""Set the HVAC Mode and State."""
|
||||
if hvac_mode == HVACMode.OFF:
|
||||
@@ -340,6 +361,7 @@ class AdvantageAirZone(AdvantageAirZoneEntity, ClimateEntity):
|
||||
else:
|
||||
await self.async_turn_on()
|
||||
|
||||
@override
|
||||
async def async_set_temperature(self, **kwargs: Any) -> None:
|
||||
"""Set the Temperature."""
|
||||
temp = kwargs.get(ATTR_TEMPERATURE)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
"""Config Flow for Advantage Air integration."""
|
||||
|
||||
from typing import Any
|
||||
from typing import Any, override
|
||||
|
||||
from advantage_air import ApiError, advantage_air
|
||||
import voluptuous as vol
|
||||
@@ -28,6 +28,7 @@ class AdvantageAirConfigFlow(ConfigFlow, domain=DOMAIN):
|
||||
|
||||
DOMAIN = DOMAIN
|
||||
|
||||
@override
|
||||
async def async_step_user(
|
||||
self, user_input: dict[str, Any] | None = None
|
||||
) -> ConfigFlowResult:
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
from datetime import timedelta
|
||||
import logging
|
||||
from typing import Any
|
||||
from typing import Any, override
|
||||
|
||||
from advantage_air import ApiError, advantage_air
|
||||
|
||||
@@ -45,6 +45,7 @@ class AdvantageAirCoordinator(DataUpdateCoordinator[dict[str, Any]]):
|
||||
)
|
||||
self.api = api
|
||||
|
||||
@override
|
||||
async def _async_update_data(self) -> dict[str, Any]:
|
||||
"""Fetch data from the API."""
|
||||
try:
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
"""Cover platform for Advantage Air integration."""
|
||||
|
||||
from typing import Any
|
||||
from typing import Any, override
|
||||
|
||||
from homeassistant.components.cover import (
|
||||
ATTR_POSITION,
|
||||
@@ -66,27 +66,32 @@ class AdvantageAirZoneVent(AdvantageAirZoneEntity, CoverEntity):
|
||||
self._attr_name = self._zone["name"]
|
||||
|
||||
@property
|
||||
@override
|
||||
def is_closed(self) -> bool:
|
||||
"""Return if vent is fully closed."""
|
||||
return self._zone["state"] == ADVANTAGE_AIR_STATE_CLOSE
|
||||
|
||||
@property
|
||||
@override
|
||||
def current_cover_position(self) -> int:
|
||||
"""Return vents current position as a percentage."""
|
||||
if self._zone["state"] == ADVANTAGE_AIR_STATE_OPEN:
|
||||
return self._zone["value"]
|
||||
return 0
|
||||
|
||||
@override
|
||||
async def async_open_cover(self, **kwargs: Any) -> None:
|
||||
"""Fully open zone vent."""
|
||||
await self.async_update_zone(
|
||||
{"state": ADVANTAGE_AIR_STATE_OPEN, "value": 100},
|
||||
)
|
||||
|
||||
@override
|
||||
async def async_close_cover(self, **kwargs: Any) -> None:
|
||||
"""Fully close zone vent."""
|
||||
await self.async_update_zone({"state": ADVANTAGE_AIR_STATE_CLOSE})
|
||||
|
||||
@override
|
||||
async def async_set_cover_position(self, **kwargs: Any) -> None:
|
||||
"""Change vent position."""
|
||||
position = round(kwargs[ATTR_POSITION] / 5) * 5
|
||||
@@ -117,14 +122,17 @@ class AdvantageAirThingCover(AdvantageAirThingEntity, CoverEntity):
|
||||
self._attr_device_class = device_class
|
||||
|
||||
@property
|
||||
@override
|
||||
def is_closed(self) -> bool:
|
||||
"""Return if cover is fully closed."""
|
||||
return self._data["value"] == 0
|
||||
|
||||
@override
|
||||
async def async_open_cover(self, **kwargs: Any) -> None:
|
||||
"""Fully open zone vent."""
|
||||
return await self.async_turn_on()
|
||||
|
||||
@override
|
||||
async def async_close_cover(self, **kwargs: Any) -> None:
|
||||
"""Fully close zone vent."""
|
||||
return await self.async_turn_off()
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
"""Light platform for Advantage Air integration."""
|
||||
|
||||
from typing import Any
|
||||
from typing import Any, override
|
||||
|
||||
from homeassistant.components.light import ATTR_BRIGHTNESS, ColorMode, LightEntity
|
||||
from homeassistant.core import HomeAssistant
|
||||
@@ -70,14 +70,17 @@ class AdvantageAirLight(AdvantageAirEntity, LightEntity):
|
||||
return self.coordinator.data["myLights"]["lights"][self._id]
|
||||
|
||||
@property
|
||||
@override
|
||||
def is_on(self) -> bool:
|
||||
"""Return if the light is on."""
|
||||
return self._data["state"] == ADVANTAGE_AIR_STATE_ON
|
||||
|
||||
@override
|
||||
async def async_turn_on(self, **kwargs: Any) -> None:
|
||||
"""Turn the light on."""
|
||||
await self.async_update_state(True)
|
||||
|
||||
@override
|
||||
async def async_turn_off(self, **kwargs: Any) -> None:
|
||||
"""Turn the light off."""
|
||||
await self.async_update_state(False)
|
||||
@@ -99,10 +102,12 @@ class AdvantageAirLightDimmable(AdvantageAirLight):
|
||||
)
|
||||
|
||||
@property
|
||||
@override
|
||||
def brightness(self) -> int:
|
||||
"""Return the brightness of this light between 0..255."""
|
||||
return round(self._data["value"] * 255 / 100)
|
||||
|
||||
@override
|
||||
async def async_turn_on(self, **kwargs: Any) -> None:
|
||||
"""Turn the light on and optionally set the brightness."""
|
||||
if ATTR_BRIGHTNESS in kwargs:
|
||||
@@ -124,10 +129,12 @@ class AdvantageAirThingLightDimmable(AdvantageAirThingEntity, LightEntity):
|
||||
_attr_supported_color_modes = {ColorMode.BRIGHTNESS}
|
||||
|
||||
@property
|
||||
@override
|
||||
def brightness(self) -> int:
|
||||
"""Return the brightness of this light between 0..255."""
|
||||
return round(self._data["value"] * 255 / 100)
|
||||
|
||||
@override
|
||||
async def async_turn_on(self, **kwargs: Any) -> None:
|
||||
"""Turn the light on by setting the brightness."""
|
||||
await self.async_update_value(round(kwargs.get(ATTR_BRIGHTNESS, 255) / 2.55))
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
"""Select platform for Advantage Air integration."""
|
||||
|
||||
from typing import override
|
||||
|
||||
from homeassistant.components.select import SelectEntity
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback
|
||||
@@ -48,10 +50,12 @@ class AdvantageAirMyZone(AdvantageAirAcEntity, SelectEntity):
|
||||
self._attr_options.append(zone["name"])
|
||||
|
||||
@property
|
||||
@override
|
||||
def current_option(self) -> str:
|
||||
"""Return the current MyZone."""
|
||||
return self._number_to_name[self._ac["myZone"]]
|
||||
|
||||
@override
|
||||
async def async_select_option(self, option: str) -> None:
|
||||
"""Set the MyZone."""
|
||||
await self.async_update_ac({"myZone": self._name_to_number[option]})
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
"""Sensor platform for Advantage Air integration."""
|
||||
|
||||
from decimal import Decimal
|
||||
from typing import Any
|
||||
from typing import Any, override
|
||||
|
||||
from homeassistant.components.sensor import (
|
||||
SensorDeviceClass,
|
||||
@@ -67,11 +67,13 @@ class AdvantageAirTimeTo(AdvantageAirAcEntity, SensorEntity):
|
||||
self._attr_unique_id += f"-timeto{action}"
|
||||
|
||||
@property
|
||||
@override
|
||||
def native_value(self) -> Decimal:
|
||||
"""Return the current value."""
|
||||
return self._ac[self._time_key]
|
||||
|
||||
@property
|
||||
@override
|
||||
def icon(self) -> str:
|
||||
"""Return a representative icon of the timer."""
|
||||
if self._ac[self._time_key] > 0:
|
||||
@@ -100,6 +102,7 @@ class AdvantageAirZoneVent(AdvantageAirZoneEntity, SensorEntity):
|
||||
self._attr_unique_id += "-vent"
|
||||
|
||||
@property
|
||||
@override
|
||||
def native_value(self) -> Decimal:
|
||||
"""Return the current value of the air vent."""
|
||||
if self._zone["state"] == ADVANTAGE_AIR_STATE_OPEN:
|
||||
@@ -107,6 +110,7 @@ class AdvantageAirZoneVent(AdvantageAirZoneEntity, SensorEntity):
|
||||
return Decimal(0)
|
||||
|
||||
@property
|
||||
@override
|
||||
def icon(self) -> str:
|
||||
"""Return a representative icon."""
|
||||
if self._zone["state"] == ADVANTAGE_AIR_STATE_OPEN:
|
||||
@@ -130,11 +134,13 @@ class AdvantageAirZoneSignal(AdvantageAirZoneEntity, SensorEntity):
|
||||
self._attr_unique_id += "-signal"
|
||||
|
||||
@property
|
||||
@override
|
||||
def native_value(self) -> Decimal:
|
||||
"""Return the current value of the wireless signal."""
|
||||
return self._zone["rssi"]
|
||||
|
||||
@property
|
||||
@override
|
||||
def icon(self) -> str:
|
||||
"""Return a representative icon."""
|
||||
if self._zone["rssi"] >= 80:
|
||||
@@ -166,6 +172,7 @@ class AdvantageAirZoneTemp(AdvantageAirZoneEntity, SensorEntity):
|
||||
self._attr_unique_id += "-temp"
|
||||
|
||||
@property
|
||||
@override
|
||||
def native_value(self) -> Decimal:
|
||||
"""Return the current value of the measured temperature."""
|
||||
return self._zone["measuredTemp"]
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
"""Switch platform for Advantage Air integration."""
|
||||
|
||||
from typing import Any
|
||||
from typing import Any, override
|
||||
|
||||
from homeassistant.components.switch import SwitchDeviceClass, SwitchEntity
|
||||
from homeassistant.core import HomeAssistant
|
||||
@@ -57,14 +57,17 @@ class AdvantageAirFreshAir(AdvantageAirAcEntity, SwitchEntity):
|
||||
self._attr_unique_id += "-freshair"
|
||||
|
||||
@property
|
||||
@override
|
||||
def is_on(self) -> bool:
|
||||
"""Return the fresh air status."""
|
||||
return self._ac["freshAirStatus"] == ADVANTAGE_AIR_STATE_ON
|
||||
|
||||
@override
|
||||
async def async_turn_on(self, **kwargs: Any) -> None:
|
||||
"""Turn fresh air on."""
|
||||
await self.async_update_ac({"freshAirStatus": ADVANTAGE_AIR_STATE_ON})
|
||||
|
||||
@override
|
||||
async def async_turn_off(self, **kwargs: Any) -> None:
|
||||
"""Turn fresh air off."""
|
||||
await self.async_update_ac({"freshAirStatus": ADVANTAGE_AIR_STATE_OFF})
|
||||
@@ -83,14 +86,17 @@ class AdvantageAirMyFan(AdvantageAirAcEntity, SwitchEntity):
|
||||
self._attr_unique_id += "-myfan"
|
||||
|
||||
@property
|
||||
@override
|
||||
def is_on(self) -> bool:
|
||||
"""Return the MyFan status."""
|
||||
return self._ac[ADVANTAGE_AIR_AUTOFAN_ENABLED]
|
||||
|
||||
@override
|
||||
async def async_turn_on(self, **kwargs: Any) -> None:
|
||||
"""Turn MyFan on."""
|
||||
await self.async_update_ac({ADVANTAGE_AIR_AUTOFAN_ENABLED: True})
|
||||
|
||||
@override
|
||||
async def async_turn_off(self, **kwargs: Any) -> None:
|
||||
"""Turn MyFan off."""
|
||||
await self.async_update_ac({ADVANTAGE_AIR_AUTOFAN_ENABLED: False})
|
||||
@@ -109,14 +115,17 @@ class AdvantageAirNightMode(AdvantageAirAcEntity, SwitchEntity):
|
||||
self._attr_unique_id += "-nightmode"
|
||||
|
||||
@property
|
||||
@override
|
||||
def is_on(self) -> bool:
|
||||
"""Return the Night Mode status."""
|
||||
return self._ac[ADVANTAGE_AIR_NIGHT_MODE_ENABLED]
|
||||
|
||||
@override
|
||||
async def async_turn_on(self, **kwargs: Any) -> None:
|
||||
"""Turn Night Mode on."""
|
||||
await self.async_update_ac({ADVANTAGE_AIR_NIGHT_MODE_ENABLED: True})
|
||||
|
||||
@override
|
||||
async def async_turn_off(self, **kwargs: Any) -> None:
|
||||
"""Turn Night Mode off."""
|
||||
await self.async_update_ac({ADVANTAGE_AIR_NIGHT_MODE_ENABLED: False})
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
"""Advantage Air Update platform."""
|
||||
|
||||
from typing import override
|
||||
|
||||
from homeassistant.components.update import UpdateEntity
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers.device_registry import DeviceInfo
|
||||
@@ -40,11 +42,13 @@ class AdvantageAirApp(AdvantageAirEntity, UpdateEntity):
|
||||
)
|
||||
|
||||
@property
|
||||
@override
|
||||
def installed_version(self) -> str:
|
||||
"""Return the current app version."""
|
||||
return self.coordinator.data["system"]["myAppRev"]
|
||||
|
||||
@property
|
||||
@override
|
||||
def latest_version(self) -> str:
|
||||
"""Return if there is an update."""
|
||||
if self.coordinator.data["system"]["needsUpdate"]:
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
"""Config flow for AEMET OpenData."""
|
||||
|
||||
from typing import Any
|
||||
from typing import Any, override
|
||||
|
||||
from aemet_opendata.exceptions import AuthError
|
||||
from aemet_opendata.interface import AEMET, ConnectionOptions
|
||||
@@ -31,6 +31,7 @@ OPTIONS_FLOW = {
|
||||
class AemetConfigFlow(ConfigFlow, domain=DOMAIN):
|
||||
"""Config flow for AEMET OpenData."""
|
||||
|
||||
@override
|
||||
async def async_step_user(
|
||||
self, user_input: dict[str, Any] | None = None
|
||||
) -> ConfigFlowResult:
|
||||
@@ -82,6 +83,7 @@ class AemetConfigFlow(ConfigFlow, domain=DOMAIN):
|
||||
|
||||
@staticmethod
|
||||
@callback
|
||||
@override
|
||||
def async_get_options_flow(
|
||||
config_entry: ConfigEntry,
|
||||
) -> SchemaOptionsFlowHandler:
|
||||
|
||||
@@ -4,7 +4,7 @@ from asyncio import timeout
|
||||
from dataclasses import dataclass
|
||||
from datetime import timedelta
|
||||
import logging
|
||||
from typing import Any, Final, cast
|
||||
from typing import Any, Final, cast, override
|
||||
|
||||
from aemet_opendata.const import (
|
||||
AOD_CONDITION,
|
||||
@@ -60,6 +60,7 @@ class WeatherUpdateCoordinator(DataUpdateCoordinator):
|
||||
update_interval=WEATHER_UPDATE_INTERVAL,
|
||||
)
|
||||
|
||||
@override
|
||||
async def _async_update_data(self) -> dict[str, Any]:
|
||||
"""Update coordinator data."""
|
||||
async with timeout(API_TIMEOUT):
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
"""Support for the AEMET OpenData images."""
|
||||
|
||||
from typing import Final
|
||||
from typing import Final, override
|
||||
|
||||
from aemet_opendata.const import AOD_DATETIME, AOD_IMG_BYTES, AOD_IMG_TYPE, AOD_RADAR
|
||||
from aemet_opendata.helpers import dict_nested_value
|
||||
@@ -68,6 +68,7 @@ class AemetImage(AemetEntity, ImageEntity):
|
||||
self._async_update_attrs()
|
||||
|
||||
@callback
|
||||
@override
|
||||
def _handle_coordinator_update(self) -> None:
|
||||
"""Update attributes when the coordinator updates."""
|
||||
self._async_update_attrs()
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
from collections.abc import Callable
|
||||
from dataclasses import dataclass
|
||||
from datetime import datetime
|
||||
from typing import Final
|
||||
from typing import Final, override
|
||||
|
||||
from aemet_opendata.const import (
|
||||
AOD_CONDITION,
|
||||
@@ -399,6 +399,7 @@ class AemetSensor(AemetEntity, SensorEntity):
|
||||
self._attr_unique_id = f"{unique_id}-{description.key}"
|
||||
|
||||
@property
|
||||
@override
|
||||
def native_value(self):
|
||||
"""Return the state of the device."""
|
||||
value = self.get_aemet_value(self.entity_description.keys)
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
"""Support for the AEMET OpenData service."""
|
||||
|
||||
from typing import override
|
||||
|
||||
from aemet_opendata.const import (
|
||||
AOD_CONDITION,
|
||||
AOD_FORECAST_DAILY,
|
||||
@@ -74,47 +76,56 @@ class AemetWeather(
|
||||
self._attr_unique_id = unique_id
|
||||
|
||||
@property
|
||||
@override
|
||||
def condition(self) -> str | None:
|
||||
"""Return the current condition."""
|
||||
cond = self.get_aemet_value([AOD_WEATHER, AOD_CONDITION])
|
||||
return CONDITIONS_MAP.get(cond)
|
||||
|
||||
@callback
|
||||
@override
|
||||
def _async_forecast_daily(self) -> list[Forecast]:
|
||||
"""Return the daily forecast in native units."""
|
||||
return self.get_aemet_forecast(AOD_FORECAST_DAILY)
|
||||
|
||||
@callback
|
||||
@override
|
||||
def _async_forecast_hourly(self) -> list[Forecast]:
|
||||
"""Return the hourly forecast in native units."""
|
||||
return self.get_aemet_forecast(AOD_FORECAST_HOURLY)
|
||||
|
||||
@property
|
||||
@override
|
||||
def humidity(self) -> float | None:
|
||||
"""Return the humidity."""
|
||||
return self.get_aemet_value([AOD_WEATHER, AOD_HUMIDITY])
|
||||
|
||||
@property
|
||||
@override
|
||||
def native_pressure(self) -> float | None:
|
||||
"""Return the pressure."""
|
||||
return self.get_aemet_value([AOD_WEATHER, AOD_PRESSURE])
|
||||
|
||||
@property
|
||||
@override
|
||||
def native_temperature(self) -> float | None:
|
||||
"""Return the temperature."""
|
||||
return self.get_aemet_value([AOD_WEATHER, AOD_TEMP])
|
||||
|
||||
@property
|
||||
@override
|
||||
def wind_bearing(self) -> float | None:
|
||||
"""Return the wind bearing."""
|
||||
return self.get_aemet_value([AOD_WEATHER, AOD_WIND_DIRECTION])
|
||||
|
||||
@property
|
||||
@override
|
||||
def native_wind_gust_speed(self) -> float | None:
|
||||
"""Return the wind gust speed in native units."""
|
||||
return self.get_aemet_value([AOD_WEATHER, AOD_WIND_SPEED_MAX])
|
||||
|
||||
@property
|
||||
@override
|
||||
def native_wind_speed(self) -> float | None:
|
||||
"""Return the wind speed."""
|
||||
return self.get_aemet_value([AOD_WEATHER, AOD_WIND_SPEED])
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
"""Config flow for AfterShip integration."""
|
||||
|
||||
import logging
|
||||
from typing import Any
|
||||
from typing import Any, override
|
||||
|
||||
from pyaftership import AfterShip, AfterShipException
|
||||
import voluptuous as vol
|
||||
@@ -20,6 +20,7 @@ class AfterShipConfigFlow(ConfigFlow, domain=DOMAIN):
|
||||
|
||||
VERSION = 1
|
||||
|
||||
@override
|
||||
async def async_step_user(
|
||||
self, user_input: dict[str, Any] | None = None
|
||||
) -> ConfigFlowResult:
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
"""Support for non-delivered packages recorded in AfterShip."""
|
||||
|
||||
import logging
|
||||
from typing import Any, Final
|
||||
from typing import Any, Final, override
|
||||
|
||||
from pyaftership import AfterShip, AfterShipException
|
||||
|
||||
@@ -96,15 +96,18 @@ class AfterShipSensor(SensorEntity):
|
||||
self._attr_name = name
|
||||
|
||||
@property
|
||||
@override
|
||||
def native_value(self) -> int | None:
|
||||
"""Return the state of the sensor."""
|
||||
return self._state
|
||||
|
||||
@property
|
||||
@override
|
||||
def extra_state_attributes(self) -> dict[str, str]:
|
||||
"""Return attributes for the sensor."""
|
||||
return self._attributes
|
||||
|
||||
@override
|
||||
async def async_added_to_hass(self) -> None:
|
||||
"""Register callbacks."""
|
||||
self.async_on_remove(
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
"""Support for Agent DVR Alarm Control Panels."""
|
||||
|
||||
from typing import override
|
||||
|
||||
from homeassistant.components.alarm_control_panel import (
|
||||
AlarmControlPanelEntity,
|
||||
AlarmControlPanelEntityFeature,
|
||||
@@ -70,23 +72,27 @@ class AgentBaseStation(AlarmControlPanelEntity):
|
||||
else:
|
||||
self._attr_alarm_state = AlarmControlPanelState.DISARMED
|
||||
|
||||
@override
|
||||
async def async_alarm_disarm(self, code: str | None = None) -> None:
|
||||
"""Send disarm command."""
|
||||
await self._client.disarm()
|
||||
self._attr_alarm_state = AlarmControlPanelState.DISARMED
|
||||
|
||||
@override
|
||||
async def async_alarm_arm_away(self, code: str | None = None) -> None:
|
||||
"""Send arm away command. Uses custom mode."""
|
||||
await self._client.arm()
|
||||
await self._client.set_active_profile(CONF_AWAY_MODE_NAME)
|
||||
self._attr_alarm_state = AlarmControlPanelState.ARMED_AWAY
|
||||
|
||||
@override
|
||||
async def async_alarm_arm_home(self, code: str | None = None) -> None:
|
||||
"""Send arm home command. Uses custom mode."""
|
||||
await self._client.arm()
|
||||
await self._client.set_active_profile(CONF_HOME_MODE_NAME)
|
||||
self._attr_alarm_state = AlarmControlPanelState.ARMED_HOME
|
||||
|
||||
@override
|
||||
async def async_alarm_arm_night(self, code: str | None = None) -> None:
|
||||
"""Send arm night command. Uses custom mode."""
|
||||
await self._client.arm()
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
from datetime import timedelta
|
||||
import logging
|
||||
from typing import override
|
||||
|
||||
from agent import AgentError
|
||||
|
||||
@@ -95,6 +96,7 @@ class AgentCamera(MjpegCamera):
|
||||
}
|
||||
|
||||
@property
|
||||
@override
|
||||
def is_recording(self) -> bool:
|
||||
"""Return whether the monitor is recording."""
|
||||
return self.device.recording
|
||||
@@ -115,11 +117,13 @@ class AgentCamera(MjpegCamera):
|
||||
return self.device.connected
|
||||
|
||||
@property
|
||||
@override
|
||||
def is_on(self) -> bool:
|
||||
"""Return true if on."""
|
||||
return self.device.online
|
||||
|
||||
@property
|
||||
@override
|
||||
def motion_detection_enabled(self) -> bool:
|
||||
"""Return the camera motion detection status."""
|
||||
return self.device.detector_active
|
||||
@@ -132,10 +136,12 @@ class AgentCamera(MjpegCamera):
|
||||
"""Disable alerts."""
|
||||
await self.device.alerts_off()
|
||||
|
||||
@override
|
||||
async def async_enable_motion_detection(self) -> None:
|
||||
"""Enable motion detection."""
|
||||
await self.device.detector_on()
|
||||
|
||||
@override
|
||||
async def async_disable_motion_detection(self) -> None:
|
||||
"""Disable motion detection."""
|
||||
await self.device.detector_off()
|
||||
@@ -148,6 +154,7 @@ class AgentCamera(MjpegCamera):
|
||||
"""Stop recording."""
|
||||
await self.device.record_stop()
|
||||
|
||||
@override
|
||||
async def async_turn_on(self) -> None:
|
||||
"""Enable the camera."""
|
||||
await self.device.enable()
|
||||
@@ -156,6 +163,7 @@ class AgentCamera(MjpegCamera):
|
||||
"""Take a snapshot."""
|
||||
await self.device.snapshot()
|
||||
|
||||
@override
|
||||
async def async_turn_off(self) -> None:
|
||||
"""Disable the camera."""
|
||||
await self.device.disable()
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
"""Config flow to configure Agent devices."""
|
||||
|
||||
from contextlib import suppress
|
||||
from typing import Any
|
||||
from typing import Any, override
|
||||
|
||||
from agent import AgentConnectionError, AgentError
|
||||
from agent.a import Agent
|
||||
@@ -20,6 +20,7 @@ DEFAULT_PORT = 8090
|
||||
class AgentFlowHandler(ConfigFlow, domain=DOMAIN):
|
||||
"""Handle an Agent config flow."""
|
||||
|
||||
@override
|
||||
async def async_step_user(
|
||||
self, user_input: dict[str, Any] | None = None
|
||||
) -> ConfigFlowResult:
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
from collections.abc import AsyncGenerator
|
||||
import contextlib
|
||||
from typing import final
|
||||
from typing import final, override
|
||||
|
||||
from propcache.api import cached_property
|
||||
|
||||
@@ -30,6 +30,7 @@ class AITaskEntity(RestoreEntity):
|
||||
|
||||
@property
|
||||
@final
|
||||
@override
|
||||
def state(self) -> str | None:
|
||||
"""Return the state of the entity."""
|
||||
if self.__last_activity is None:
|
||||
@@ -37,10 +38,12 @@ class AITaskEntity(RestoreEntity):
|
||||
return self.__last_activity
|
||||
|
||||
@cached_property
|
||||
@override
|
||||
def supported_features(self) -> AITaskEntityFeature:
|
||||
"""Flag supported features."""
|
||||
return self._attr_supported_features
|
||||
|
||||
@override
|
||||
async def async_internal_added_to_hass(self) -> None:
|
||||
"""Call when the entity is added to hass."""
|
||||
await super().async_internal_added_to_hass()
|
||||
|
||||
@@ -6,7 +6,7 @@ import io
|
||||
import mimetypes
|
||||
from pathlib import Path
|
||||
import tempfile
|
||||
from typing import Any
|
||||
from typing import Any, override
|
||||
|
||||
import voluptuous as vol
|
||||
|
||||
@@ -259,6 +259,7 @@ class GenDataTask:
|
||||
llm_api: llm.API | None = None
|
||||
"""API to provide to the LLM."""
|
||||
|
||||
@override
|
||||
def __str__(self) -> str:
|
||||
"""Return task as a string."""
|
||||
return f"<GenDataTask {self.name}: {id(self)}>"
|
||||
@@ -295,6 +296,7 @@ class GenImageTask:
|
||||
attachments: list[conversation.Attachment] | None = None
|
||||
"""List of attachments to go along the instructions."""
|
||||
|
||||
@override
|
||||
def __str__(self) -> str:
|
||||
"""Return task as a string."""
|
||||
return f"<GenImageTask {self.name}: {id(self)}>"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
"""Config flow for Aidot integration."""
|
||||
|
||||
from typing import Any
|
||||
from typing import Any, override
|
||||
|
||||
from aidot.client import AidotClient
|
||||
from aidot.const import CONF_ID, DEFAULT_COUNTRY_CODE, SUPPORTED_COUNTRY_CODES
|
||||
@@ -34,6 +34,7 @@ DATA_SCHEMA = vol.Schema(
|
||||
class AidotConfigFlow(ConfigFlow, domain=DOMAIN):
|
||||
"""Handle aidot config flow."""
|
||||
|
||||
@override
|
||||
async def async_step_user(
|
||||
self, user_input: dict[str, Any] | None = None
|
||||
) -> ConfigFlowResult:
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
from datetime import timedelta
|
||||
import logging
|
||||
from typing import override
|
||||
|
||||
from aidot.client import AidotClient
|
||||
from aidot.const import (
|
||||
@@ -48,6 +49,7 @@ class AidotDeviceUpdateCoordinator(DataUpdateCoordinator[DeviceStatusData]):
|
||||
)
|
||||
self.device_client = device_client
|
||||
|
||||
@override
|
||||
async def _async_setup(self) -> None:
|
||||
"""Set up the coordinator."""
|
||||
self.device_client.on_status_update = self._handle_status_update
|
||||
@@ -56,6 +58,7 @@ class AidotDeviceUpdateCoordinator(DataUpdateCoordinator[DeviceStatusData]):
|
||||
"""Handle status callback."""
|
||||
self.async_set_updated_data(status)
|
||||
|
||||
@override
|
||||
async def _async_update_data(self) -> DeviceStatusData:
|
||||
"""Return current status."""
|
||||
return self.device_client.status
|
||||
@@ -86,6 +89,7 @@ class AidotDeviceManagerCoordinator(DataUpdateCoordinator[None]):
|
||||
self.client.set_token_fresh_cb(self.token_fresh_cb)
|
||||
self.device_coordinators: dict[str, AidotDeviceUpdateCoordinator] = {}
|
||||
|
||||
@override
|
||||
async def _async_setup(self) -> None:
|
||||
"""Set up the coordinator."""
|
||||
try:
|
||||
@@ -93,6 +97,7 @@ class AidotDeviceManagerCoordinator(DataUpdateCoordinator[None]):
|
||||
except AidotUserOrPassIncorrect as error:
|
||||
raise ConfigEntryError from error
|
||||
|
||||
@override
|
||||
async def _async_update_data(self) -> None:
|
||||
"""Update data async."""
|
||||
try:
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
"""Support for Aidot lights."""
|
||||
|
||||
from typing import Any
|
||||
from typing import Any, override
|
||||
|
||||
from homeassistant.components.light import (
|
||||
ATTR_BRIGHTNESS,
|
||||
@@ -78,16 +78,19 @@ class AidotLight(CoordinatorEntity[AidotDeviceUpdateCoordinator], LightEntity):
|
||||
self._attr_rgbw_color = self.coordinator.data.rgbw
|
||||
|
||||
@property
|
||||
@override
|
||||
def available(self) -> bool:
|
||||
"""Return if entity is available."""
|
||||
return super().available and self.coordinator.data.online
|
||||
|
||||
@callback
|
||||
@override
|
||||
def _handle_coordinator_update(self) -> None:
|
||||
"""Update."""
|
||||
self._update_status()
|
||||
super()._handle_coordinator_update()
|
||||
|
||||
@override
|
||||
async def async_turn_on(self, **kwargs: Any) -> None:
|
||||
"""Turn the light on, applying brightness, color temperature, RGBW, or plain on."""
|
||||
if ATTR_BRIGHTNESS in kwargs:
|
||||
@@ -114,6 +117,7 @@ class AidotLight(CoordinatorEntity[AidotDeviceUpdateCoordinator], LightEntity):
|
||||
self._attr_is_on = True
|
||||
self.async_write_ha_state()
|
||||
|
||||
@override
|
||||
async def async_turn_off(self, **kwargs: Any) -> None:
|
||||
"""Turn the light off."""
|
||||
await self.coordinator.device_client.async_turn_off()
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
from datetime import timedelta
|
||||
import logging
|
||||
from typing import Final, final
|
||||
from typing import Final, final, override
|
||||
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.const import CONCENTRATION_MICROGRAMS_PER_CUBIC_METER
|
||||
@@ -131,6 +131,7 @@ class AirQualityEntity(Entity):
|
||||
|
||||
@final
|
||||
@property
|
||||
@override
|
||||
def state_attributes(self) -> dict[str, str | int | float]:
|
||||
"""Return the state attributes."""
|
||||
data: dict[str, str | int | float] = {}
|
||||
@@ -142,11 +143,13 @@ class AirQualityEntity(Entity):
|
||||
return data
|
||||
|
||||
@property
|
||||
@override
|
||||
def state(self) -> StateType:
|
||||
"""Return the current state."""
|
||||
return self.particulate_matter_2_5
|
||||
|
||||
@property
|
||||
@override
|
||||
def unit_of_measurement(self) -> str:
|
||||
"""Return the unit of measurement of this entity."""
|
||||
return CONCENTRATION_MICROGRAMS_PER_CUBIC_METER
|
||||
|
||||
@@ -279,7 +279,7 @@
|
||||
"title": "Air Quality",
|
||||
"triggers": {
|
||||
"co2_changed": {
|
||||
"description": "Triggers after one or more carbon dioxide levels change.",
|
||||
"description": "Triggers when one or more carbon dioxide levels change.",
|
||||
"fields": {
|
||||
"threshold": {
|
||||
"name": "[%key:component::air_quality::common::trigger_threshold_name%]"
|
||||
@@ -288,7 +288,7 @@
|
||||
"name": "Carbon dioxide level changed"
|
||||
},
|
||||
"co2_crossed_threshold": {
|
||||
"description": "Triggers after one or more carbon dioxide levels cross a threshold.",
|
||||
"description": "Triggers when one or more carbon dioxide levels cross a threshold.",
|
||||
"fields": {
|
||||
"behavior": {
|
||||
"name": "[%key:component::air_quality::common::trigger_behavior_name%]"
|
||||
@@ -303,7 +303,7 @@
|
||||
"name": "Carbon dioxide level crossed threshold"
|
||||
},
|
||||
"co_changed": {
|
||||
"description": "Triggers after one or more carbon monoxide levels change.",
|
||||
"description": "Triggers when one or more carbon monoxide levels change.",
|
||||
"fields": {
|
||||
"threshold": {
|
||||
"name": "[%key:component::air_quality::common::trigger_threshold_name%]"
|
||||
@@ -312,7 +312,7 @@
|
||||
"name": "Carbon monoxide level changed"
|
||||
},
|
||||
"co_cleared": {
|
||||
"description": "Triggers after one or more carbon monoxide sensors stop detecting carbon monoxide.",
|
||||
"description": "Triggers when one or more carbon monoxide sensors stop detecting carbon monoxide.",
|
||||
"fields": {
|
||||
"behavior": {
|
||||
"name": "[%key:component::air_quality::common::trigger_behavior_name%]"
|
||||
@@ -324,7 +324,7 @@
|
||||
"name": "Carbon monoxide cleared"
|
||||
},
|
||||
"co_crossed_threshold": {
|
||||
"description": "Triggers after one or more carbon monoxide levels cross a threshold.",
|
||||
"description": "Triggers when one or more carbon monoxide levels cross a threshold.",
|
||||
"fields": {
|
||||
"behavior": {
|
||||
"name": "[%key:component::air_quality::common::trigger_behavior_name%]"
|
||||
@@ -339,7 +339,7 @@
|
||||
"name": "Carbon monoxide level crossed threshold"
|
||||
},
|
||||
"co_detected": {
|
||||
"description": "Triggers after one or more carbon monoxide sensors start detecting carbon monoxide.",
|
||||
"description": "Triggers when one or more carbon monoxide sensors start detecting carbon monoxide.",
|
||||
"fields": {
|
||||
"behavior": {
|
||||
"name": "[%key:component::air_quality::common::trigger_behavior_name%]"
|
||||
@@ -351,7 +351,7 @@
|
||||
"name": "Carbon monoxide detected"
|
||||
},
|
||||
"gas_cleared": {
|
||||
"description": "Triggers after one or more gas sensors stop detecting gas.",
|
||||
"description": "Triggers when one or more gas sensors stop detecting gas.",
|
||||
"fields": {
|
||||
"behavior": {
|
||||
"name": "[%key:component::air_quality::common::trigger_behavior_name%]"
|
||||
@@ -363,7 +363,7 @@
|
||||
"name": "Gas cleared"
|
||||
},
|
||||
"gas_detected": {
|
||||
"description": "Triggers after one or more gas sensors start detecting gas.",
|
||||
"description": "Triggers when one or more gas sensors start detecting gas.",
|
||||
"fields": {
|
||||
"behavior": {
|
||||
"name": "[%key:component::air_quality::common::trigger_behavior_name%]"
|
||||
@@ -375,7 +375,7 @@
|
||||
"name": "Gas detected"
|
||||
},
|
||||
"n2o_changed": {
|
||||
"description": "Triggers after one or more nitrous oxide levels change.",
|
||||
"description": "Triggers when one or more nitrous oxide levels change.",
|
||||
"fields": {
|
||||
"threshold": {
|
||||
"name": "[%key:component::air_quality::common::trigger_threshold_name%]"
|
||||
@@ -384,7 +384,7 @@
|
||||
"name": "Nitrous oxide level changed"
|
||||
},
|
||||
"n2o_crossed_threshold": {
|
||||
"description": "Triggers after one or more nitrous oxide levels cross a threshold.",
|
||||
"description": "Triggers when one or more nitrous oxide levels cross a threshold.",
|
||||
"fields": {
|
||||
"behavior": {
|
||||
"name": "[%key:component::air_quality::common::trigger_behavior_name%]"
|
||||
@@ -399,7 +399,7 @@
|
||||
"name": "Nitrous oxide level crossed threshold"
|
||||
},
|
||||
"no2_changed": {
|
||||
"description": "Triggers after one or more nitrogen dioxide levels change.",
|
||||
"description": "Triggers when one or more nitrogen dioxide levels change.",
|
||||
"fields": {
|
||||
"threshold": {
|
||||
"name": "[%key:component::air_quality::common::trigger_threshold_name%]"
|
||||
@@ -408,7 +408,7 @@
|
||||
"name": "Nitrogen dioxide level changed"
|
||||
},
|
||||
"no2_crossed_threshold": {
|
||||
"description": "Triggers after one or more nitrogen dioxide levels cross a threshold.",
|
||||
"description": "Triggers when one or more nitrogen dioxide levels cross a threshold.",
|
||||
"fields": {
|
||||
"behavior": {
|
||||
"name": "[%key:component::air_quality::common::trigger_behavior_name%]"
|
||||
@@ -423,7 +423,7 @@
|
||||
"name": "Nitrogen dioxide level crossed threshold"
|
||||
},
|
||||
"no_changed": {
|
||||
"description": "Triggers after one or more nitrogen monoxide levels change.",
|
||||
"description": "Triggers when one or more nitrogen monoxide levels change.",
|
||||
"fields": {
|
||||
"threshold": {
|
||||
"name": "[%key:component::air_quality::common::trigger_threshold_name%]"
|
||||
@@ -432,7 +432,7 @@
|
||||
"name": "Nitrogen monoxide level changed"
|
||||
},
|
||||
"no_crossed_threshold": {
|
||||
"description": "Triggers after one or more nitrogen monoxide levels cross a threshold.",
|
||||
"description": "Triggers when one or more nitrogen monoxide levels cross a threshold.",
|
||||
"fields": {
|
||||
"behavior": {
|
||||
"name": "[%key:component::air_quality::common::trigger_behavior_name%]"
|
||||
@@ -447,7 +447,7 @@
|
||||
"name": "Nitrogen monoxide level crossed threshold"
|
||||
},
|
||||
"ozone_changed": {
|
||||
"description": "Triggers after one or more ozone levels change.",
|
||||
"description": "Triggers when one or more ozone levels change.",
|
||||
"fields": {
|
||||
"threshold": {
|
||||
"name": "[%key:component::air_quality::common::trigger_threshold_name%]"
|
||||
@@ -456,7 +456,7 @@
|
||||
"name": "Ozone level changed"
|
||||
},
|
||||
"ozone_crossed_threshold": {
|
||||
"description": "Triggers after one or more ozone levels cross a threshold.",
|
||||
"description": "Triggers when one or more ozone levels cross a threshold.",
|
||||
"fields": {
|
||||
"behavior": {
|
||||
"name": "[%key:component::air_quality::common::trigger_behavior_name%]"
|
||||
@@ -471,7 +471,7 @@
|
||||
"name": "Ozone level crossed threshold"
|
||||
},
|
||||
"pm10_changed": {
|
||||
"description": "Triggers after one or more PM10 levels change.",
|
||||
"description": "Triggers when one or more PM10 levels change.",
|
||||
"fields": {
|
||||
"threshold": {
|
||||
"name": "[%key:component::air_quality::common::trigger_threshold_name%]"
|
||||
@@ -480,7 +480,7 @@
|
||||
"name": "PM10 level changed"
|
||||
},
|
||||
"pm10_crossed_threshold": {
|
||||
"description": "Triggers after one or more PM10 levels cross a threshold.",
|
||||
"description": "Triggers when one or more PM10 levels cross a threshold.",
|
||||
"fields": {
|
||||
"behavior": {
|
||||
"name": "[%key:component::air_quality::common::trigger_behavior_name%]"
|
||||
@@ -495,7 +495,7 @@
|
||||
"name": "PM10 level crossed threshold"
|
||||
},
|
||||
"pm1_changed": {
|
||||
"description": "Triggers after one or more PM1 levels change.",
|
||||
"description": "Triggers when one or more PM1 levels change.",
|
||||
"fields": {
|
||||
"threshold": {
|
||||
"name": "[%key:component::air_quality::common::trigger_threshold_name%]"
|
||||
@@ -504,7 +504,7 @@
|
||||
"name": "PM1 level changed"
|
||||
},
|
||||
"pm1_crossed_threshold": {
|
||||
"description": "Triggers after one or more PM1 levels cross a threshold.",
|
||||
"description": "Triggers when one or more PM1 levels cross a threshold.",
|
||||
"fields": {
|
||||
"behavior": {
|
||||
"name": "[%key:component::air_quality::common::trigger_behavior_name%]"
|
||||
@@ -519,7 +519,7 @@
|
||||
"name": "PM1 level crossed threshold"
|
||||
},
|
||||
"pm25_changed": {
|
||||
"description": "Triggers after one or more PM2.5 levels change.",
|
||||
"description": "Triggers when one or more PM2.5 levels change.",
|
||||
"fields": {
|
||||
"threshold": {
|
||||
"name": "[%key:component::air_quality::common::trigger_threshold_name%]"
|
||||
@@ -528,7 +528,7 @@
|
||||
"name": "PM2.5 level changed"
|
||||
},
|
||||
"pm25_crossed_threshold": {
|
||||
"description": "Triggers after one or more PM2.5 levels cross a threshold.",
|
||||
"description": "Triggers when one or more PM2.5 levels cross a threshold.",
|
||||
"fields": {
|
||||
"behavior": {
|
||||
"name": "[%key:component::air_quality::common::trigger_behavior_name%]"
|
||||
@@ -543,7 +543,7 @@
|
||||
"name": "PM2.5 level crossed threshold"
|
||||
},
|
||||
"pm4_changed": {
|
||||
"description": "Triggers after one or more PM4 levels change.",
|
||||
"description": "Triggers when one or more PM4 levels change.",
|
||||
"fields": {
|
||||
"threshold": {
|
||||
"name": "[%key:component::air_quality::common::trigger_threshold_name%]"
|
||||
@@ -552,7 +552,7 @@
|
||||
"name": "PM4 level changed"
|
||||
},
|
||||
"pm4_crossed_threshold": {
|
||||
"description": "Triggers after one or more PM4 levels cross a threshold.",
|
||||
"description": "Triggers when one or more PM4 levels cross a threshold.",
|
||||
"fields": {
|
||||
"behavior": {
|
||||
"name": "[%key:component::air_quality::common::trigger_behavior_name%]"
|
||||
@@ -567,7 +567,7 @@
|
||||
"name": "PM4 level crossed threshold"
|
||||
},
|
||||
"smoke_cleared": {
|
||||
"description": "Triggers after one or more smoke sensors stop detecting smoke.",
|
||||
"description": "Triggers when one or more smoke sensors stop detecting smoke.",
|
||||
"fields": {
|
||||
"behavior": {
|
||||
"name": "[%key:component::air_quality::common::trigger_behavior_name%]"
|
||||
@@ -579,7 +579,7 @@
|
||||
"name": "Smoke cleared"
|
||||
},
|
||||
"smoke_detected": {
|
||||
"description": "Triggers after one or more smoke sensors start detecting smoke.",
|
||||
"description": "Triggers when one or more smoke sensors start detecting smoke.",
|
||||
"fields": {
|
||||
"behavior": {
|
||||
"name": "[%key:component::air_quality::common::trigger_behavior_name%]"
|
||||
@@ -591,7 +591,7 @@
|
||||
"name": "Smoke detected"
|
||||
},
|
||||
"so2_changed": {
|
||||
"description": "Triggers after one or more sulphur dioxide levels change.",
|
||||
"description": "Triggers when one or more sulphur dioxide levels change.",
|
||||
"fields": {
|
||||
"threshold": {
|
||||
"name": "[%key:component::air_quality::common::trigger_threshold_name%]"
|
||||
@@ -600,7 +600,7 @@
|
||||
"name": "Sulphur dioxide level changed"
|
||||
},
|
||||
"so2_crossed_threshold": {
|
||||
"description": "Triggers after one or more sulphur dioxide levels cross a threshold.",
|
||||
"description": "Triggers when one or more sulphur dioxide levels cross a threshold.",
|
||||
"fields": {
|
||||
"behavior": {
|
||||
"name": "[%key:component::air_quality::common::trigger_behavior_name%]"
|
||||
@@ -615,7 +615,7 @@
|
||||
"name": "Sulphur dioxide level crossed threshold"
|
||||
},
|
||||
"voc_changed": {
|
||||
"description": "Triggers after one or more volatile organic compound levels change.",
|
||||
"description": "Triggers when one or more volatile organic compound levels change.",
|
||||
"fields": {
|
||||
"threshold": {
|
||||
"name": "[%key:component::air_quality::common::trigger_threshold_name%]"
|
||||
@@ -624,7 +624,7 @@
|
||||
"name": "Volatile organic compounds level changed"
|
||||
},
|
||||
"voc_crossed_threshold": {
|
||||
"description": "Triggers after one or more volatile organic compounds levels cross a threshold.",
|
||||
"description": "Triggers when one or more volatile organic compounds levels cross a threshold.",
|
||||
"fields": {
|
||||
"behavior": {
|
||||
"name": "[%key:component::air_quality::common::trigger_behavior_name%]"
|
||||
@@ -639,7 +639,7 @@
|
||||
"name": "Volatile organic compounds level crossed threshold"
|
||||
},
|
||||
"voc_ratio_changed": {
|
||||
"description": "Triggers after one or more volatile organic compound ratios change.",
|
||||
"description": "Triggers when one or more volatile organic compound ratios change.",
|
||||
"fields": {
|
||||
"threshold": {
|
||||
"name": "[%key:component::air_quality::common::trigger_threshold_name%]"
|
||||
@@ -648,7 +648,7 @@
|
||||
"name": "Volatile organic compounds ratio changed"
|
||||
},
|
||||
"voc_ratio_crossed_threshold": {
|
||||
"description": "Triggers after one or more volatile organic compounds ratios cross a threshold.",
|
||||
"description": "Triggers when one or more volatile organic compounds ratios cross a threshold.",
|
||||
"fields": {
|
||||
"behavior": {
|
||||
"name": "[%key:component::air_quality::common::trigger_behavior_name%]"
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
from collections.abc import Awaitable, Callable
|
||||
from dataclasses import dataclass
|
||||
from typing import override
|
||||
|
||||
from airgradient import AirGradientClient, ConfigurationControl
|
||||
|
||||
@@ -103,6 +104,7 @@ class AirGradientButton(AirGradientEntity, ButtonEntity):
|
||||
self._attr_unique_id = f"{coordinator.serial_number}-{description.key}"
|
||||
|
||||
@exception_handler
|
||||
@override
|
||||
async def async_press(self) -> None:
|
||||
"""Press the button."""
|
||||
await self.entity_description.press_fn(self.coordinator.client)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
"""Config flow for Airgradient."""
|
||||
|
||||
from collections.abc import Mapping
|
||||
from typing import Any
|
||||
from typing import Any, override
|
||||
|
||||
from airgradient import (
|
||||
AirGradientClient,
|
||||
@@ -42,6 +42,7 @@ class AirGradientConfigFlow(ConfigFlow, domain=DOMAIN):
|
||||
if config.configuration_control is ConfigurationControl.NOT_INITIALIZED:
|
||||
await self.client.set_configuration_control(ConfigurationControl.LOCAL)
|
||||
|
||||
@override
|
||||
async def async_step_zeroconf(
|
||||
self, discovery_info: ZeroconfServiceInfo
|
||||
) -> ConfigFlowResult:
|
||||
@@ -83,6 +84,7 @@ class AirGradientConfigFlow(ConfigFlow, domain=DOMAIN):
|
||||
},
|
||||
)
|
||||
|
||||
@override
|
||||
async def async_step_user(
|
||||
self, user_input: dict[str, Any] | None = None
|
||||
) -> ConfigFlowResult:
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
from dataclasses import dataclass
|
||||
from datetime import timedelta
|
||||
from typing import override
|
||||
|
||||
from airgradient import AirGradientClient, AirGradientError, Config, Measures
|
||||
|
||||
@@ -47,6 +48,7 @@ class AirGradientCoordinator(DataUpdateCoordinator[AirGradientData]):
|
||||
assert self.config_entry.unique_id
|
||||
self.serial_number = self.config_entry.unique_id
|
||||
|
||||
@override
|
||||
async def _async_setup(self) -> None:
|
||||
"""Set up the coordinator."""
|
||||
try:
|
||||
@@ -60,6 +62,7 @@ class AirGradientCoordinator(DataUpdateCoordinator[AirGradientData]):
|
||||
translation_placeholders={"error": str(error)},
|
||||
) from error
|
||||
|
||||
@override
|
||||
async def _async_update_data(self) -> AirGradientData:
|
||||
try:
|
||||
measures = await self.client.get_current_measures()
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
from collections.abc import Awaitable, Callable
|
||||
from dataclasses import dataclass
|
||||
from typing import override
|
||||
|
||||
from airgradient import AirGradientClient, Config
|
||||
from airgradient.models import ConfigurationControl
|
||||
@@ -119,11 +120,13 @@ class AirGradientNumber(AirGradientEntity, NumberEntity):
|
||||
self._attr_unique_id = f"{coordinator.serial_number}-{description.key}"
|
||||
|
||||
@property
|
||||
@override
|
||||
def native_value(self) -> int | None:
|
||||
"""Return the state of the number."""
|
||||
return self.entity_description.value_fn(self.coordinator.data.config)
|
||||
|
||||
@exception_handler
|
||||
@override
|
||||
async def async_set_native_value(self, value: float) -> None:
|
||||
"""Set the selected value."""
|
||||
await self.entity_description.set_value_fn(self.coordinator.client, int(value))
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
from collections.abc import Awaitable, Callable
|
||||
from dataclasses import dataclass
|
||||
from typing import override
|
||||
|
||||
from airgradient import AirGradientClient, Config
|
||||
from airgradient.models import ConfigurationControl, LedBarMode, TemperatureUnit
|
||||
@@ -215,11 +216,13 @@ class AirGradientSelect(AirGradientEntity, SelectEntity):
|
||||
self._attr_unique_id = f"{coordinator.serial_number}-{description.key}"
|
||||
|
||||
@property
|
||||
@override
|
||||
def current_option(self) -> str | None:
|
||||
"""Return the state of the select."""
|
||||
return self.entity_description.value_fn(self.coordinator.data.config)
|
||||
|
||||
@exception_handler
|
||||
@override
|
||||
async def async_select_option(self, option: str) -> None:
|
||||
"""Change the selected option."""
|
||||
await self.entity_description.set_value_fn(self.coordinator.client, option)
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
from collections.abc import Callable
|
||||
from dataclasses import dataclass
|
||||
from typing import override
|
||||
|
||||
from airgradient import Config
|
||||
from airgradient.models import (
|
||||
@@ -295,6 +296,7 @@ class AirGradientMeasurementSensor(AirGradientSensor):
|
||||
entity_description: AirGradientMeasurementSensorEntityDescription
|
||||
|
||||
@property
|
||||
@override
|
||||
def native_value(self) -> StateType:
|
||||
"""Return the state of the sensor."""
|
||||
return self.entity_description.value_fn(self.coordinator.data.measures)
|
||||
@@ -318,6 +320,7 @@ class AirGradientConfigSensor(AirGradientSensor):
|
||||
)
|
||||
|
||||
@property
|
||||
@override
|
||||
def native_value(self) -> StateType:
|
||||
"""Return the state of the sensor."""
|
||||
return self.entity_description.value_fn(self.coordinator.data.config)
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
from collections.abc import Awaitable, Callable
|
||||
from dataclasses import dataclass
|
||||
from typing import Any
|
||||
from typing import Any, override
|
||||
|
||||
from airgradient import AirGradientClient, Config
|
||||
from airgradient.models import ConfigurationControl
|
||||
@@ -97,17 +97,20 @@ class AirGradientSwitch(AirGradientEntity, SwitchEntity):
|
||||
self._attr_unique_id = f"{coordinator.serial_number}-{description.key}"
|
||||
|
||||
@property
|
||||
@override
|
||||
def is_on(self) -> bool:
|
||||
"""Return the state of the switch."""
|
||||
return self.entity_description.value_fn(self.coordinator.data.config)
|
||||
|
||||
@exception_handler
|
||||
@override
|
||||
async def async_turn_on(self, **kwargs: Any) -> None:
|
||||
"""Turn the switch on."""
|
||||
await self.entity_description.set_value_fn(self.coordinator.client, True)
|
||||
await self.coordinator.async_request_refresh()
|
||||
|
||||
@exception_handler
|
||||
@override
|
||||
async def async_turn_off(self, **kwargs: Any) -> None:
|
||||
"""Turn the switch off."""
|
||||
await self.entity_description.set_value_fn(self.coordinator.client, False)
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
from datetime import timedelta
|
||||
import logging
|
||||
from typing import override
|
||||
|
||||
from airgradient import AirGradientConnectionError
|
||||
from propcache.api import cached_property
|
||||
@@ -42,20 +43,24 @@ class AirGradientUpdate(AirGradientEntity, UpdateEntity):
|
||||
self._attr_unique_id = f"{coordinator.serial_number}-update"
|
||||
|
||||
@cached_property
|
||||
@override
|
||||
def should_poll(self) -> bool:
|
||||
"""Return True because we need to poll the latest version."""
|
||||
return True
|
||||
|
||||
@property
|
||||
@override
|
||||
def installed_version(self) -> str:
|
||||
"""Return the installed version of the entity."""
|
||||
return self.coordinator.data.measures.firmware_version
|
||||
|
||||
@property
|
||||
@override
|
||||
def available(self) -> bool:
|
||||
"""Return if entity is available."""
|
||||
return super().available and self._attr_available
|
||||
|
||||
@override
|
||||
async def async_update(self) -> None:
|
||||
"""Update the entity."""
|
||||
try:
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
from asyncio import timeout
|
||||
from http import HTTPStatus
|
||||
from typing import Any
|
||||
from typing import Any, override
|
||||
|
||||
from aiohttp import ClientSession
|
||||
from airly import Airly
|
||||
@@ -26,6 +26,7 @@ class AirlyFlowHandler(ConfigFlow, domain=DOMAIN):
|
||||
|
||||
VERSION = 1
|
||||
|
||||
@override
|
||||
async def async_step_user(
|
||||
self, user_input: dict[str, Any] | None = None
|
||||
) -> ConfigFlowResult:
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user