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
6 changes: 3 additions & 3 deletions .github/workflows/builder.yml
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ jobs:
run: find ./homeassistant/components/*/translations -name "*.json" | tar zcvf translations.tar.gz -T -

- name: Upload translations
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0
with:
name: translations
path: translations.tar.gz
Expand Down Expand Up @@ -175,7 +175,7 @@ jobs:
sed -i "s|pykrakenapi|# pykrakenapi|g" requirements_all.txt

- name: Download translations
uses: actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0 # v5.0.0
uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6.0.0
with:
name: translations

Expand Down Expand Up @@ -464,7 +464,7 @@ jobs:
python-version: ${{ env.DEFAULT_PYTHON }}

- name: Download translations
uses: actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0 # v5.0.0
uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6.0.0
with:
name: translations

Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -535,7 +535,7 @@ jobs:
python --version
uv pip freeze >> pip_freeze.txt
- name: Upload pip_freeze artifact
uses: &actions-upload-artifact actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
uses: &actions-upload-artifact actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0
with:
name: pip-freeze-${{ matrix.python-version }}
path: pip_freeze.txt
Expand Down Expand Up @@ -867,7 +867,7 @@ jobs:
run: |
echo "::add-matcher::.github/workflows/matchers/pytest-slow.json"
- name: Download pytest_buckets
uses: &actions-download-artifact actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0 # v5.0.0
uses: &actions-download-artifact actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6.0.0
with:
name: pytest_buckets
- &compile-english-translations
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/codeql.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,11 @@ jobs:
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0

- name: Initialize CodeQL
uses: github/codeql-action/init@16140ae1a102900babc80a33c44059580f687047 # v4.30.9
uses: github/codeql-action/init@4e94bd11f71e507f7f87df81788dff88d1dacbfb # v4.31.0
with:
languages: python

- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@16140ae1a102900babc80a33c44059580f687047 # v4.30.9
uses: github/codeql-action/analyze@4e94bd11f71e507f7f87df81788dff88d1dacbfb # v4.31.0
with:
category: "/language:python"
4 changes: 2 additions & 2 deletions .github/workflows/wheels.yml
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ jobs:
) > build_constraints.txt

- name: Upload env_file
uses: &actions-upload-artifact actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
uses: &actions-upload-artifact actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0
with:
name: env_file
path: ./.env_file
Expand Down Expand Up @@ -150,7 +150,7 @@ jobs:

- &download-env-file
name: Download env_file
uses: &actions-download-artifact actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0 # v5.0.0
uses: &actions-download-artifact actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6.0.0
with:
name: env_file

Expand Down
2 changes: 2 additions & 0 deletions CODEOWNERS

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 3 additions & 3 deletions homeassistant/components/axis/config_flow.py
Original file line number Diff line number Diff line change
Expand Up @@ -109,12 +109,12 @@ async def async_step_user(

if self.source == SOURCE_REAUTH:
self._abort_if_unique_id_mismatch()
return self.async_update_reload_and_abort(
return self.async_update_and_abort(
self._get_reauth_entry(), data_updates=config
)
if self.source == SOURCE_RECONFIGURE:
self._abort_if_unique_id_mismatch()
return self.async_update_reload_and_abort(
return self.async_update_and_abort(
self._get_reconfigure_entry(), data_updates=config
)
self._abort_if_unique_id_configured()
Expand Down Expand Up @@ -248,7 +248,7 @@ async def _process_discovered_device(
await self.async_set_unique_id(discovery_info[CONF_MAC])

self._abort_if_unique_id_configured(
updates={CONF_HOST: discovery_info[CONF_HOST]}
updates={CONF_HOST: discovery_info[CONF_HOST]}, reload_on_update=False
)

self.context.update(
Expand Down
3 changes: 3 additions & 0 deletions homeassistant/components/cert_expiry/config_flow.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
from .const import DEFAULT_PORT, DOMAIN
from .errors import (
ConnectionRefused,
ConnectionReset,
ConnectionTimeout,
ResolveFailed,
ValidationFailure,
Expand Down Expand Up @@ -49,6 +50,8 @@ async def _test_connection(
self._errors[CONF_HOST] = "connection_timeout"
except ConnectionRefused:
self._errors[CONF_HOST] = "connection_refused"
except ConnectionReset:
self._errors[CONF_HOST] = "connection_reset"
except ValidationFailure:
return True
else:
Expand Down
4 changes: 4 additions & 0 deletions homeassistant/components/cert_expiry/errors.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,7 @@ class ConnectionTimeout(TemporaryFailure):

class ConnectionRefused(TemporaryFailure):
"""Network connection refused."""


class ConnectionReset(TemporaryFailure):
"""Network connection reset."""
3 changes: 3 additions & 0 deletions homeassistant/components/cert_expiry/helper.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
from .const import TIMEOUT
from .errors import (
ConnectionRefused,
ConnectionReset,
ConnectionTimeout,
ResolveFailed,
ValidationFailure,
Expand Down Expand Up @@ -58,6 +59,8 @@ async def get_cert_expiry_timestamp(
raise ConnectionRefused(
f"Connection refused by server: {hostname}:{port}"
) from err
except ConnectionResetError as err:
raise ConnectionReset(f"Connection reset by server: {hostname}:{port}") from err
except ssl.CertificateError as err:
raise ValidationFailure(err.verify_message) from err
except ssl.SSLError as err:
Expand Down
3 changes: 2 additions & 1 deletion homeassistant/components/cert_expiry/strings.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@
"error": {
"resolve_failed": "This host cannot be resolved",
"connection_timeout": "Timeout when connecting to this host",
"connection_refused": "Connection refused when connecting to host"
"connection_refused": "Connection refused when connecting to host",
"connection_reset": "Connection reset when connecting to host"
},
"abort": {
"already_configured": "[%key:common::config_flow::abort::already_configured_service%]",
Expand Down
9 changes: 6 additions & 3 deletions homeassistant/components/deconz/config_flow.py
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,8 @@ async def _create_entry(self) -> ConfigFlowResult:
CONF_HOST: self.host,
CONF_PORT: self.port,
CONF_API_KEY: self.api_key,
}
},
reload_on_update=False,
)

except TimeoutError:
Expand Down Expand Up @@ -231,7 +232,8 @@ async def async_step_ssdp(
updates={
CONF_HOST: self.host,
CONF_PORT: self.port,
}
},
reload_on_update=False,
)

self.context.update(
Expand Down Expand Up @@ -265,7 +267,8 @@ async def async_step_hassio(
CONF_HOST: self.host,
CONF_PORT: self.port,
CONF_API_KEY: self.api_key,
}
},
reload_on_update=False,
)

self.context["configuration_url"] = HASSIO_CONFIGURATION_URL
Expand Down
2 changes: 1 addition & 1 deletion homeassistant/components/homematicip_cloud/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/homematicip_cloud",
"iot_class": "cloud_push",
"loggers": ["homematicip"],
"requirements": ["homematicip==2.3.0"]
"requirements": ["homematicip==2.3.1"]
}
32 changes: 31 additions & 1 deletion homeassistant/components/homewizard/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
from homeassistant.const import CONF_IP_ADDRESS, CONF_TOKEN
from homeassistant.core import HomeAssistant
from homeassistant.exceptions import ConfigEntryNotReady
from homeassistant.helpers import device_registry as dr
from homeassistant.helpers.aiohttp_client import async_get_clientsession
from homeassistant.helpers.issue_registry import IssueSeverity, async_create_issue

Expand Down Expand Up @@ -71,6 +72,25 @@ async def async_unload_entry(hass: HomeAssistant, entry: HomeWizardConfigEntry)
return await hass.config_entries.async_unload_platforms(entry, PLATFORMS)


def get_main_device(
hass: HomeAssistant, entry: HomeWizardConfigEntry
) -> dr.DeviceEntry | None:
"""Helper function to get the main device for the config entry."""
device_registry = dr.async_get(hass)
device_entries = dr.async_entries_for_config_entry(
device_registry, config_entry_id=entry.entry_id
)

if not device_entries:
return None

# Get first device that is not a sub-device, as this is the main device in HomeWizard
# This is relevant for the P1 Meter which may create sub-devices for external utility meters
return next(
(device for device in device_entries if device.via_device_id is None), None
)


async def async_check_v2_support_and_create_issue(
hass: HomeAssistant, entry: HomeWizardConfigEntry
) -> None:
Expand All @@ -79,6 +99,16 @@ async def async_check_v2_support_and_create_issue(
if not await has_v2_api(entry.data[CONF_IP_ADDRESS], async_get_clientsession(hass)):
return

title = entry.title

# Try to get the name from the device registry
# This is to make it clearer which device needs reconfiguration, as the config entry title is kept default most of the time
if main_device := get_main_device(hass, entry):
device_name = main_device.name_by_user or main_device.name

if device_name and entry.title != device_name:
title = f"{entry.title} ({device_name})"

async_create_issue(
hass,
DOMAIN,
Expand All @@ -88,7 +118,7 @@ async def async_check_v2_support_and_create_issue(
learn_more_url="https://home-assistant.io/integrations/homewizard/#which-button-do-i-need-to-press-to-configure-the-device",
translation_key="migrate_to_v2_api",
translation_placeholders={
"title": entry.title,
"title": title,
},
severity=IssueSeverity.WARNING,
data={"entry_id": entry.entry_id},
Expand Down
2 changes: 1 addition & 1 deletion homeassistant/components/homewizard/strings.json
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,7 @@
},
"issues": {
"migrate_to_v2_api": {
"title": "Update authentication method",
"title": "Update the authentication method for {title}",
"fix_flow": {
"step": {
"confirm": {
Expand Down
12 changes: 11 additions & 1 deletion homeassistant/components/matter/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,14 @@
from homeassistant.const import CONF_URL, EVENT_HOMEASSISTANT_STOP
from homeassistant.core import Event, HomeAssistant, callback
from homeassistant.exceptions import ConfigEntryNotReady
from homeassistant.helpers import device_registry as dr
from homeassistant.helpers import config_validation as cv, device_registry as dr
from homeassistant.helpers.aiohttp_client import async_get_clientsession
from homeassistant.helpers.issue_registry import (
IssueSeverity,
async_create_issue,
async_delete_issue,
)
from homeassistant.helpers.typing import ConfigType

from .adapter import MatterAdapter
from .addon import get_addon_manager
Expand All @@ -40,10 +41,13 @@
node_from_ha_device_id,
)
from .models import MatterDeviceInfo
from .services import async_setup_services

CONNECT_TIMEOUT = 10
LISTEN_READY_TIMEOUT = 30

CONFIG_SCHEMA = cv.config_entry_only_config_schema(DOMAIN)


@callback
@cache
Expand All @@ -64,6 +68,12 @@ def get_matter_device_info(
)


async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
"""Set up the Matter integration services."""
async_setup_services(hass)
return True


async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
"""Set up Matter from a config entry."""
if use_addon := entry.data.get(CONF_USE_ADDON):
Expand Down
14 changes: 14 additions & 0 deletions homeassistant/components/matter/button.py
Original file line number Diff line number Diff line change
Expand Up @@ -155,4 +155,18 @@ async def async_press(self) -> None:
required_attributes=(clusters.SmokeCoAlarm.Attributes.AcceptedCommandList,),
value_contains=clusters.SmokeCoAlarm.Commands.SelfTestRequest.command_id,
),
MatterDiscoverySchema(
platform=Platform.BUTTON,
entity_description=MatterButtonEntityDescription(
key="WaterHeaterManagementCancelBoost",
translation_key="cancel_boost",
command=clusters.WaterHeaterManagement.Commands.CancelBoost,
),
entity_class=MatterCommandButton,
required_attributes=(
clusters.WaterHeaterManagement.Attributes.AcceptedCommandList,
),
value_contains=clusters.WaterHeaterManagement.Commands.CancelBoost.command_id,
allow_multi=True, # Also used in water_heater
),
]
5 changes: 5 additions & 0 deletions homeassistant/components/matter/icons.json
Original file line number Diff line number Diff line change
Expand Up @@ -163,5 +163,10 @@
"default": "mdi:shield-lock"
}
}
},
"services": {
"water_heater_boost": {
"service": "mdi:water-boiler"
}
}
}
38 changes: 38 additions & 0 deletions homeassistant/components/matter/services.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
"""Services for Matter devices."""

from __future__ import annotations

import voluptuous as vol

from homeassistant.components.water_heater import DOMAIN as WATER_HEATER_DOMAIN
from homeassistant.core import HomeAssistant, callback
from homeassistant.helpers import config_validation as cv, service

from .const import DOMAIN

ATTR_DURATION = "duration"
ATTR_EMERGENCY_BOOST = "emergency_boost"
ATTR_TEMPORARY_SETPOINT = "temporary_setpoint"

SERVICE_WATER_HEATER_BOOST = "water_heater_boost"


@callback
def async_setup_services(hass: HomeAssistant) -> None:
"""Register the Matter services."""

service.async_register_platform_entity_service(
hass,
DOMAIN,
SERVICE_WATER_HEATER_BOOST,
entity_domain=WATER_HEATER_DOMAIN,
schema={
# duration >=1
vol.Required(ATTR_DURATION): vol.All(vol.Coerce(int), vol.Range(min=1)),
vol.Optional(ATTR_EMERGENCY_BOOST): cv.boolean,
vol.Optional(ATTR_TEMPORARY_SETPOINT): vol.All(
vol.Coerce(int), vol.Range(min=30, max=65)
),
},
func="async_set_boost",
)
Loading
Loading