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 .github/workflows/builder.yml
Original file line number Diff line number Diff line change
Expand Up @@ -324,7 +324,7 @@ jobs:
uses: actions/[email protected]

- name: Install Cosign
uses: sigstore/cosign-installer@v3.8.2
uses: sigstore/cosign-installer@v3.9.1
with:
cosign-release: "v2.2.3"

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.

2 changes: 1 addition & 1 deletion homeassistant/components/conversation/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/conversation",
"integration_type": "system",
"quality_scale": "internal",
"requirements": ["hassil==2.2.3", "home-assistant-intents==2025.6.10"]
"requirements": ["hassil==2.2.3", "home-assistant-intents==2025.6.23"]
}
2 changes: 1 addition & 1 deletion homeassistant/components/frontend/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,5 +20,5 @@
"documentation": "https://www.home-assistant.io/integrations/frontend",
"integration_type": "system",
"quality_scale": "internal",
"requirements": ["home-assistant-frontend==20250531.3"]
"requirements": ["home-assistant-frontend==20250531.4"]
}
10 changes: 1 addition & 9 deletions homeassistant/components/hassio/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
import struct
from typing import Any, NamedTuple

import aiofiles
from aiohasupervisor import SupervisorError
import voluptuous as vol

Expand Down Expand Up @@ -239,12 +238,6 @@ def _is_32_bit() -> bool:
return size * 8 == 32


async def _get_arch() -> str:
async with aiofiles.open("/etc/apk/arch") as arch_file:
raw_arch = await arch_file.read()
return {"x86": "i386"}.get(raw_arch, raw_arch)


class APIEndpointSettings(NamedTuple):
"""Settings for API endpoint."""

Expand Down Expand Up @@ -566,15 +559,14 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
await coordinator.async_config_entry_first_refresh()
hass.data[ADDONS_COORDINATOR] = coordinator

arch = await _get_arch()

def deprecated_setup_issue() -> None:
os_info = get_os_info(hass)
info = get_info(hass)
if os_info is None or info is None:
return
is_haos = info.get("hassos") is not None
board = os_info.get("board")
arch = info.get("arch", "unknown")
unsupported_board = board in {"tinker", "odroid-xu4", "rpi2"}
unsupported_os_on_board = board in {"rpi3", "rpi4"}
if is_haos and (unsupported_board or unsupported_os_on_board):
Expand Down
90 changes: 45 additions & 45 deletions homeassistant/components/homeassistant/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
import struct
from typing import Any

import aiofiles
import voluptuous as vol

from homeassistant import config as conf_util, core_config
Expand All @@ -18,6 +17,7 @@
ATTR_ENTITY_ID,
ATTR_LATITUDE,
ATTR_LONGITUDE,
EVENT_HOMEASSISTANT_STARTED,
RESTART_EXIT_CODE,
SERVICE_RELOAD,
SERVICE_SAVE_PERSISTENT_STATES,
Expand All @@ -26,6 +26,7 @@
SERVICE_TURN_ON,
)
from homeassistant.core import (
Event,
HomeAssistant,
ServiceCall,
ServiceResponse,
Expand Down Expand Up @@ -101,12 +102,6 @@ def _is_32_bit() -> bool:
return size * 8 == 32


async def _get_arch() -> str:
async with aiofiles.open("/etc/apk/arch") as arch_file:
raw_arch = (await arch_file.read()).strip()
return {"x86": "i386", "x86_64": "amd64"}.get(raw_arch, raw_arch)


async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool: # noqa: C901
"""Set up general services related to Home Assistant."""

Expand Down Expand Up @@ -411,45 +406,50 @@ async def async_handle_reload_all(call: ServiceCall) -> None:
hass.data[DATA_EXPOSED_ENTITIES] = exposed_entities
async_set_stop_handler(hass, _async_stop)

info = await async_get_system_info(hass)
async def _async_check_deprecation(event: Event) -> None:
"""Check and create deprecation issues after startup."""
info = await async_get_system_info(hass)

installation_type = info["installation_type"][15:]
if installation_type in {"Core", "Container"}:
deprecated_method = installation_type == "Core"
bit32 = _is_32_bit()
arch = info["arch"]
if bit32 and installation_type == "Container":
arch = info.get("container_arch", arch)
ir.async_create_issue(
hass,
DOMAIN,
"deprecated_container",
learn_more_url=DEPRECATION_URL,
is_fixable=False,
severity=IssueSeverity.WARNING,
translation_key="deprecated_container",
translation_placeholders={"arch": arch},
)
deprecated_architecture = bit32 and installation_type != "Container"
if deprecated_method or deprecated_architecture:
issue_id = "deprecated"
if deprecated_method:
issue_id += "_method"
if deprecated_architecture:
issue_id += "_architecture"
ir.async_create_issue(
hass,
DOMAIN,
issue_id,
learn_more_url=DEPRECATION_URL,
is_fixable=False,
severity=IssueSeverity.WARNING,
translation_key=issue_id,
translation_placeholders={
"installation_type": installation_type,
"arch": arch,
},
)

installation_type = info["installation_type"][15:]
if installation_type in {"Core", "Container"}:
deprecated_method = installation_type == "Core"
bit32 = _is_32_bit()
arch = info["arch"]
if bit32 and installation_type == "Container":
arch = await _get_arch()
ir.async_create_issue(
hass,
DOMAIN,
"deprecated_container",
learn_more_url=DEPRECATION_URL,
is_fixable=False,
severity=IssueSeverity.WARNING,
translation_key="deprecated_container",
translation_placeholders={"arch": arch},
)
deprecated_architecture = bit32 and installation_type != "Container"
if deprecated_method or deprecated_architecture:
issue_id = "deprecated"
if deprecated_method:
issue_id += "_method"
if deprecated_architecture:
issue_id += "_architecture"
ir.async_create_issue(
hass,
DOMAIN,
issue_id,
learn_more_url=DEPRECATION_URL,
is_fixable=False,
severity=IssueSeverity.WARNING,
translation_key=issue_id,
translation_placeholders={
"installation_type": installation_type,
"arch": arch,
},
)
# Delay deprecation check to make sure installation method is determined correctly
hass.bus.async_listen_once(EVENT_HOMEASSISTANT_STARTED, _async_check_deprecation)

return True

Expand Down
1 change: 1 addition & 0 deletions homeassistant/components/homeassistant/strings.json
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,7 @@
"info": {
"arch": "CPU architecture",
"config_dir": "Configuration directory",
"container_arch": "Container architecture",
"dev": "Development",
"docker": "Docker",
"hassio": "Supervisor",
Expand Down
1 change: 1 addition & 0 deletions homeassistant/components/homeassistant/system_health.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ async def system_health_info(hass: HomeAssistant) -> dict[str, Any]:
"dev": info.get("dev"),
"hassio": info.get("hassio"),
"docker": info.get("docker"),
"container_arch": info.get("container_arch"),
"user": info.get("user"),
"virtualenv": info.get("virtualenv"),
"python_version": info.get("python_version"),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
"documentation": "https://www.home-assistant.io/integrations/homeassistant_hardware",
"integration_type": "system",
"requirements": [
"universal-silabs-flasher==0.0.30",
"universal-silabs-flasher==0.0.31",
"ha-silabs-firmware-client==0.2.0"
]
}
2 changes: 1 addition & 1 deletion homeassistant/components/homewizard/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,6 @@
"iot_class": "local_polling",
"loggers": ["homewizard_energy"],
"quality_scale": "platinum",
"requirements": ["python-homewizard-energy==9.1.1"],
"requirements": ["python-homewizard-energy==9.2.0"],
"zeroconf": ["_hwenergy._tcp.local.", "_homewizard._tcp.local."]
}
2 changes: 1 addition & 1 deletion homeassistant/components/homewizard/strings.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
},
"authorize": {
"title": "Authorize",
"description": "Press the button on the HomeWizard Energy device, then select the button below."
"description": "Press the button on the HomeWizard Energy device for two seconds, then select the button below."
},
"reconfigure": {
"description": "Update configuration for {title}.",
Expand Down
3 changes: 1 addition & 2 deletions homeassistant/components/playstation_network/config_flow.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,7 @@ async def async_step_user(
npsso = parse_npsso_token(user_input[CONF_NPSSO])
except PSNAWPInvalidTokenError:
errors["base"] = "invalid_account"

if npsso:
else:
psn = PlaystationNetwork(self.hass, npsso)
try:
user: User = await psn.get_user()
Expand Down
2 changes: 1 addition & 1 deletion homeassistant/components/playstation_network/strings.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
"npsso": "NPSSO token"
},
"data_description": {
"npsso": "The NPSSO token is generated during successful login of your PlayStation Network account and is used to authenticate your requests from with Home Assistant."
"npsso": "The NPSSO token is generated upon successful login of your PlayStation Network account and is used to authenticate your requests within Home Assistant."
},
"description": "To obtain your NPSSO token, log in to your [PlayStation account]({psn_link}) first. Then [click here]({npsso_link}) to retrieve the token."
}
Expand Down
103 changes: 103 additions & 0 deletions homeassistant/components/vegehub/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
"""The Vegetronix VegeHub integration."""

from collections.abc import Awaitable, Callable
from http import HTTPStatus
from typing import Any

from aiohttp.hdrs import METH_POST
from aiohttp.web import Request, Response
from vegehub import VegeHub

from homeassistant.components.http import HomeAssistantView
from homeassistant.components.webhook import (
async_register as webhook_register,
async_unregister as webhook_unregister,
)
from homeassistant.const import (
CONF_DEVICE,
CONF_IP_ADDRESS,
CONF_MAC,
CONF_WEBHOOK_ID,
EVENT_HOMEASSISTANT_STOP,
)
from homeassistant.core import HomeAssistant

from .const import DOMAIN, NAME, PLATFORMS
from .coordinator import VegeHubConfigEntry, VegeHubCoordinator


async def async_setup_entry(hass: HomeAssistant, entry: VegeHubConfigEntry) -> bool:
"""Set up VegeHub from a config entry."""

device_mac = entry.data[CONF_MAC]

assert entry.unique_id

vegehub = VegeHub(
entry.data[CONF_IP_ADDRESS],
device_mac,
entry.unique_id,
info=entry.data[CONF_DEVICE],
)

# Initialize runtime data
entry.runtime_data = VegeHubCoordinator(
hass=hass, config_entry=entry, vegehub=vegehub
)

async def unregister_webhook(_: Any) -> None:
webhook_unregister(hass, entry.data[CONF_WEBHOOK_ID])

async def register_webhook() -> None:
webhook_name = f"{NAME} {device_mac}"

webhook_register(
hass,
DOMAIN,
webhook_name,
entry.data[CONF_WEBHOOK_ID],
get_webhook_handler(device_mac, entry.entry_id, entry.runtime_data),
allowed_methods=[METH_POST],
)

entry.async_on_unload(
hass.bus.async_listen_once(EVENT_HOMEASSISTANT_STOP, unregister_webhook)
)

# Now add in all the entities for this device.
await hass.config_entries.async_forward_entry_setups(entry, PLATFORMS)

await register_webhook()

return True


async def async_unload_entry(hass: HomeAssistant, entry: VegeHubConfigEntry) -> bool:
"""Unload a VegeHub config entry."""
webhook_unregister(hass, entry.data[CONF_WEBHOOK_ID])

# Unload platforms
return await hass.config_entries.async_unload_platforms(entry, PLATFORMS)


def get_webhook_handler(
device_mac: str, entry_id: str, coordinator: VegeHubCoordinator
) -> Callable[[HomeAssistant, str, Request], Awaitable[Response | None]]:
"""Return webhook handler."""

async def async_webhook_handler(
hass: HomeAssistant, webhook_id: str, request: Request
) -> Response | None:
# Handle http post calls to the path.
if not request.body_exists:
return HomeAssistantView.json(
result="No Body", status_code=HTTPStatus.BAD_REQUEST
)
data = await request.json()

if coordinator:
await coordinator.update_from_webhook(data)

return HomeAssistantView.json(result="OK", status_code=HTTPStatus.OK)

return async_webhook_handler
Loading
Loading