mirror of
https://github.com/home-assistant/core.git
synced 2026-02-23 10:41:19 +01:00
Compare commits
56 Commits
hv_switch
...
Apollon77-
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
707c9dd0c6 | ||
|
|
629045ef74 | ||
|
|
452b0775ee | ||
|
|
dc5caf307b | ||
|
|
686bcb3199 | ||
|
|
047d5735d8 | ||
|
|
c3b0f7ba55 | ||
|
|
11f0cd690e | ||
|
|
048fbba36d | ||
|
|
a791797a6f | ||
|
|
aa2bb44f0e | ||
|
|
6ecbaa979a | ||
|
|
6115a4c1fb | ||
|
|
f6459453ed | ||
|
|
eeb7ce3725 | ||
|
|
f020948e2d | ||
|
|
0711176f9c | ||
|
|
cd26901386 | ||
|
|
3c1b7ada9a | ||
|
|
debf07e3fc | ||
|
|
541cc808b0 | ||
|
|
46b0eaecf6 | ||
|
|
35e770b998 | ||
|
|
ed9ad950d9 | ||
|
|
02058afb10 | ||
|
|
3f6bfa96fc | ||
|
|
430f064243 | ||
|
|
08adb88c6b | ||
|
|
14b6269dbf | ||
|
|
19b1fc6561 | ||
|
|
b6e83d22e3 | ||
|
|
7cd48ef079 | ||
|
|
2a03d95bcd | ||
|
|
e7e8c7a53a | ||
|
|
6ce28987ab | ||
|
|
da537ddb8b | ||
|
|
03f81e4a09 | ||
|
|
88bc6165b5 | ||
|
|
a1f35ed3c4 | ||
|
|
c15a804ab4 | ||
|
|
34f1c4cbe0 | ||
|
|
bf950e4916 | ||
|
|
47eba50b4a | ||
|
|
8ff06f3c72 | ||
|
|
d2918586f9 | ||
|
|
8c3e72b53d | ||
|
|
3143d9c4fd | ||
|
|
04621a2e58 | ||
|
|
9b6e6a688d | ||
|
|
2bf5f67ecd | ||
|
|
522f63cdab | ||
|
|
03f5e6d6a3 | ||
|
|
c2ba5d87d5 | ||
|
|
6a9fd67e05 | ||
|
|
69db5787ec | ||
|
|
8a38bace90 |
2
.github/workflows/ci.yaml
vendored
2
.github/workflows/ci.yaml
vendored
@@ -37,7 +37,7 @@ on:
|
||||
type: boolean
|
||||
|
||||
env:
|
||||
CACHE_VERSION: 2
|
||||
CACHE_VERSION: 3
|
||||
UV_CACHE_VERSION: 1
|
||||
MYPY_CACHE_VERSION: 1
|
||||
HA_SHORT_VERSION: "2026.3"
|
||||
|
||||
@@ -4,16 +4,16 @@
|
||||
"abort": {
|
||||
"fw_download_failed": "{firmware_name} firmware for your {model} failed to download. Make sure Home Assistant has internet access and try again.",
|
||||
"fw_install_failed": "{firmware_name} firmware failed to install, check Home Assistant logs for more information.",
|
||||
"not_hassio_thread": "The OpenThread Border Router add-on can only be installed with Home Assistant OS. If you would like to use the {model} as a Thread border router, please manually set up OpenThread Border Router to communicate with it.",
|
||||
"otbr_addon_already_running": "The OpenThread Border Router add-on is already running, it cannot be installed again.",
|
||||
"otbr_still_using_stick": "This {model} is in use by the OpenThread Border Router add-on. If you use the Thread network, make sure you have alternative border routers. Uninstall the add-on and try again.",
|
||||
"unsupported_firmware": "The radio firmware on your {model} could not be determined. Make sure that no other integration or add-on is currently trying to communicate with the device. If you are running Home Assistant OS in a virtual machine or in Docker, please make sure that permissions are set correctly for the device.",
|
||||
"not_hassio_thread": "The OpenThread Border Router app can only be installed with Home Assistant OS. If you would like to use the {model} as a Thread border router, please manually set up OpenThread Border Router to communicate with it.",
|
||||
"otbr_addon_already_running": "The OpenThread Border Router app is already running, it cannot be installed again.",
|
||||
"otbr_still_using_stick": "This {model} is in use by the OpenThread Border Router app. If you use the Thread network, make sure you have alternative border routers. Uninstall the app and try again.",
|
||||
"unsupported_firmware": "The radio firmware on your {model} could not be determined. Make sure that no other integration or app is currently trying to communicate with the device. If you are running Home Assistant OS in a virtual machine or in Docker, please make sure that permissions are set correctly for the device.",
|
||||
"zha_still_using_stick": "This {model} is in use by the Zigbee Home Automation integration. Please migrate your Zigbee network to another adapter or delete the integration and try again."
|
||||
},
|
||||
"progress": {
|
||||
"install_firmware": "Installing {firmware_name} firmware.\n\nDo not make any changes to your hardware or software until this finishes.",
|
||||
"install_otbr_addon": "Installing add-on",
|
||||
"start_otbr_addon": "Starting add-on"
|
||||
"install_otbr_addon": "Installing app",
|
||||
"start_otbr_addon": "Starting app"
|
||||
},
|
||||
"step": {
|
||||
"confirm_otbr": {
|
||||
@@ -34,7 +34,7 @@
|
||||
"title": "Updating adapter"
|
||||
},
|
||||
"otbr_failed": {
|
||||
"description": "The OpenThread Border Router add-on installation was unsuccessful. Ensure no other software is trying to communicate with the {model}, you have access to the Internet and can install other add-ons, and try again. Check the Supervisor logs if the problem persists.",
|
||||
"description": "The OpenThread Border Router app installation was unsuccessful. Ensure no other software is trying to communicate with the {model}, you have access to the Internet and can install other apps, and try again. Check the Supervisor logs if the problem persists.",
|
||||
"title": "Failed to set up OpenThread Border Router"
|
||||
},
|
||||
"pick_firmware": {
|
||||
@@ -89,11 +89,11 @@
|
||||
"silabs_multiprotocol_hardware": {
|
||||
"options": {
|
||||
"abort": {
|
||||
"addon_already_running": "Failed to start the {addon_name} add-on because it is already running.",
|
||||
"addon_info_failed": "Failed to get {addon_name} add-on info.",
|
||||
"addon_install_failed": "Failed to install the {addon_name} add-on.",
|
||||
"addon_already_running": "Failed to start the {addon_name} app because it is already running.",
|
||||
"addon_info_failed": "Failed to get {addon_name} app info.",
|
||||
"addon_install_failed": "Failed to install the {addon_name} app.",
|
||||
"addon_set_config_failed": "Failed to set {addon_name} configuration.",
|
||||
"addon_start_failed": "Failed to start the {addon_name} add-on.",
|
||||
"addon_start_failed": "Failed to start the {addon_name} app.",
|
||||
"not_hassio": "The hardware options can only be configured on Home Assistant OS installations.",
|
||||
"zha_migration_failed": "The ZHA migration did not succeed."
|
||||
},
|
||||
@@ -101,8 +101,8 @@
|
||||
"unknown": "[%key:common::config_flow::error::unknown%]"
|
||||
},
|
||||
"progress": {
|
||||
"install_addon": "Please wait while the {addon_name} add-on installation finishes. This can take several minutes.",
|
||||
"start_addon": "Please wait while the {addon_name} add-on start completes. This may take some seconds."
|
||||
"install_addon": "Please wait while the {addon_name} app installation finishes. This can take several minutes.",
|
||||
"start_addon": "Please wait while the {addon_name} app start completes. This may take some seconds."
|
||||
},
|
||||
"step": {
|
||||
"addon_installed_other_device": {
|
||||
@@ -129,7 +129,7 @@
|
||||
"title": "[%key:component::homeassistant_hardware::silabs_multiprotocol_hardware::options::step::reconfigure_addon::title%]"
|
||||
},
|
||||
"install_addon": {
|
||||
"title": "The Silicon Labs Multiprotocol add-on installation has started"
|
||||
"title": "The Silicon Labs Multiprotocol app installation has started"
|
||||
},
|
||||
"notify_channel_change": {
|
||||
"description": "A Zigbee and Thread channel change has been initiated and will finish in {delay_minutes} minutes.",
|
||||
@@ -143,7 +143,7 @@
|
||||
"title": "Reconfigure IEEE 802.15.4 radio multiprotocol support"
|
||||
},
|
||||
"start_addon": {
|
||||
"title": "The Silicon Labs Multiprotocol add-on is starting."
|
||||
"title": "The Silicon Labs Multiprotocol app is starting."
|
||||
},
|
||||
"uninstall_addon": {
|
||||
"data": {
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
from datetime import datetime
|
||||
from functools import partial
|
||||
import logging
|
||||
from typing import Any
|
||||
|
||||
from pyhomematic import HMConnection
|
||||
import voluptuous as vol
|
||||
@@ -215,8 +216,11 @@ def setup(hass: HomeAssistant, config: ConfigType) -> bool:
|
||||
hass.data[DATA_CONF] = remotes = {}
|
||||
hass.data[DATA_STORE] = set()
|
||||
|
||||
interfaces: dict[str, dict[str, Any]] = conf[CONF_INTERFACES]
|
||||
hosts: dict[str, dict[str, Any]] = conf[CONF_HOSTS]
|
||||
|
||||
# Create hosts-dictionary for pyhomematic
|
||||
for rname, rconfig in conf[CONF_INTERFACES].items():
|
||||
for rname, rconfig in interfaces.items():
|
||||
remotes[rname] = {
|
||||
"ip": rconfig.get(CONF_HOST),
|
||||
"port": rconfig.get(CONF_PORT),
|
||||
@@ -232,7 +236,7 @@ def setup(hass: HomeAssistant, config: ConfigType) -> bool:
|
||||
"connect": True,
|
||||
}
|
||||
|
||||
for sname, sconfig in conf[CONF_HOSTS].items():
|
||||
for sname, sconfig in hosts.items():
|
||||
remotes[sname] = {
|
||||
"ip": sconfig.get(CONF_HOST),
|
||||
"port": sconfig[CONF_PORT],
|
||||
@@ -258,7 +262,7 @@ def setup(hass: HomeAssistant, config: ConfigType) -> bool:
|
||||
hass.bus.listen_once(EVENT_HOMEASSISTANT_STOP, hass.data[DATA_HOMEMATIC].stop)
|
||||
|
||||
# Init homematic hubs
|
||||
entity_hubs = [HMHub(hass, homematic, hub_name) for hub_name in conf[CONF_HOSTS]]
|
||||
entity_hubs = [HMHub(hass, homematic, hub_name) for hub_name in hosts]
|
||||
|
||||
def _hm_service_virtualkey(service: ServiceCall) -> None:
|
||||
"""Service to handle virtualkey servicecalls."""
|
||||
@@ -294,7 +298,7 @@ def setup(hass: HomeAssistant, config: ConfigType) -> bool:
|
||||
|
||||
def _service_handle_value(service: ServiceCall) -> None:
|
||||
"""Service to call setValue method for HomeMatic system variable."""
|
||||
entity_ids = service.data.get(ATTR_ENTITY_ID)
|
||||
entity_ids: list[str] | None = service.data.get(ATTR_ENTITY_ID)
|
||||
name = service.data[ATTR_NAME]
|
||||
value = service.data[ATTR_VALUE]
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@ from pyhomematic import HMConnection
|
||||
from pyhomematic.devicetypes.generic import HMGeneric
|
||||
|
||||
from homeassistant.const import ATTR_NAME
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers import config_validation as cv
|
||||
from homeassistant.helpers.entity import Entity, EntityDescription
|
||||
from homeassistant.helpers.event import track_time_interval
|
||||
@@ -199,14 +200,14 @@ class HMHub(Entity):
|
||||
|
||||
_attr_should_poll = False
|
||||
|
||||
def __init__(self, hass, homematic, name):
|
||||
def __init__(self, hass: HomeAssistant, homematic: HMConnection, name: str) -> None:
|
||||
"""Initialize HomeMatic hub."""
|
||||
self.hass = hass
|
||||
self.entity_id = f"{DOMAIN}.{name.lower()}"
|
||||
self._homematic = homematic
|
||||
self._variables = {}
|
||||
self._variables: dict[str, Any] = {}
|
||||
self._name = name
|
||||
self._state = None
|
||||
self._state: int | None = None
|
||||
|
||||
# Load data
|
||||
track_time_interval(self.hass, self._update_hub, SCAN_INTERVAL_HUB)
|
||||
@@ -216,12 +217,12 @@ class HMHub(Entity):
|
||||
self.hass.add_job(self._update_variables, None)
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
def name(self) -> str:
|
||||
"""Return the name of the device."""
|
||||
return self._name
|
||||
|
||||
@property
|
||||
def state(self):
|
||||
def state(self) -> int | None:
|
||||
"""Return the state of the entity."""
|
||||
return self._state
|
||||
|
||||
@@ -231,7 +232,7 @@ class HMHub(Entity):
|
||||
return self._variables.copy()
|
||||
|
||||
@property
|
||||
def icon(self):
|
||||
def icon(self) -> str:
|
||||
"""Return the icon to use in the frontend, if any."""
|
||||
return "mdi:gradient-vertical"
|
||||
|
||||
|
||||
@@ -13,5 +13,5 @@
|
||||
"iot_class": "cloud_push",
|
||||
"loggers": ["pylitterbot"],
|
||||
"quality_scale": "bronze",
|
||||
"requirements": ["pylitterbot==2025.0.0"]
|
||||
"requirements": ["pylitterbot==2025.1.0"]
|
||||
}
|
||||
|
||||
@@ -8,6 +8,6 @@
|
||||
"documentation": "https://www.home-assistant.io/integrations/matter",
|
||||
"integration_type": "hub",
|
||||
"iot_class": "local_push",
|
||||
"requirements": ["python-matter-server==8.1.2"],
|
||||
"requirements": ["matter-python-client==0.4.1"],
|
||||
"zeroconf": ["_matter._tcp.local.", "_matterc._udp.local."]
|
||||
}
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
{
|
||||
"config": {
|
||||
"abort": {
|
||||
"addon_get_discovery_info_failed": "Failed to get Matter Server add-on discovery info.",
|
||||
"addon_info_failed": "Failed to get Matter Server add-on info.",
|
||||
"addon_install_failed": "Failed to install the Matter Server add-on.",
|
||||
"addon_start_failed": "Failed to start the Matter Server add-on.",
|
||||
"addon_get_discovery_info_failed": "Failed to get Matter Server app discovery info.",
|
||||
"addon_info_failed": "Failed to get Matter Server app info.",
|
||||
"addon_install_failed": "Failed to install the Matter Server app.",
|
||||
"addon_start_failed": "Failed to start the Matter Server app.",
|
||||
"already_configured": "[%key:common::config_flow::abort::already_configured_device%]",
|
||||
"already_in_progress": "[%key:common::config_flow::abort::already_in_progress%]",
|
||||
"cannot_connect": "[%key:common::config_flow::error::cannot_connect%]",
|
||||
"not_matter_addon": "Discovered add-on is not the official Matter Server add-on.",
|
||||
"not_matter_addon": "Discovered app is not the official Matter Server app.",
|
||||
"reconfiguration_successful": "Successfully reconfigured the Matter integration."
|
||||
},
|
||||
"error": {
|
||||
@@ -18,15 +18,15 @@
|
||||
},
|
||||
"flow_title": "{name}",
|
||||
"progress": {
|
||||
"install_addon": "Please wait while the Matter Server add-on installation finishes. This can take several minutes.",
|
||||
"start_addon": "Please wait while the Matter Server add-on starts. This add-on is what powers Matter in Home Assistant. This may take some seconds."
|
||||
"install_addon": "Please wait while the Matter Server app installation finishes. This can take several minutes.",
|
||||
"start_addon": "Please wait while the Matter Server app starts. This app is what powers Matter in Home Assistant. This may take some seconds."
|
||||
},
|
||||
"step": {
|
||||
"hassio_confirm": {
|
||||
"title": "Set up the Matter integration with the Matter Server add-on"
|
||||
"title": "Set up the Matter integration with the Matter Server app"
|
||||
},
|
||||
"install_addon": {
|
||||
"title": "The add-on installation has started"
|
||||
"title": "The app installation has started"
|
||||
},
|
||||
"manual": {
|
||||
"data": {
|
||||
@@ -35,13 +35,13 @@
|
||||
},
|
||||
"on_supervisor": {
|
||||
"data": {
|
||||
"use_addon": "Use the official Matter Server Supervisor add-on"
|
||||
"use_addon": "Use the official Matter Server Supervisor app"
|
||||
},
|
||||
"description": "Do you want to use the official Matter Server Supervisor add-on?\n\nIf you are already running the Matter Server in another add-on, in a custom container, natively etc., then do not select this option.",
|
||||
"description": "Do you want to use the official Matter Server Supervisor app?\n\nIf you are already running the Matter Server in another app, in a custom container, natively etc., then do not select this option.",
|
||||
"title": "Select connection method"
|
||||
},
|
||||
"start_addon": {
|
||||
"title": "Starting add-on."
|
||||
"title": "Starting app."
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
"documentation": "https://www.home-assistant.io/integrations/ntfy",
|
||||
"integration_type": "service",
|
||||
"iot_class": "cloud_push",
|
||||
"loggers": ["aionfty"],
|
||||
"loggers": ["aiontfy"],
|
||||
"quality_scale": "platinum",
|
||||
"requirements": ["aiontfy==0.7.0"]
|
||||
"requirements": ["aiontfy==0.8.0"]
|
||||
}
|
||||
|
||||
@@ -7,5 +7,5 @@
|
||||
"integration_type": "service",
|
||||
"iot_class": "local_polling",
|
||||
"quality_scale": "bronze",
|
||||
"requirements": ["pyportainer==1.0.23"]
|
||||
"requirements": ["pyportainer==1.0.27"]
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
"codeowners": ["@Lash-L"],
|
||||
"config_flow": true,
|
||||
"documentation": "https://www.home-assistant.io/integrations/snoo",
|
||||
"integration_type": "hub",
|
||||
"iot_class": "cloud_push",
|
||||
"loggers": ["snoo"],
|
||||
"quality_scale": "bronze",
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
"config_flow": true,
|
||||
"dependencies": ["bluetooth_adapters"],
|
||||
"documentation": "https://www.home-assistant.io/integrations/snooz",
|
||||
"integration_type": "device",
|
||||
"iot_class": "local_push",
|
||||
"requirements": ["pysnooz==0.8.6"]
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
"codeowners": ["@squishykid", "@Darsstar"],
|
||||
"config_flow": true,
|
||||
"documentation": "https://www.home-assistant.io/integrations/solax",
|
||||
"integration_type": "device",
|
||||
"iot_class": "local_polling",
|
||||
"loggers": ["solax"],
|
||||
"requirements": ["solax==3.2.3"]
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
"codeowners": ["@ratsept"],
|
||||
"config_flow": true,
|
||||
"documentation": "https://www.home-assistant.io/integrations/soma",
|
||||
"integration_type": "hub",
|
||||
"iot_class": "local_polling",
|
||||
"loggers": ["api"],
|
||||
"requirements": ["pysoma==0.0.12"]
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
}
|
||||
],
|
||||
"documentation": "https://www.home-assistant.io/integrations/somfy_mylink",
|
||||
"integration_type": "hub",
|
||||
"iot_class": "assumed_state",
|
||||
"loggers": ["somfy_mylink_synergy"],
|
||||
"requirements": ["somfy-mylink-synergy==1.0.6"]
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
"codeowners": ["@ctalkington"],
|
||||
"config_flow": true,
|
||||
"documentation": "https://www.home-assistant.io/integrations/sonarr",
|
||||
"integration_type": "service",
|
||||
"iot_class": "local_polling",
|
||||
"loggers": ["aiopyarr"],
|
||||
"requirements": ["aiopyarr==23.4.0"]
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
"codeowners": ["@rytilahti", "@shenxn"],
|
||||
"config_flow": true,
|
||||
"documentation": "https://www.home-assistant.io/integrations/songpal",
|
||||
"integration_type": "device",
|
||||
"iot_class": "local_push",
|
||||
"loggers": ["songpal"],
|
||||
"requirements": ["python-songpal==0.16.2"],
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
"codeowners": ["@kroimon"],
|
||||
"config_flow": true,
|
||||
"documentation": "https://www.home-assistant.io/integrations/soundtouch",
|
||||
"integration_type": "device",
|
||||
"iot_class": "local_polling",
|
||||
"loggers": ["libsoundtouch"],
|
||||
"requirements": ["libsoundtouch==0.8"],
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
"codeowners": ["@Bre77"],
|
||||
"config_flow": true,
|
||||
"documentation": "https://www.home-assistant.io/integrations/splunk",
|
||||
"integration_type": "service",
|
||||
"iot_class": "local_push",
|
||||
"loggers": ["hass_splunk"],
|
||||
"quality_scale": "legacy",
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
"codeowners": ["@briglx"],
|
||||
"config_flow": true,
|
||||
"documentation": "https://www.home-assistant.io/integrations/srp_energy",
|
||||
"integration_type": "service",
|
||||
"iot_class": "cloud_polling",
|
||||
"loggers": ["srpenergy"],
|
||||
"requirements": ["srpenergy==1.3.6"]
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
"codeowners": ["@anonym-tsk"],
|
||||
"config_flow": true,
|
||||
"documentation": "https://www.home-assistant.io/integrations/starline",
|
||||
"integration_type": "hub",
|
||||
"iot_class": "cloud_polling",
|
||||
"loggers": ["starline"],
|
||||
"requirements": ["starline==0.1.5"]
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
"codeowners": ["@boswelja"],
|
||||
"config_flow": true,
|
||||
"documentation": "https://www.home-assistant.io/integrations/starlink",
|
||||
"integration_type": "device",
|
||||
"iot_class": "local_polling",
|
||||
"requirements": ["starlink-grpc-core==1.2.3"]
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
}
|
||||
],
|
||||
"documentation": "https://www.home-assistant.io/integrations/steamist",
|
||||
"integration_type": "device",
|
||||
"iot_class": "local_polling",
|
||||
"loggers": ["aiosteamist", "discovery30303"],
|
||||
"requirements": ["aiosteamist==1.0.1", "discovery30303==0.3.3"]
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
"codeowners": ["@fucm", "@ThyMYthOS"],
|
||||
"config_flow": true,
|
||||
"documentation": "https://www.home-assistant.io/integrations/stiebel_eltron",
|
||||
"integration_type": "device",
|
||||
"iot_class": "local_polling",
|
||||
"loggers": ["pymodbus", "pystiebeleltron"],
|
||||
"requirements": ["pystiebeleltron==0.2.5"]
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
"codeowners": [],
|
||||
"config_flow": true,
|
||||
"documentation": "https://www.home-assistant.io/integrations/streamlabswater",
|
||||
"integration_type": "service",
|
||||
"iot_class": "cloud_polling",
|
||||
"loggers": ["streamlabswater"],
|
||||
"requirements": ["streamlabswater==1.0.1"]
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
"codeowners": ["@G-Two"],
|
||||
"config_flow": true,
|
||||
"documentation": "https://www.home-assistant.io/integrations/subaru",
|
||||
"integration_type": "hub",
|
||||
"iot_class": "cloud_polling",
|
||||
"loggers": ["stdiomask", "subarulink"],
|
||||
"requirements": ["subarulink==0.7.15"]
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
"codeowners": ["@ooii", "@jb101010-2"],
|
||||
"config_flow": true,
|
||||
"documentation": "https://www.home-assistant.io/integrations/suez_water",
|
||||
"integration_type": "service",
|
||||
"iot_class": "cloud_polling",
|
||||
"loggers": ["pysuez", "regex"],
|
||||
"quality_scale": "bronze",
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
}
|
||||
],
|
||||
"documentation": "https://www.home-assistant.io/integrations/sunricher_dali",
|
||||
"integration_type": "hub",
|
||||
"iot_class": "local_push",
|
||||
"quality_scale": "silver",
|
||||
"requirements": ["PySrDaliGateway==0.19.3"]
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
"codeowners": ["@benleb", "@danielhiversen"],
|
||||
"config_flow": true,
|
||||
"documentation": "https://www.home-assistant.io/integrations/surepetcare",
|
||||
"integration_type": "hub",
|
||||
"iot_class": "cloud_polling",
|
||||
"loggers": ["rich", "surepy"],
|
||||
"requirements": ["surepy==0.9.0"]
|
||||
|
||||
@@ -4,7 +4,7 @@ from __future__ import annotations
|
||||
|
||||
from datetime import timedelta
|
||||
import logging
|
||||
from typing import Any
|
||||
from typing import TYPE_CHECKING, Any
|
||||
|
||||
from swisshydrodata import SwissHydroData
|
||||
import voluptuous as vol
|
||||
@@ -67,8 +67,8 @@ def setup_platform(
|
||||
discovery_info: DiscoveryInfoType | None = None,
|
||||
) -> None:
|
||||
"""Set up the Swiss hydrological sensor."""
|
||||
station = config[CONF_STATION]
|
||||
monitored_conditions = config[CONF_MONITORED_CONDITIONS]
|
||||
station: int = config[CONF_STATION]
|
||||
monitored_conditions: list[str] = config[CONF_MONITORED_CONDITIONS]
|
||||
|
||||
hydro_data = HydrologicalData(station)
|
||||
hydro_data.update()
|
||||
@@ -93,38 +93,24 @@ class SwissHydrologicalDataSensor(SensorEntity):
|
||||
"Data provided by the Swiss Federal Office for the Environment FOEN"
|
||||
)
|
||||
|
||||
def __init__(self, hydro_data, station, condition):
|
||||
def __init__(
|
||||
self, hydro_data: HydrologicalData, station: int, condition: str
|
||||
) -> None:
|
||||
"""Initialize the Swiss hydrological sensor."""
|
||||
self.hydro_data = hydro_data
|
||||
data = hydro_data.data
|
||||
if TYPE_CHECKING:
|
||||
# Setup will fail in setup_platform if the data is None.
|
||||
assert data is not None
|
||||
|
||||
self._condition = condition
|
||||
self._data = self._state = self._unit_of_measurement = None
|
||||
self._icon = CONDITIONS[condition]
|
||||
self._data: dict[str, Any] | None = data
|
||||
self._attr_icon = CONDITIONS[condition]
|
||||
self._attr_name = f"{data['water-body-name']} {condition}"
|
||||
self._attr_native_unit_of_measurement = data["parameters"][condition]["unit"]
|
||||
self._attr_unique_id = f"{station}_{condition}"
|
||||
self._station = station
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
"""Return the name of the sensor."""
|
||||
return f"{self._data['water-body-name']} {self._condition}"
|
||||
|
||||
@property
|
||||
def unique_id(self) -> str:
|
||||
"""Return a unique, friendly identifier for this entity."""
|
||||
return f"{self._station}_{self._condition}"
|
||||
|
||||
@property
|
||||
def native_unit_of_measurement(self):
|
||||
"""Return the unit of measurement of this entity, if any."""
|
||||
if self._state is not None:
|
||||
return self.hydro_data.data["parameters"][self._condition]["unit"]
|
||||
return None
|
||||
|
||||
@property
|
||||
def native_value(self):
|
||||
"""Return the state of the sensor."""
|
||||
if isinstance(self._state, (int, float)):
|
||||
return round(self._state, 2)
|
||||
return None
|
||||
|
||||
@property
|
||||
def extra_state_attributes(self) -> dict[str, Any]:
|
||||
"""Return the device state attributes."""
|
||||
@@ -146,32 +132,28 @@ class SwissHydrologicalDataSensor(SensorEntity):
|
||||
|
||||
return attrs
|
||||
|
||||
@property
|
||||
def icon(self):
|
||||
"""Icon to use in the frontend."""
|
||||
return self._icon
|
||||
|
||||
def update(self) -> None:
|
||||
"""Get the latest data and update the state."""
|
||||
self.hydro_data.update()
|
||||
self._data = self.hydro_data.data
|
||||
|
||||
if self._data is None:
|
||||
self._state = None
|
||||
else:
|
||||
self._state = self._data["parameters"][self._condition]["value"]
|
||||
self._attr_native_value = None
|
||||
if self._data is not None:
|
||||
state = self._data["parameters"][self._condition]["value"]
|
||||
if isinstance(state, (int, float)):
|
||||
self._attr_native_value = round(state, 2)
|
||||
|
||||
|
||||
class HydrologicalData:
|
||||
"""The Class for handling the data retrieval."""
|
||||
|
||||
def __init__(self, station):
|
||||
def __init__(self, station: int) -> None:
|
||||
"""Initialize the data object."""
|
||||
self.station = station
|
||||
self.data = None
|
||||
self.data: dict[str, Any] | None = None
|
||||
|
||||
@Throttle(MIN_TIME_BETWEEN_UPDATES)
|
||||
def update(self):
|
||||
def update(self) -> None:
|
||||
"""Get the latest data."""
|
||||
|
||||
shd = SwissHydroData()
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
"codeowners": ["@fabaff", "@miaucl"],
|
||||
"config_flow": true,
|
||||
"documentation": "https://www.home-assistant.io/integrations/swiss_public_transport",
|
||||
"integration_type": "service",
|
||||
"iot_class": "cloud_polling",
|
||||
"loggers": ["opendata_transport"],
|
||||
"requirements": ["python-opendata-transport==0.5.0"]
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
"codeowners": ["@jafar-atili"],
|
||||
"config_flow": true,
|
||||
"documentation": "https://www.home-assistant.io/integrations/switchbee",
|
||||
"integration_type": "hub",
|
||||
"iot_class": "local_push",
|
||||
"requirements": ["pyswitchbee==1.8.3"]
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
"codeowners": ["@thecode", "@YogevBokobza"],
|
||||
"config_flow": true,
|
||||
"documentation": "https://www.home-assistant.io/integrations/switcher_kis",
|
||||
"integration_type": "hub",
|
||||
"iot_class": "local_push",
|
||||
"loggers": ["aioswitcher"],
|
||||
"quality_scale": "silver",
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
"codeowners": ["@zhulik"],
|
||||
"config_flow": true,
|
||||
"documentation": "https://www.home-assistant.io/integrations/syncthing",
|
||||
"integration_type": "service",
|
||||
"iot_class": "local_polling",
|
||||
"loggers": ["aiosyncthing"],
|
||||
"requirements": ["aiosyncthing==0.7.1"]
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
"codeowners": ["@nielstron"],
|
||||
"config_flow": true,
|
||||
"documentation": "https://www.home-assistant.io/integrations/syncthru",
|
||||
"integration_type": "device",
|
||||
"iot_class": "local_polling",
|
||||
"loggers": ["pysyncthru"],
|
||||
"requirements": ["PySyncThru==0.8.0", "url-normalize==2.2.1"],
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
"codeowners": ["@Guy293"],
|
||||
"config_flow": true,
|
||||
"documentation": "https://www.home-assistant.io/integrations/tami4",
|
||||
"integration_type": "device",
|
||||
"iot_class": "cloud_polling",
|
||||
"requirements": ["Tami4EdgeAPI==3.0"]
|
||||
}
|
||||
|
||||
@@ -468,7 +468,7 @@ async def _async_send_telegram_message(service: ServiceCall) -> ServiceResponse:
|
||||
targets = _build_targets(service)
|
||||
|
||||
service_responses: JsonValueType = []
|
||||
errors: list[tuple[HomeAssistantError, str]] = []
|
||||
errors: list[tuple[Exception, str]] = []
|
||||
|
||||
# invoke the service for each target
|
||||
for target_config_entry, target_chat_id, target_notify_entity_id in targets:
|
||||
@@ -495,7 +495,7 @@ async def _async_send_telegram_message(service: ServiceCall) -> ServiceResponse:
|
||||
|
||||
assert isinstance(service_responses, list)
|
||||
service_responses.extend(formatted_responses)
|
||||
except HomeAssistantError as ex:
|
||||
except (HomeAssistantError, TelegramError) as ex:
|
||||
target = target_notify_entity_id or str(target_chat_id)
|
||||
errors.append((ex, target))
|
||||
|
||||
|
||||
@@ -433,7 +433,6 @@ class TelegramNotificationService:
|
||||
async def _send_msgs(
|
||||
self,
|
||||
func_send: Callable,
|
||||
msg_error: str,
|
||||
message_tag: str | None,
|
||||
*args_msg: Any,
|
||||
context: Context | None = None,
|
||||
@@ -459,12 +458,10 @@ class TelegramNotificationService:
|
||||
|
||||
response: Message = await self._send_msg(
|
||||
func_send,
|
||||
msg_error,
|
||||
message_tag,
|
||||
chat_id,
|
||||
*args_msg,
|
||||
context=context,
|
||||
suppress_error=len(chat_ids) > 1,
|
||||
**kwargs_msg,
|
||||
)
|
||||
if response:
|
||||
@@ -475,58 +472,39 @@ class TelegramNotificationService:
|
||||
async def _send_msg(
|
||||
self,
|
||||
func_send: Callable,
|
||||
msg_error: str,
|
||||
message_tag: str | None,
|
||||
*args_msg: Any,
|
||||
context: Context | None = None,
|
||||
suppress_error: bool = False,
|
||||
**kwargs_msg: Any,
|
||||
) -> Any:
|
||||
"""Send one message."""
|
||||
try:
|
||||
out = await func_send(*args_msg, **kwargs_msg)
|
||||
if isinstance(out, Message):
|
||||
chat_id = out.chat_id
|
||||
message_id = out.message_id
|
||||
self._last_message_id[chat_id] = message_id
|
||||
_LOGGER.debug(
|
||||
"Last message ID: %s (from chat_id %s)",
|
||||
self._last_message_id,
|
||||
chat_id,
|
||||
)
|
||||
|
||||
event_data: dict[str, Any] = {
|
||||
ATTR_CHAT_ID: chat_id,
|
||||
ATTR_MESSAGEID: message_id,
|
||||
}
|
||||
if message_tag is not None:
|
||||
event_data[ATTR_MESSAGE_TAG] = message_tag
|
||||
if kwargs_msg.get(ATTR_MESSAGE_THREAD_ID) is not None:
|
||||
event_data[ATTR_MESSAGE_THREAD_ID] = kwargs_msg[
|
||||
ATTR_MESSAGE_THREAD_ID
|
||||
]
|
||||
|
||||
event_data["bot"] = _get_bot_info(self.bot, self.config)
|
||||
|
||||
self.hass.bus.async_fire(
|
||||
EVENT_TELEGRAM_SENT, event_data, context=context
|
||||
)
|
||||
async_dispatcher_send(
|
||||
self.hass, signal(self.bot), EVENT_TELEGRAM_SENT, event_data
|
||||
)
|
||||
except TelegramError as exc:
|
||||
if not suppress_error:
|
||||
raise HomeAssistantError(
|
||||
translation_domain=DOMAIN,
|
||||
translation_key="action_failed",
|
||||
translation_placeholders={"error": str(exc)},
|
||||
) from exc
|
||||
|
||||
_LOGGER.error(
|
||||
"%s: %s. Args: %s, kwargs: %s", msg_error, exc, args_msg, kwargs_msg
|
||||
out = await func_send(*args_msg, **kwargs_msg)
|
||||
if isinstance(out, Message):
|
||||
chat_id = out.chat_id
|
||||
message_id = out.message_id
|
||||
self._last_message_id[chat_id] = message_id
|
||||
_LOGGER.debug(
|
||||
"Last message ID: %s (from chat_id %s)",
|
||||
self._last_message_id,
|
||||
chat_id,
|
||||
)
|
||||
|
||||
event_data: dict[str, Any] = {
|
||||
ATTR_CHAT_ID: chat_id,
|
||||
ATTR_MESSAGEID: message_id,
|
||||
}
|
||||
if message_tag is not None:
|
||||
event_data[ATTR_MESSAGE_TAG] = message_tag
|
||||
if kwargs_msg.get(ATTR_MESSAGE_THREAD_ID) is not None:
|
||||
event_data[ATTR_MESSAGE_THREAD_ID] = kwargs_msg[ATTR_MESSAGE_THREAD_ID]
|
||||
|
||||
event_data["bot"] = _get_bot_info(self.bot, self.config)
|
||||
|
||||
self.hass.bus.async_fire(EVENT_TELEGRAM_SENT, event_data, context=context)
|
||||
async_dispatcher_send(
|
||||
self.hass, signal(self.bot), EVENT_TELEGRAM_SENT, event_data
|
||||
)
|
||||
|
||||
return None
|
||||
return out
|
||||
|
||||
async def send_message(
|
||||
@@ -542,7 +520,6 @@ class TelegramNotificationService:
|
||||
params = self._get_msg_kwargs(kwargs)
|
||||
return await self._send_msgs(
|
||||
self.bot.send_message,
|
||||
"Error sending message",
|
||||
params[ATTR_MESSAGE_TAG],
|
||||
text,
|
||||
chat_id=chat_id,
|
||||
@@ -567,7 +544,6 @@ class TelegramNotificationService:
|
||||
_LOGGER.debug("Delete message %s in chat ID %s", message_id, chat_id)
|
||||
deleted: bool = await self._send_msg(
|
||||
self.bot.delete_message,
|
||||
"Error deleting message",
|
||||
None,
|
||||
chat_id,
|
||||
message_id,
|
||||
@@ -644,7 +620,6 @@ class TelegramNotificationService:
|
||||
|
||||
return await self._send_msg(
|
||||
self.bot.edit_message_media,
|
||||
"Error editing message media",
|
||||
params[ATTR_MESSAGE_TAG],
|
||||
media=media,
|
||||
chat_id=chat_id,
|
||||
@@ -678,7 +653,6 @@ class TelegramNotificationService:
|
||||
_LOGGER.debug("Editing message with ID %s", message_id or inline_message_id)
|
||||
return await self._send_msg(
|
||||
self.bot.edit_message_text,
|
||||
"Error editing text message",
|
||||
params[ATTR_MESSAGE_TAG],
|
||||
text,
|
||||
chat_id=chat_id,
|
||||
@@ -693,7 +667,6 @@ class TelegramNotificationService:
|
||||
if type_edit == SERVICE_EDIT_CAPTION:
|
||||
return await self._send_msg(
|
||||
self.bot.edit_message_caption,
|
||||
"Error editing message attributes",
|
||||
params[ATTR_MESSAGE_TAG],
|
||||
chat_id=chat_id,
|
||||
message_id=message_id,
|
||||
@@ -707,7 +680,6 @@ class TelegramNotificationService:
|
||||
|
||||
return await self._send_msg(
|
||||
self.bot.edit_message_reply_markup,
|
||||
"Error editing message attributes",
|
||||
params[ATTR_MESSAGE_TAG],
|
||||
chat_id=chat_id,
|
||||
message_id=message_id,
|
||||
@@ -735,7 +707,6 @@ class TelegramNotificationService:
|
||||
)
|
||||
await self._send_msg(
|
||||
self.bot.answer_callback_query,
|
||||
"Error sending answer callback query",
|
||||
params[ATTR_MESSAGE_TAG],
|
||||
callback_query_id,
|
||||
text=message,
|
||||
@@ -756,7 +727,6 @@ class TelegramNotificationService:
|
||||
_LOGGER.debug("Send action %s in chat ID %s", chat_action, chat_id)
|
||||
is_successful = await self._send_msg(
|
||||
self.bot.send_chat_action,
|
||||
"Error sending action",
|
||||
None,
|
||||
chat_id=chat_id,
|
||||
action=chat_action,
|
||||
@@ -791,7 +761,6 @@ class TelegramNotificationService:
|
||||
if file_type == SERVICE_SEND_PHOTO:
|
||||
return await self._send_msgs(
|
||||
self.bot.send_photo,
|
||||
"Error sending photo",
|
||||
params[ATTR_MESSAGE_TAG],
|
||||
chat_id=kwargs[ATTR_CHAT_ID],
|
||||
photo=file_content,
|
||||
@@ -808,7 +777,6 @@ class TelegramNotificationService:
|
||||
if file_type == SERVICE_SEND_STICKER:
|
||||
return await self._send_msgs(
|
||||
self.bot.send_sticker,
|
||||
"Error sending sticker",
|
||||
params[ATTR_MESSAGE_TAG],
|
||||
chat_id=kwargs[ATTR_CHAT_ID],
|
||||
sticker=file_content,
|
||||
@@ -823,7 +791,6 @@ class TelegramNotificationService:
|
||||
if file_type == SERVICE_SEND_VIDEO:
|
||||
return await self._send_msgs(
|
||||
self.bot.send_video,
|
||||
"Error sending video",
|
||||
params[ATTR_MESSAGE_TAG],
|
||||
chat_id=kwargs[ATTR_CHAT_ID],
|
||||
video=file_content,
|
||||
@@ -840,7 +807,6 @@ class TelegramNotificationService:
|
||||
if file_type == SERVICE_SEND_DOCUMENT:
|
||||
return await self._send_msgs(
|
||||
self.bot.send_document,
|
||||
"Error sending document",
|
||||
params[ATTR_MESSAGE_TAG],
|
||||
chat_id=kwargs[ATTR_CHAT_ID],
|
||||
document=file_content,
|
||||
@@ -857,7 +823,6 @@ class TelegramNotificationService:
|
||||
if file_type == SERVICE_SEND_VOICE:
|
||||
return await self._send_msgs(
|
||||
self.bot.send_voice,
|
||||
"Error sending voice",
|
||||
params[ATTR_MESSAGE_TAG],
|
||||
chat_id=kwargs[ATTR_CHAT_ID],
|
||||
voice=file_content,
|
||||
@@ -873,7 +838,6 @@ class TelegramNotificationService:
|
||||
# SERVICE_SEND_ANIMATION
|
||||
return await self._send_msgs(
|
||||
self.bot.send_animation,
|
||||
"Error sending animation",
|
||||
params[ATTR_MESSAGE_TAG],
|
||||
chat_id=kwargs[ATTR_CHAT_ID],
|
||||
animation=file_content,
|
||||
@@ -899,7 +863,6 @@ class TelegramNotificationService:
|
||||
if stickerid:
|
||||
return await self._send_msgs(
|
||||
self.bot.send_sticker,
|
||||
"Error sending sticker",
|
||||
params[ATTR_MESSAGE_TAG],
|
||||
chat_id=kwargs[ATTR_CHAT_ID],
|
||||
sticker=stickerid,
|
||||
@@ -925,7 +888,6 @@ class TelegramNotificationService:
|
||||
params = self._get_msg_kwargs(kwargs)
|
||||
return await self._send_msgs(
|
||||
self.bot.send_location,
|
||||
"Error sending location",
|
||||
params[ATTR_MESSAGE_TAG],
|
||||
chat_id=kwargs[ATTR_CHAT_ID],
|
||||
latitude=latitude,
|
||||
@@ -951,7 +913,6 @@ class TelegramNotificationService:
|
||||
openperiod = kwargs.get(ATTR_OPEN_PERIOD)
|
||||
return await self._send_msgs(
|
||||
self.bot.send_poll,
|
||||
"Error sending poll",
|
||||
params[ATTR_MESSAGE_TAG],
|
||||
chat_id=kwargs[ATTR_CHAT_ID],
|
||||
question=question,
|
||||
@@ -974,9 +935,7 @@ class TelegramNotificationService:
|
||||
) -> Any:
|
||||
"""Remove bot from chat."""
|
||||
_LOGGER.debug("Leave from chat ID %s", chat_id)
|
||||
return await self._send_msg(
|
||||
self.bot.leave_chat, "Error leaving chat", None, chat_id, context=context
|
||||
)
|
||||
return await self._send_msg(self.bot.leave_chat, None, chat_id, context=context)
|
||||
|
||||
async def set_message_reaction(
|
||||
self,
|
||||
@@ -1000,7 +959,6 @@ class TelegramNotificationService:
|
||||
|
||||
await self._send_msg(
|
||||
self.bot.set_message_reaction,
|
||||
"Error setting message reaction",
|
||||
params[ATTR_MESSAGE_TAG],
|
||||
chat_id,
|
||||
message_id,
|
||||
@@ -1023,7 +981,6 @@ class TelegramNotificationService:
|
||||
directory_path = self.hass.config.path(DOMAIN)
|
||||
file: File = await self._send_msg(
|
||||
self.bot.get_file,
|
||||
"Error getting file",
|
||||
None,
|
||||
file_id=file_id,
|
||||
context=context,
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
"config_flow": true,
|
||||
"dependencies": ["http"],
|
||||
"documentation": "https://www.home-assistant.io/integrations/telegram_bot",
|
||||
"integration_type": "service",
|
||||
"iot_class": "cloud_push",
|
||||
"loggers": ["telegram"],
|
||||
"quality_scale": "silver",
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
"codeowners": ["@fredrike"],
|
||||
"config_flow": true,
|
||||
"documentation": "https://www.home-assistant.io/integrations/tellduslive",
|
||||
"integration_type": "hub",
|
||||
"iot_class": "cloud_polling",
|
||||
"requirements": ["tellduslive==0.10.12"]
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
}
|
||||
],
|
||||
"documentation": "https://www.home-assistant.io/integrations/tesla_wall_connector",
|
||||
"integration_type": "device",
|
||||
"iot_class": "local_polling",
|
||||
"loggers": ["tesla_wall_connector"],
|
||||
"requirements": ["tesla-wall-connector==1.1.0"]
|
||||
|
||||
@@ -53,6 +53,7 @@
|
||||
"config_flow": true,
|
||||
"dependencies": ["bluetooth_adapters"],
|
||||
"documentation": "https://www.home-assistant.io/integrations/thermobeacon",
|
||||
"integration_type": "device",
|
||||
"iot_class": "local_push",
|
||||
"requirements": ["thermobeacon-ble==0.10.0"]
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
"config_flow": true,
|
||||
"dependencies": ["bluetooth_adapters"],
|
||||
"documentation": "https://www.home-assistant.io/integrations/thermopro",
|
||||
"integration_type": "device",
|
||||
"iot_class": "local_push",
|
||||
"requirements": ["thermopro-ble==1.1.3"]
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
"config_flow": true,
|
||||
"dependencies": ["application_credentials", "recorder"],
|
||||
"documentation": "https://www.home-assistant.io/integrations/tibber",
|
||||
"integration_type": "hub",
|
||||
"iot_class": "cloud_polling",
|
||||
"loggers": ["tibber"],
|
||||
"requirements": ["pyTibber==0.35.0"]
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
"config_flow": true,
|
||||
"dependencies": ["bluetooth_adapters"],
|
||||
"documentation": "https://www.home-assistant.io/integrations/tilt_ble",
|
||||
"integration_type": "device",
|
||||
"iot_class": "local_push",
|
||||
"requirements": ["tilt-ble==1.0.1"]
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
"codeowners": ["@boralyl"],
|
||||
"config_flow": true,
|
||||
"documentation": "https://www.home-assistant.io/integrations/todoist",
|
||||
"integration_type": "service",
|
||||
"iot_class": "cloud_polling",
|
||||
"loggers": ["todoist"],
|
||||
"requirements": ["todoist-api-python==3.1.0"]
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
"config_flow": true,
|
||||
"dependencies": ["bluetooth"],
|
||||
"documentation": "https://www.home-assistant.io/integrations/togrill",
|
||||
"integration_type": "device",
|
||||
"iot_class": "local_push",
|
||||
"loggers": ["togrill_bluetooth"],
|
||||
"quality_scale": "bronze",
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
}
|
||||
],
|
||||
"documentation": "https://www.home-assistant.io/integrations/tolo",
|
||||
"integration_type": "device",
|
||||
"iot_class": "local_polling",
|
||||
"loggers": ["tololib"],
|
||||
"requirements": ["tololib==1.2.2"]
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
}
|
||||
],
|
||||
"documentation": "https://www.home-assistant.io/integrations/toon",
|
||||
"integration_type": "device",
|
||||
"iot_class": "cloud_push",
|
||||
"loggers": ["toonapi"],
|
||||
"requirements": ["toonapi==0.3.0"]
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
"codeowners": ["@austinmroczek"],
|
||||
"config_flow": true,
|
||||
"documentation": "https://www.home-assistant.io/integrations/totalconnect",
|
||||
"integration_type": "hub",
|
||||
"iot_class": "cloud_polling",
|
||||
"loggers": ["total_connect_client"],
|
||||
"requirements": ["total-connect-client==2025.12.2"]
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
"homekit": {
|
||||
"models": ["TRADFRI"]
|
||||
},
|
||||
"integration_type": "hub",
|
||||
"iot_class": "local_polling",
|
||||
"loggers": ["pytradfri"],
|
||||
"requirements": ["pytradfri[async]==9.0.1"]
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
"codeowners": ["@gjohansson-ST"],
|
||||
"config_flow": true,
|
||||
"documentation": "https://www.home-assistant.io/integrations/trafikverket_camera",
|
||||
"integration_type": "service",
|
||||
"iot_class": "cloud_polling",
|
||||
"loggers": ["pytrafikverket"],
|
||||
"requirements": ["pytrafikverket==1.1.1"]
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
"codeowners": ["@gjohansson-ST"],
|
||||
"config_flow": true,
|
||||
"documentation": "https://www.home-assistant.io/integrations/trafikverket_ferry",
|
||||
"integration_type": "service",
|
||||
"iot_class": "cloud_polling",
|
||||
"loggers": ["pytrafikverket"],
|
||||
"requirements": ["pytrafikverket==1.1.1"]
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
"codeowners": ["@gjohansson-ST"],
|
||||
"config_flow": true,
|
||||
"documentation": "https://www.home-assistant.io/integrations/trafikverket_train",
|
||||
"integration_type": "service",
|
||||
"iot_class": "cloud_polling",
|
||||
"loggers": ["pytrafikverket"],
|
||||
"requirements": ["pytrafikverket==1.1.1"]
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
"codeowners": ["@gjohansson-ST"],
|
||||
"config_flow": true,
|
||||
"documentation": "https://www.home-assistant.io/integrations/trafikverket_weatherstation",
|
||||
"integration_type": "service",
|
||||
"iot_class": "cloud_polling",
|
||||
"loggers": ["pytrafikverket"],
|
||||
"requirements": ["pytrafikverket==1.1.1"]
|
||||
|
||||
@@ -5948,7 +5948,7 @@
|
||||
"name": "Samsung Smart TV"
|
||||
},
|
||||
"syncthru": {
|
||||
"integration_type": "hub",
|
||||
"integration_type": "device",
|
||||
"config_flow": true,
|
||||
"iot_class": "local_polling",
|
||||
"name": "Samsung SyncThru Printer"
|
||||
@@ -6411,7 +6411,7 @@
|
||||
},
|
||||
"snooz": {
|
||||
"name": "Snooz",
|
||||
"integration_type": "hub",
|
||||
"integration_type": "device",
|
||||
"config_flow": true,
|
||||
"iot_class": "local_push"
|
||||
},
|
||||
@@ -6440,7 +6440,7 @@
|
||||
},
|
||||
"solax": {
|
||||
"name": "SolaX Power",
|
||||
"integration_type": "hub",
|
||||
"integration_type": "device",
|
||||
"config_flow": true,
|
||||
"iot_class": "local_polling"
|
||||
},
|
||||
@@ -6463,7 +6463,7 @@
|
||||
},
|
||||
"sonarr": {
|
||||
"name": "Sonarr",
|
||||
"integration_type": "hub",
|
||||
"integration_type": "service",
|
||||
"config_flow": true,
|
||||
"iot_class": "local_polling"
|
||||
},
|
||||
@@ -6495,7 +6495,7 @@
|
||||
"name": "Sony Projector"
|
||||
},
|
||||
"songpal": {
|
||||
"integration_type": "hub",
|
||||
"integration_type": "device",
|
||||
"config_flow": true,
|
||||
"iot_class": "local_push",
|
||||
"name": "Sony Songpal"
|
||||
@@ -6510,7 +6510,7 @@
|
||||
},
|
||||
"soundtouch": {
|
||||
"name": "Bose SoundTouch",
|
||||
"integration_type": "hub",
|
||||
"integration_type": "device",
|
||||
"config_flow": true,
|
||||
"iot_class": "local_polling"
|
||||
},
|
||||
@@ -6534,7 +6534,7 @@
|
||||
},
|
||||
"splunk": {
|
||||
"name": "Splunk",
|
||||
"integration_type": "hub",
|
||||
"integration_type": "service",
|
||||
"config_flow": true,
|
||||
"iot_class": "local_push",
|
||||
"single_config_entry": true
|
||||
@@ -6553,7 +6553,7 @@
|
||||
},
|
||||
"srp_energy": {
|
||||
"name": "SRP Energy",
|
||||
"integration_type": "hub",
|
||||
"integration_type": "service",
|
||||
"config_flow": true,
|
||||
"iot_class": "cloud_polling"
|
||||
},
|
||||
@@ -6571,7 +6571,7 @@
|
||||
},
|
||||
"starlink": {
|
||||
"name": "Starlink",
|
||||
"integration_type": "hub",
|
||||
"integration_type": "device",
|
||||
"config_flow": true,
|
||||
"iot_class": "local_polling"
|
||||
},
|
||||
@@ -6595,13 +6595,13 @@
|
||||
},
|
||||
"steamist": {
|
||||
"name": "Steamist",
|
||||
"integration_type": "hub",
|
||||
"integration_type": "device",
|
||||
"config_flow": true,
|
||||
"iot_class": "local_polling"
|
||||
},
|
||||
"stiebel_eltron": {
|
||||
"name": "STIEBEL ELTRON",
|
||||
"integration_type": "hub",
|
||||
"integration_type": "device",
|
||||
"config_flow": true,
|
||||
"iot_class": "local_polling"
|
||||
},
|
||||
@@ -6613,7 +6613,7 @@
|
||||
},
|
||||
"streamlabswater": {
|
||||
"name": "StreamLabs",
|
||||
"integration_type": "hub",
|
||||
"integration_type": "service",
|
||||
"config_flow": true,
|
||||
"iot_class": "cloud_polling"
|
||||
},
|
||||
@@ -6625,7 +6625,7 @@
|
||||
},
|
||||
"suez_water": {
|
||||
"name": "Suez Water",
|
||||
"integration_type": "hub",
|
||||
"integration_type": "service",
|
||||
"config_flow": true,
|
||||
"iot_class": "cloud_polling"
|
||||
},
|
||||
@@ -6678,7 +6678,7 @@
|
||||
},
|
||||
"swiss_public_transport": {
|
||||
"name": "Swiss public transport",
|
||||
"integration_type": "hub",
|
||||
"integration_type": "service",
|
||||
"config_flow": true,
|
||||
"iot_class": "cloud_polling"
|
||||
},
|
||||
@@ -6729,7 +6729,7 @@
|
||||
},
|
||||
"syncthing": {
|
||||
"name": "Syncthing",
|
||||
"integration_type": "hub",
|
||||
"integration_type": "service",
|
||||
"config_flow": true,
|
||||
"iot_class": "local_polling"
|
||||
},
|
||||
@@ -6801,7 +6801,7 @@
|
||||
},
|
||||
"tami4": {
|
||||
"name": "Tami4 Edge / Edge+",
|
||||
"integration_type": "hub",
|
||||
"integration_type": "device",
|
||||
"config_flow": true,
|
||||
"iot_class": "cloud_polling"
|
||||
},
|
||||
@@ -6869,7 +6869,7 @@
|
||||
"name": "Telegram"
|
||||
},
|
||||
"telegram_bot": {
|
||||
"integration_type": "hub",
|
||||
"integration_type": "service",
|
||||
"config_flow": true,
|
||||
"iot_class": "cloud_push",
|
||||
"name": "Telegram bot"
|
||||
@@ -6921,7 +6921,7 @@
|
||||
"name": "Tesla Powerwall"
|
||||
},
|
||||
"tesla_wall_connector": {
|
||||
"integration_type": "hub",
|
||||
"integration_type": "device",
|
||||
"config_flow": true,
|
||||
"iot_class": "local_polling",
|
||||
"name": "Tesla Wall Connector"
|
||||
@@ -6959,7 +6959,7 @@
|
||||
},
|
||||
"thermobeacon": {
|
||||
"name": "ThermoBeacon",
|
||||
"integration_type": "hub",
|
||||
"integration_type": "device",
|
||||
"config_flow": true,
|
||||
"iot_class": "local_push"
|
||||
},
|
||||
@@ -6970,7 +6970,7 @@
|
||||
},
|
||||
"thermopro": {
|
||||
"name": "ThermoPro",
|
||||
"integration_type": "hub",
|
||||
"integration_type": "device",
|
||||
"config_flow": true,
|
||||
"iot_class": "local_push"
|
||||
},
|
||||
@@ -7040,7 +7040,7 @@
|
||||
"name": "Tilt",
|
||||
"integrations": {
|
||||
"tilt_ble": {
|
||||
"integration_type": "hub",
|
||||
"integration_type": "device",
|
||||
"config_flow": true,
|
||||
"iot_class": "local_push",
|
||||
"name": "Tilt Hydrometer BLE"
|
||||
@@ -7066,19 +7066,19 @@
|
||||
},
|
||||
"todoist": {
|
||||
"name": "Todoist",
|
||||
"integration_type": "hub",
|
||||
"integration_type": "service",
|
||||
"config_flow": true,
|
||||
"iot_class": "cloud_polling"
|
||||
},
|
||||
"togrill": {
|
||||
"name": "ToGrill",
|
||||
"integration_type": "hub",
|
||||
"integration_type": "device",
|
||||
"config_flow": true,
|
||||
"iot_class": "local_push"
|
||||
},
|
||||
"tolo": {
|
||||
"name": "TOLO Sauna",
|
||||
"integration_type": "hub",
|
||||
"integration_type": "device",
|
||||
"config_flow": true,
|
||||
"iot_class": "local_polling"
|
||||
},
|
||||
@@ -7096,7 +7096,7 @@
|
||||
},
|
||||
"toon": {
|
||||
"name": "Toon",
|
||||
"integration_type": "hub",
|
||||
"integration_type": "device",
|
||||
"config_flow": true,
|
||||
"iot_class": "cloud_push"
|
||||
},
|
||||
@@ -7171,25 +7171,25 @@
|
||||
"name": "Trafikverket",
|
||||
"integrations": {
|
||||
"trafikverket_camera": {
|
||||
"integration_type": "hub",
|
||||
"integration_type": "service",
|
||||
"config_flow": true,
|
||||
"iot_class": "cloud_polling",
|
||||
"name": "Trafikverket Camera"
|
||||
},
|
||||
"trafikverket_ferry": {
|
||||
"integration_type": "hub",
|
||||
"integration_type": "service",
|
||||
"config_flow": true,
|
||||
"iot_class": "cloud_polling",
|
||||
"name": "Trafikverket Ferry"
|
||||
},
|
||||
"trafikverket_train": {
|
||||
"integration_type": "hub",
|
||||
"integration_type": "service",
|
||||
"config_flow": true,
|
||||
"iot_class": "cloud_polling",
|
||||
"name": "Trafikverket Train"
|
||||
},
|
||||
"trafikverket_weatherstation": {
|
||||
"integration_type": "hub",
|
||||
"integration_type": "service",
|
||||
"config_flow": true,
|
||||
"iot_class": "cloud_polling",
|
||||
"name": "Trafikverket Weather Station"
|
||||
|
||||
@@ -711,6 +711,7 @@ _ENTITY_MATCH: list[TypeHintMatch] = [
|
||||
TypeHintMatch(
|
||||
function_name="icon",
|
||||
return_type=["str", None],
|
||||
mandatory=True,
|
||||
),
|
||||
TypeHintMatch(
|
||||
function_name="entity_picture",
|
||||
|
||||
12
requirements_all.txt
generated
12
requirements_all.txt
generated
@@ -339,7 +339,7 @@ aionanoleaf2==1.0.2
|
||||
aionotion==2024.03.0
|
||||
|
||||
# homeassistant.components.ntfy
|
||||
aiontfy==0.7.0
|
||||
aiontfy==0.8.0
|
||||
|
||||
# homeassistant.components.nut
|
||||
aionut==4.3.4
|
||||
@@ -1466,6 +1466,9 @@ lxml==6.0.1
|
||||
# homeassistant.components.matrix
|
||||
matrix-nio==0.25.2
|
||||
|
||||
# homeassistant.components.matter
|
||||
matter-python-client==0.4.1
|
||||
|
||||
# homeassistant.components.maxcube
|
||||
maxcube-api==0.4.3
|
||||
|
||||
@@ -2224,7 +2227,7 @@ pyliebherrhomeapi==0.3.0
|
||||
pylitejet==0.6.3
|
||||
|
||||
# homeassistant.components.litterrobot
|
||||
pylitterbot==2025.0.0
|
||||
pylitterbot==2025.1.0
|
||||
|
||||
# homeassistant.components.lutron_caseta
|
||||
pylutron-caseta==0.26.0
|
||||
@@ -2364,7 +2367,7 @@ pyplaato==0.0.19
|
||||
pypoint==3.0.0
|
||||
|
||||
# homeassistant.components.portainer
|
||||
pyportainer==1.0.23
|
||||
pyportainer==1.0.27
|
||||
|
||||
# homeassistant.components.probe_plus
|
||||
pyprobeplus==1.1.2
|
||||
@@ -2580,9 +2583,6 @@ python-kasa[speedups]==0.10.2
|
||||
# homeassistant.components.linkplay
|
||||
python-linkplay==0.2.12
|
||||
|
||||
# homeassistant.components.matter
|
||||
python-matter-server==8.1.2
|
||||
|
||||
# homeassistant.components.melcloud
|
||||
python-melcloud==0.1.2
|
||||
|
||||
|
||||
12
requirements_test_all.txt
generated
12
requirements_test_all.txt
generated
@@ -324,7 +324,7 @@ aionanoleaf2==1.0.2
|
||||
aionotion==2024.03.0
|
||||
|
||||
# homeassistant.components.ntfy
|
||||
aiontfy==0.7.0
|
||||
aiontfy==0.8.0
|
||||
|
||||
# homeassistant.components.nut
|
||||
aionut==4.3.4
|
||||
@@ -1282,6 +1282,9 @@ lxml==6.0.1
|
||||
# homeassistant.components.matrix
|
||||
matrix-nio==0.25.2
|
||||
|
||||
# homeassistant.components.matter
|
||||
matter-python-client==0.4.1
|
||||
|
||||
# homeassistant.components.maxcube
|
||||
maxcube-api==0.4.3
|
||||
|
||||
@@ -1895,7 +1898,7 @@ pyliebherrhomeapi==0.3.0
|
||||
pylitejet==0.6.3
|
||||
|
||||
# homeassistant.components.litterrobot
|
||||
pylitterbot==2025.0.0
|
||||
pylitterbot==2025.1.0
|
||||
|
||||
# homeassistant.components.lutron_caseta
|
||||
pylutron-caseta==0.26.0
|
||||
@@ -2014,7 +2017,7 @@ pyplaato==0.0.19
|
||||
pypoint==3.0.0
|
||||
|
||||
# homeassistant.components.portainer
|
||||
pyportainer==1.0.23
|
||||
pyportainer==1.0.27
|
||||
|
||||
# homeassistant.components.probe_plus
|
||||
pyprobeplus==1.1.2
|
||||
@@ -2176,9 +2179,6 @@ python-kasa[speedups]==0.10.2
|
||||
# homeassistant.components.linkplay
|
||||
python-linkplay==0.2.12
|
||||
|
||||
# homeassistant.components.matter
|
||||
python-matter-server==8.1.2
|
||||
|
||||
# homeassistant.components.melcloud
|
||||
python-melcloud==0.1.2
|
||||
|
||||
|
||||
@@ -203,11 +203,6 @@ FORBIDDEN_PACKAGE_EXCEPTIONS: dict[str, dict[str, set[str]]] = {
|
||||
"sense": {"sense-energy": {"async-timeout"}},
|
||||
"slimproto": {"aioslimproto": {"async-timeout"}},
|
||||
"surepetcare": {"surepy": {"async-timeout"}},
|
||||
"tami4": {
|
||||
# https://github.com/SeleniumHQ/selenium/issues/16943
|
||||
# tami4 > selenium > types*
|
||||
"selenium": {"types-certifi", "types-urllib3"},
|
||||
},
|
||||
"travisci": {
|
||||
# https://github.com/menegazzo/travispy seems to be unmaintained
|
||||
# and unused https://www.home-assistant.io/integrations/travisci
|
||||
|
||||
@@ -353,7 +353,7 @@ async def test_send_sticker_partial_error(
|
||||
assert mock_send_sticker.call_count == 2
|
||||
assert err.value.translation_key == "multiple_errors"
|
||||
assert err.value.translation_placeholders == {
|
||||
"errors": "`entity_id` notify.mock_title_mock_chat_1: Action failed. mock network error\n`entity_id` notify.mock_title_mock_chat_2: Action failed. mock network error"
|
||||
"errors": "`entity_id` notify.mock_title_mock_chat_1: mock network error\n`entity_id` notify.mock_title_mock_chat_2: mock network error"
|
||||
}
|
||||
|
||||
|
||||
@@ -364,7 +364,7 @@ async def test_send_sticker_error(hass: HomeAssistant, webhook_bot) -> None:
|
||||
) as mock_bot:
|
||||
mock_bot.side_effect = NetworkError("mock network error")
|
||||
|
||||
with pytest.raises(HomeAssistantError) as err:
|
||||
with pytest.raises(TelegramError) as err:
|
||||
await hass.services.async_call(
|
||||
DOMAIN,
|
||||
SERVICE_SEND_STICKER,
|
||||
@@ -377,8 +377,8 @@ async def test_send_sticker_error(hass: HomeAssistant, webhook_bot) -> None:
|
||||
await hass.async_block_till_done()
|
||||
|
||||
mock_bot.assert_called_once()
|
||||
assert err.value.translation_domain == DOMAIN
|
||||
assert err.value.translation_key == "action_failed"
|
||||
assert err.typename == "NetworkError"
|
||||
assert err.value.message == "mock network error"
|
||||
|
||||
|
||||
async def test_send_message_with_invalid_inline_keyboard(
|
||||
@@ -2264,7 +2264,7 @@ async def test_download_file_when_bot_failed_to_get_file(
|
||||
"homeassistant.components.telegram_bot.bot.Bot.get_file",
|
||||
AsyncMock(side_effect=TelegramError("failed to get file")),
|
||||
),
|
||||
pytest.raises(HomeAssistantError) as err,
|
||||
pytest.raises(TelegramError) as err,
|
||||
):
|
||||
await hass.services.async_call(
|
||||
DOMAIN,
|
||||
@@ -2273,7 +2273,9 @@ async def test_download_file_when_bot_failed_to_get_file(
|
||||
blocking=True,
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
assert err.value.translation_key == "action_failed"
|
||||
|
||||
assert err.typename == "TelegramError"
|
||||
assert err.value.message == "failed to get file"
|
||||
|
||||
|
||||
async def test_download_file_when_empty_file_path(
|
||||
|
||||
Reference in New Issue
Block a user