Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
da537dd
Add integration_type device to steamist (#163640)
joostlek Feb 20, 2026
6ce2898
Add integration_type service to syncthing (#163651)
joostlek Feb 20, 2026
e7e8c7a
Add integration_type device to togrill (#163669)
joostlek Feb 20, 2026
2a03d95
Add integration_type service to telegram_bot (#163660)
joostlek Feb 20, 2026
7cd48ef
Add integration_type device to tami4 (#163659)
joostlek Feb 20, 2026
b6e83d2
Add integration_type device to syncthru (#163658)
joostlek Feb 20, 2026
19b1fc6
Add integration_type hub to tibber (#163665)
joostlek Feb 20, 2026
14b6269
Add integration_type device to thermopro (#163664)
joostlek Feb 20, 2026
08adb88
Add integration_type device to thermobeacon (#163663)
joostlek Feb 20, 2026
430f064
Add integration_type device to tesla_wall_connector (#163662)
joostlek Feb 20, 2026
3f6bfa9
Add integration_type hub to tellduslive (#163661)
joostlek Feb 20, 2026
02058af
Add integration_type service to trafikverket_weatherstation (#163677)
joostlek Feb 20, 2026
ed9ad95
Add integration_type service to trafikverket_train (#163676)
joostlek Feb 20, 2026
35e770b
Add integration_type service to trafikverket_ferry (#163675)
joostlek Feb 20, 2026
46b0eae
Add integration_type service to trafikverket_camera (#163674)
joostlek Feb 20, 2026
541cc80
Add integration_type hub to totalconnect (#163672)
joostlek Feb 20, 2026
debf07e
Add integration_type device to toon (#163671)
joostlek Feb 20, 2026
3c1b7ad
Add integration_type device to tolo (#163670)
joostlek Feb 20, 2026
cd26901
Add integration_type service to todoist (#163668)
joostlek Feb 20, 2026
0711176
Add integration_type device to tilt_ble (#163666)
joostlek Feb 20, 2026
f020948
Add integration_type hub to tradfri (#163673)
joostlek Feb 20, 2026
eeb7ce3
Improve type hints in homematic hub (#163614)
epenet Feb 20, 2026
f645945
Add integration_type hub to surepetcare (#163646)
joostlek Feb 20, 2026
6115a4c
Use shorthand attributes in swiss_hydrological_data (#163607)
epenet Feb 20, 2026
6ecbaa9
Fix hassfest requirements check (#163681)
cdce8p Feb 20, 2026
aa2bb44
Bump pyportainer 1.0.27 (#163613)
erwindouna Feb 20, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
12 changes: 8 additions & 4 deletions homeassistant/components/homematic/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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),
Expand All @@ -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],
Expand All @@ -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."""
Expand Down Expand Up @@ -294,7 +298,7 @@ def _hm_service_virtualkey(service: ServiceCall) -> None:

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]

Expand Down
13 changes: 7 additions & 6 deletions homeassistant/components/homematic/entity.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
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
Expand Down Expand Up @@ -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)
Expand All @@ -216,12 +217,12 @@ def __init__(self, hass, homematic, name):
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

Expand All @@ -231,7 +232,7 @@ def extra_state_attributes(self) -> dict[str, Any]:
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"

Expand Down
2 changes: 1 addition & 1 deletion homeassistant/components/portainer/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,5 @@
"integration_type": "service",
"iot_class": "local_polling",
"quality_scale": "bronze",
"requirements": ["pyportainer==1.0.23"]
"requirements": ["pyportainer==1.0.27"]
}
1 change: 1 addition & 0 deletions homeassistant/components/steamist/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -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"]
Expand Down
1 change: 1 addition & 0 deletions homeassistant/components/surepetcare/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -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"]
Expand Down
66 changes: 24 additions & 42 deletions homeassistant/components/swiss_hydrological_data/sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

from datetime import timedelta
import logging
from typing import Any
from typing import TYPE_CHECKING, Any

from swisshydrodata import SwissHydroData
import voluptuous as vol
Expand Down Expand Up @@ -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()
Expand All @@ -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."""
Expand All @@ -146,32 +132,28 @@ def extra_state_attributes(self) -> dict[str, Any]:

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()
Expand Down
1 change: 1 addition & 0 deletions homeassistant/components/syncthing/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -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"]
Expand Down
1 change: 1 addition & 0 deletions homeassistant/components/syncthru/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -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"],
Expand Down
1 change: 1 addition & 0 deletions homeassistant/components/tami4/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -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"]
}
1 change: 1 addition & 0 deletions homeassistant/components/telegram_bot/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
1 change: 1 addition & 0 deletions homeassistant/components/tellduslive/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -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"]
}
Original file line number Diff line number Diff line change
Expand Up @@ -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"]
Expand Down
1 change: 1 addition & 0 deletions homeassistant/components/thermobeacon/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -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"]
}
1 change: 1 addition & 0 deletions homeassistant/components/thermopro/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -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"]
}
1 change: 1 addition & 0 deletions homeassistant/components/tibber/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -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"]
Expand Down
1 change: 1 addition & 0 deletions homeassistant/components/tilt_ble/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -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"]
}
1 change: 1 addition & 0 deletions homeassistant/components/todoist/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -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"]
Expand Down
1 change: 1 addition & 0 deletions homeassistant/components/togrill/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
1 change: 1 addition & 0 deletions homeassistant/components/tolo/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -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"]
Expand Down
1 change: 1 addition & 0 deletions homeassistant/components/toon/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -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"]
Expand Down
1 change: 1 addition & 0 deletions homeassistant/components/totalconnect/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -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"]
Expand Down
1 change: 1 addition & 0 deletions homeassistant/components/tradfri/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
"homekit": {
"models": ["TRADFRI"]
},
"integration_type": "hub",
"iot_class": "local_polling",
"loggers": ["pytradfri"],
"requirements": ["pytradfri[async]==9.0.1"]
Expand Down
1 change: 1 addition & 0 deletions homeassistant/components/trafikverket_camera/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -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"]
Expand Down
1 change: 1 addition & 0 deletions homeassistant/components/trafikverket_ferry/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -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"]
Expand Down
1 change: 1 addition & 0 deletions homeassistant/components/trafikverket_train/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -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"]
Expand Down
Loading
Loading