Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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 homeassistant/components/acer_projector/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,5 @@
"documentation": "https://www.home-assistant.io/integrations/acer_projector",
"iot_class": "local_polling",
"quality_scale": "legacy",
"requirements": ["serialx==1.7.1"]
"requirements": ["serialx==1.7.2"]
}
2 changes: 1 addition & 1 deletion homeassistant/components/alexa_devices/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,5 @@
"iot_class": "cloud_polling",
"loggers": ["aioamazondevices"],
"quality_scale": "platinum",
"requirements": ["aioamazondevices==13.4.3"]
"requirements": ["aioamazondevices==13.5.0"]
}
18 changes: 15 additions & 3 deletions homeassistant/components/duco/__init__.py
Original file line number Diff line number Diff line change
@@ -1,22 +1,34 @@
"""The Duco integration."""

from duco import DucoClient, build_ssl_context
import re

from duco_connectivity import DucoClient

from homeassistant.const import CONF_HOST
from homeassistant.core import HomeAssistant
from homeassistant.helpers import entity_registry as er
from homeassistant.helpers.aiohttp_client import async_get_clientsession

from .const import PLATFORMS
from .coordinator import DucoConfigEntry, DucoCoordinator

_REMOVED_SENSOR_RE = re.compile(r"_\d+_(box_)?temperature$")


async def async_setup_entry(hass: HomeAssistant, entry: DucoConfigEntry) -> bool:
"""Set up Duco from a config entry."""
ssl_context = await hass.async_add_executor_job(build_ssl_context)
# Remove entity registry entries for the temperature and box_temperature
# sensors that were removed when migrating to python-duco-connectivity.
entity_registry = er.async_get(hass)
for entity_entry in er.async_entries_for_config_entry(
entity_registry, entry.entry_id
):
if _REMOVED_SENSOR_RE.search(entity_entry.unique_id):
entity_registry.async_remove(entity_entry.entity_id)

client = DucoClient(
session=async_get_clientsession(hass),
host=entry.data[CONF_HOST],
ssl_context=ssl_context,
)

coordinator = DucoCoordinator(hass, entry, client)
Expand Down
6 changes: 2 additions & 4 deletions homeassistant/components/duco/config_flow.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
import logging
from typing import Any

from duco import DucoClient, build_ssl_context
from duco.exceptions import DucoConnectionError, DucoError
from duco_connectivity import DucoClient
from duco_connectivity.exceptions import DucoConnectionError, DucoError
import voluptuous as vol

from homeassistant.config_entries import ConfigFlow, ConfigFlowResult
Expand Down Expand Up @@ -158,11 +158,9 @@ async def _validate_input(self, host: str) -> tuple[str, str]:

Returns a tuple of (box_name, mac_address).
"""
ssl_context = await self.hass.async_add_executor_job(build_ssl_context)
client = DucoClient(
session=async_get_clientsession(self.hass),
host=host,
ssl_context=ssl_context,
)
board_info = await client.async_get_board_info()
lan_info = await client.async_get_lan_info()
Expand Down
6 changes: 3 additions & 3 deletions homeassistant/components/duco/coordinator.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@
from dataclasses import dataclass
import logging

from duco import DucoClient
from duco.exceptions import DucoConnectionError, DucoError
from duco.models import BoardInfo, Node
from duco_connectivity import DucoClient
from duco_connectivity.exceptions import DucoConnectionError, DucoError
from duco_connectivity.models import BoardInfo, Node

from homeassistant.config_entries import ConfigEntry
from homeassistant.core import HomeAssistant
Expand Down
4 changes: 2 additions & 2 deletions homeassistant/components/duco/diagnostics.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from dataclasses import asdict
from typing import Any

from duco.exceptions import DucoConnectionError
from duco_connectivity.exceptions import DucoConnectionError

from homeassistant.components.diagnostics import async_redact_data
from homeassistant.const import CONF_HOST
Expand Down Expand Up @@ -45,7 +45,7 @@ async def async_get_config_entry_diagnostics(
api_info_obj = await coordinator.client.async_get_api_info()
lan_info = await coordinator.client.async_get_lan_info()
duco_diags = await coordinator.client.async_get_diagnostics()
write_remaining = await coordinator.client.async_get_write_req_remaining()
write_remaining = await coordinator.client.async_get_write_requests_remaining()
except DucoConnectionError as err:
raise HomeAssistantError(
translation_domain=DOMAIN,
Expand Down
2 changes: 1 addition & 1 deletion homeassistant/components/duco/entity.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
"""Base entity for the Duco integration."""

from duco.models import Node
from duco_connectivity.models import Node

from homeassistant.const import ATTR_VIA_DEVICE
from homeassistant.helpers.device_registry import CONNECTION_NETWORK_MAC, DeviceInfo
Expand Down
4 changes: 2 additions & 2 deletions homeassistant/components/duco/fan.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@

import logging

from duco.exceptions import DucoError, DucoRateLimitError
from duco.models import Node, NodeType, VentilationState
from duco_connectivity.exceptions import DucoError, DucoRateLimitError
from duco_connectivity.models import Node, NodeType, VentilationState

from homeassistant.components.fan import FanEntity, FanEntityFeature
from homeassistant.core import HomeAssistant
Expand Down
4 changes: 2 additions & 2 deletions homeassistant/components/duco/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@
"documentation": "https://www.home-assistant.io/integrations/duco",
"integration_type": "hub",
"iot_class": "local_polling",
"loggers": ["duco"],
"loggers": ["duco_connectivity"],
"quality_scale": "platinum",
"requirements": ["python-duco-client==0.5.0"],
"requirements": ["python-duco-connectivity==0.2.0"],
"zeroconf": [
{
"name": "duco [[][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][]].*",
Expand Down
32 changes: 9 additions & 23 deletions homeassistant/components/duco/sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
from datetime import datetime
import logging

from duco.models import Node, NodeType, VentilationState
from duco_connectivity.models import Node, NodeType, VentilationState

from homeassistant.components.sensor import (
SensorDeviceClass,
Expand All @@ -18,7 +18,6 @@
PERCENTAGE,
SIGNAL_STRENGTH_DECIBELS_MILLIWATT,
EntityCategory,
UnitOfTemperature,
)
from homeassistant.core import HomeAssistant, callback
from homeassistant.helpers import device_registry as dr
Expand Down Expand Up @@ -54,20 +53,18 @@ class DucoBoxSensorEntityDescription(SensorEntityDescription):
key="ventilation_state",
translation_key="ventilation_state",
device_class=SensorDeviceClass.ENUM,
options=[s.lower() for s in VentilationState],
options=[
state.lower()
for state in VentilationState
if state != VentilationState.UNKNOWN
],
value_fn=lambda node: (
node.ventilation.state.lower() if node.ventilation else None
node.ventilation.state.lower()
if node.ventilation and node.ventilation.state != VentilationState.UNKNOWN
else None
),
node_types=(NodeType.BOX,),
),
DucoSensorEntityDescription(
key="temperature",
device_class=SensorDeviceClass.TEMPERATURE,
state_class=SensorStateClass.MEASUREMENT,
native_unit_of_measurement=UnitOfTemperature.CELSIUS,
value_fn=lambda node: node.sensor.temp if node.sensor else None,
node_types=(NodeType.UCCO2, NodeType.BSRH, NodeType.UCRH),
),
DucoSensorEntityDescription(
key="target_flow_level",
translation_key="target_flow_level",
Expand All @@ -92,17 +89,6 @@ class DucoBoxSensorEntityDescription(SensorEntityDescription):
),
node_types=(NodeType.BOX,),
),
DucoSensorEntityDescription(
key="box_temperature",
translation_key="box_temperature",
device_class=SensorDeviceClass.TEMPERATURE,
state_class=SensorStateClass.MEASUREMENT,
native_unit_of_measurement=UnitOfTemperature.CELSIUS,
entity_category=EntityCategory.DIAGNOSTIC,
entity_registry_enabled_default=False,
value_fn=lambda node: node.sensor.temp if node.sensor else None,
node_types=(NodeType.BOX,),
),
DucoSensorEntityDescription(
key="co2",
device_class=SensorDeviceClass.CO2,
Expand Down
3 changes: 0 additions & 3 deletions homeassistant/components/duco/strings.json
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,6 @@
}
},
"sensor": {
"box_temperature": {
"name": "Box temperature"
},
"iaq_co2": {
"name": "CO2 air quality index"
},
Expand Down
6 changes: 4 additions & 2 deletions homeassistant/components/duco/system_health.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

from typing import Any

from duco.exceptions import DucoConnectionError
from duco_connectivity.exceptions import DucoConnectionError

from homeassistant.components import system_health
from homeassistant.core import HomeAssistant, callback
Expand All @@ -24,7 +24,9 @@ async def _async_get_write_requests_remaining(
) -> int | dict[str, str]:
"""Get the remaining write-request quota for system health."""
try:
return await config_entry.runtime_data.client.async_get_write_req_remaining()
return (
await config_entry.runtime_data.client.async_get_write_requests_remaining()
)
except DucoConnectionError:
return {"type": "failed", "error": "unreachable"}

Expand Down
2 changes: 1 addition & 1 deletion homeassistant/components/imgw_pib/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,5 @@
"integration_type": "service",
"iot_class": "cloud_polling",
"quality_scale": "platinum",
"requirements": ["imgw_pib==2.1.1"]
"requirements": ["imgw_pib==2.1.2"]
}
4 changes: 4 additions & 0 deletions homeassistant/components/mqtt/vacuum.py
Original file line number Diff line number Diff line change
Expand Up @@ -249,6 +249,10 @@ def _strings_to_services(
supported_feature_strings: list[str] = config[CONF_SUPPORTED_FEATURES]
self._attr_supported_features = _strings_to_services(
supported_feature_strings, STRING_TO_SERVICE
) | (
self.supported_features & VacuumEntityFeature.CLEAN_AREA
if CONF_CLEAN_SEGMENTS_COMMAND_TOPIC in config
else 0
)
self._clean_segments_command_topic = config.get(
CONF_CLEAN_SEGMENTS_COMMAND_TOPIC
Expand Down
7 changes: 5 additions & 2 deletions homeassistant/components/prusalink/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
from homeassistant.helpers import issue_registry as ir
from homeassistant.helpers.httpx_client import get_async_client

from .config_flow import ConfigFlow
from .config_flow import PrusaLinkConfigFlow
from .const import DOMAIN
from .coordinator import (
InfoUpdateCoordinator,
Expand Down Expand Up @@ -67,7 +67,10 @@ async def async_setup_entry(hass: HomeAssistant, entry: PrusaLinkConfigEntry) ->

async def async_migrate_entry(hass: HomeAssistant, config_entry: ConfigEntry) -> bool:
"""Migrate old entry."""
if config_entry.version > ConfigFlow.VERSION:
if (config_entry.version, config_entry.minor_version) > (
PrusaLinkConfigFlow.VERSION,
PrusaLinkConfigFlow.MINOR_VERSION,
):
# This means the user has downgraded from a future version
return False

Expand Down
2 changes: 1 addition & 1 deletion homeassistant/components/qbittorrent/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",
"loggers": ["qbittorrent"],
"requirements": ["qbittorrent-api==2024.9.67"]
"requirements": ["qbittorrent-api==2026.5.1"]
}
31 changes: 15 additions & 16 deletions homeassistant/components/sensirion_ble/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,26 +12,26 @@
from homeassistant.const import Platform
from homeassistant.core import HomeAssistant

from .const import DOMAIN

PLATFORMS: list[Platform] = [Platform.SENSOR]

_LOGGER = logging.getLogger(__name__)

type SensirionBluetoothConfigEntry = ConfigEntry[PassiveBluetoothProcessorCoordinator]


async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
async def async_setup_entry(
hass: HomeAssistant, entry: SensirionBluetoothConfigEntry
) -> bool:
"""Set up Sensirion BLE device from a config entry."""
address = entry.unique_id
assert address is not None
data = SensirionBluetoothDeviceData()
coordinator = hass.data.setdefault(DOMAIN, {})[entry.entry_id] = (
PassiveBluetoothProcessorCoordinator(
hass,
_LOGGER,
address=address,
mode=BluetoothScanningMode.ACTIVE,
update_method=data.update,
)
entry.runtime_data = coordinator = PassiveBluetoothProcessorCoordinator(
hass,
_LOGGER,
address=address,
mode=BluetoothScanningMode.ACTIVE,
update_method=data.update,
)
await hass.config_entries.async_forward_entry_setups(entry, PLATFORMS)
entry.async_on_unload(
Expand All @@ -40,9 +40,8 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
return True


async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
async def async_unload_entry(
hass: HomeAssistant, entry: SensirionBluetoothConfigEntry
) -> bool:
"""Unload a config entry."""
if unload_ok := await hass.config_entries.async_unload_platforms(entry, PLATFORMS):
hass.data[DOMAIN].pop(entry.entry_id)

return unload_ok
return await hass.config_entries.async_unload_platforms(entry, PLATFORMS)
12 changes: 3 additions & 9 deletions homeassistant/components/sensirion_ble/sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,10 @@
Units,
)

from homeassistant import config_entries
from homeassistant.components.bluetooth.passive_update_processor import (
PassiveBluetoothDataProcessor,
PassiveBluetoothDataUpdate,
PassiveBluetoothEntityKey,
PassiveBluetoothProcessorCoordinator,
PassiveBluetoothProcessorEntity,
)
from homeassistant.components.sensor import (
Expand All @@ -31,7 +29,7 @@
from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback
from homeassistant.helpers.sensor import sensor_device_info_to_hass_device_info

from .const import DOMAIN
from . import SensirionBluetoothConfigEntry

SENSOR_DESCRIPTIONS: dict[
tuple[SSDSensorDeviceClass, Units | None], SensorEntityDescription
Expand Down Expand Up @@ -103,15 +101,11 @@ def sensor_update_to_bluetooth_data_update(

async def async_setup_entry(
hass: HomeAssistant,
entry: config_entries.ConfigEntry,
entry: SensirionBluetoothConfigEntry,
async_add_entities: AddConfigEntryEntitiesCallback,
) -> None:
"""Set up the Sensirion BLE sensors."""
# Uses legacy hass.data[DOMAIN] pattern
# pylint: disable-next=hass-use-runtime-data
coordinator: PassiveBluetoothProcessorCoordinator = hass.data[DOMAIN][
entry.entry_id
]
coordinator = entry.runtime_data
processor = PassiveBluetoothDataProcessor(sensor_update_to_bluetooth_data_update)
entry.async_on_unload(
processor.async_add_entities_listener(
Expand Down
2 changes: 1 addition & 1 deletion homeassistant/components/serial/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,5 @@
"codeowners": ["@fabaff"],
"documentation": "https://www.home-assistant.io/integrations/serial",
"iot_class": "local_polling",
"requirements": ["serialx==1.7.1"]
"requirements": ["serialx==1.7.2"]
}
2 changes: 1 addition & 1 deletion homeassistant/components/upb/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,5 @@
"documentation": "https://www.home-assistant.io/integrations/upb",
"iot_class": "local_push",
"loggers": ["upb_lib"],
"requirements": ["upb-lib==0.6.1"]
"requirements": ["upb-lib==0.7.0"]
}
2 changes: 1 addition & 1 deletion homeassistant/components/usb/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,5 @@
"integration_type": "system",
"iot_class": "local_push",
"quality_scale": "internal",
"requirements": ["aiousbwatcher==1.1.2", "serialx==1.7.1"]
"requirements": ["aiousbwatcher==1.1.2", "serialx==1.7.2"]
}
2 changes: 1 addition & 1 deletion homeassistant/package_constraints.txt
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ PyTurboJPEG==1.8.3
PyYAML==6.0.3
requests==2.33.1
securetar==2026.4.1
serialx==1.7.1
serialx==1.7.2
SQLAlchemy==2.0.49
standard-aifc==3.13.0
standard-telnetlib==3.13.0
Expand Down
Loading
Loading