Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
f932260
Add iZone manual host entry to the user config flow (#178805)
Swamp-Ig Sep 17, 2026
347d038
Bump fressnapftracker to 0.3.1 (#182495)
eifinger Sep 17, 2026
a05e622
Bump pyenphase to 4.0.5 (#182473)
catsmanac Sep 17, 2026
834d3d0
Bump aiopowerwall to 0.4.0 (#182454)
Bre77 Sep 17, 2026
f2e19bf
Bump specialized-turbo to 0.8.4 (#182443)
JamieMagee Sep 17, 2026
c1d630f
Bump samsungtvws to 3.0.6 (#182440)
chemelli74 Sep 17, 2026
66de596
Bump aioamazondevices to 16.3.0 (#182438)
chemelli74 Sep 17, 2026
8ee5b5f
Bump librouteros to 4.2.2 (#182439)
chemelli74 Sep 17, 2026
2dec311
Bump teslemetry-stream to 1.0.1 (#182368)
Bre77 Sep 17, 2026
2e7816c
Update python-slugify to 9.0.0 (#182358)
renovate[bot] Sep 17, 2026
5a081e1
Add coordinator.py to RESTful component (#178114)
iluvdata Sep 17, 2026
76b7b14
Bump pydanfossair to 1.0.0 (#182277)
madsvonqualen Sep 17, 2026
9df6d88
Move ai_task service registration to services module (#182462)
epenet Sep 17, 2026
7808328
Move assist_satellite service registration to services module (#182463)
epenet Sep 17, 2026
361ae70
Contain the download directory in telegram_bot.download_file (#182460)
frenck Sep 17, 2026
fe9fa47
Move valve service registration to services module (#182459)
epenet Sep 17, 2026
836c5cb
Service exceptions for collection_image (#182442)
karwosts Sep 17, 2026
44d87c5
Add salt setting to Midea (#182436)
chemelli74 Sep 17, 2026
9952d71
Improve testing for Midea (#182437)
chemelli74 Sep 17, 2026
8619748
Cleanup climate and sensor in Midea (#182483)
chemelli74 Sep 17, 2026
505d776
Change logging to debug in dnsip (#182502)
gjohansson-ST Sep 17, 2026
0cb1d21
Do not log the Telegram bot token (#182452)
frenck Sep 17, 2026
2d33b77
Add AI switch to Midea (#182433)
chemelli74 Sep 17, 2026
9e3957f
Keep existing HEOS group members when joining a player (#182515)
smitec11 Sep 17, 2026
c6c9edf
Split user flow init and data submission in heos config flow tests (#…
smitec11 Sep 17, 2026
6c2d414
Add time remaining sensors to Midea (#182435)
chemelli74 Sep 17, 2026
26d9bfc
Add Gree Infrared integration (#177189)
Dr-Blank Sep 17, 2026
d6fa711
Share async shell command core in command_line utils (#182352)
MartinHjelmare Sep 17, 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
1 change: 1 addition & 0 deletions .strict-typing
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,7 @@ homeassistant.components.google_sheets.*
homeassistant.components.google_weather.*
homeassistant.components.govee_ble.*
homeassistant.components.gpsd.*
homeassistant.components.gree_infrared.*
homeassistant.components.greeneye_monitor.*
homeassistant.components.group.*
homeassistant.components.guardian.*
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.

5 changes: 5 additions & 0 deletions homeassistant/brands/gree.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"domain": "gree",
"name": "Gree",
"integrations": ["gree", "gree_infrared"]
}
107 changes: 6 additions & 101 deletions homeassistant/components/ai_task/__init__.py
Original file line number Diff line number Diff line change
@@ -1,41 +1,19 @@
"""Integration to offer AI tasks to Home Assistant."""

import logging
from typing import Any

import probatio

from homeassistant.components.media_source import local_source
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import ATTR_ENTITY_ID, CONF_DESCRIPTION, CONF_SELECTOR
from homeassistant.core import (
HassJobType,
HomeAssistant,
ServiceCall,
ServiceResponse,
SupportsResponse,
callback,
)
from homeassistant.helpers import config_validation as cv, selector, storage
from homeassistant.core import HomeAssistant, callback
from homeassistant.helpers import config_validation as cv, storage
from homeassistant.helpers.entity_component import EntityComponent
from homeassistant.helpers.typing import UNDEFINED, ConfigType, UndefinedType

from .const import (
ATTR_ATTACHMENTS,
ATTR_INSTRUCTIONS,
ATTR_REQUIRED,
ATTR_STRUCTURE,
ATTR_TASK_NAME,
DATA_COMPONENT,
DATA_PREFERENCES,
DOMAIN,
SERVICE_GENERATE_DATA,
SERVICE_GENERATE_IMAGE,
AITaskEntityFeature,
)
from .const import DATA_COMPONENT, DATA_PREFERENCES, DOMAIN, AITaskEntityFeature
from .entity import AITaskEntity
from .http import async_setup as async_setup_http
from .media_source import async_get_media_source
from .services import async_setup_services
from .task import (
GenDataTask,
GenDataTaskResult,
Expand All @@ -61,32 +39,9 @@

CONFIG_SCHEMA = cv.config_entry_only_config_schema(DOMAIN)

STRUCTURE_FIELD_SCHEMA = probatio.Schema(
{
probatio.Optional(CONF_DESCRIPTION): str,
probatio.Optional(ATTR_REQUIRED): bool,
probatio.Required(CONF_SELECTOR): selector.validate_selector,
}
)


def _validate_structure_fields(value: dict[str, Any]) -> probatio.Schema:
"""Validate the structure fields as a probatio Schema."""
if not isinstance(value, dict):
raise probatio.Invalid("Structure must be a dictionary")
fields = {}
for k, v in value.items():
field_class = (
probatio.Required if v.get(ATTR_REQUIRED, False) else probatio.Optional
)
fields[field_class(k, description=v.get(CONF_DESCRIPTION))] = selector.selector(
v[CONF_SELECTOR]
)
return probatio.Schema(fields, extra=probatio.PREVENT_EXTRA)


async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
"""Register the process service."""
"""Set up AI Task."""
entity_component = EntityComponent[AITaskEntity](_LOGGER, DOMAIN, hass)
hass.data[DATA_COMPONENT] = entity_component
hass.data[DATA_PREFERENCES] = AITaskPreferences(hass)
Expand All @@ -95,44 +50,7 @@ async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
if hass.config.media_dirs:
source = await async_get_media_source(hass)
hass.http.register_view(local_source.LocalMediaView(hass, source))
hass.services.async_register(
DOMAIN,
SERVICE_GENERATE_DATA,
async_service_generate_data,
schema=probatio.Schema(
{
probatio.Required(ATTR_TASK_NAME): cv.string,
probatio.Optional(ATTR_ENTITY_ID): cv.entity_id,
probatio.Required(ATTR_INSTRUCTIONS): cv.string,
probatio.Optional(ATTR_STRUCTURE): probatio.All(
probatio.Schema({str: STRUCTURE_FIELD_SCHEMA}),
_validate_structure_fields,
),
probatio.Optional(ATTR_ATTACHMENTS): selector.MediaSelector(
{"accept": ["*/*"], "multiple": True}
),
}
),
supports_response=SupportsResponse.ONLY,
job_type=HassJobType.Coroutinefunction,
)
hass.services.async_register(
DOMAIN,
SERVICE_GENERATE_IMAGE,
async_service_generate_image,
schema=probatio.Schema(
{
probatio.Required(ATTR_TASK_NAME): cv.string,
probatio.Optional(ATTR_ENTITY_ID): cv.entity_id,
probatio.Required(ATTR_INSTRUCTIONS): cv.string,
probatio.Optional(ATTR_ATTACHMENTS): selector.MediaSelector(
{"accept": ["*/*"], "multiple": True}
),
}
),
supports_response=SupportsResponse.ONLY,
job_type=HassJobType.Coroutinefunction,
)
async_setup_services(hass)
return True


Expand All @@ -146,19 +64,6 @@ async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
return await hass.data[DATA_COMPONENT].async_unload_entry(entry)


async def async_service_generate_data(call: ServiceCall) -> ServiceResponse:
"""Run the data task service."""
result = await async_generate_data(
hass=call.hass, context=call.context, **call.data
)
return result.as_dict()


async def async_service_generate_image(call: ServiceCall) -> ServiceResponse:
"""Run the image task service."""
return await async_generate_image(hass=call.hass, context=call.context, **call.data)


class AITaskPreferences:
"""AI Task preferences."""

Expand Down
107 changes: 107 additions & 0 deletions homeassistant/components/ai_task/services.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
"""Services for the AI Task integration."""

from typing import Any

import probatio

from homeassistant.const import ATTR_ENTITY_ID, CONF_DESCRIPTION, CONF_SELECTOR
from homeassistant.core import (
HassJobType,
HomeAssistant,
ServiceCall,
ServiceResponse,
SupportsResponse,
callback,
)
from homeassistant.helpers import config_validation as cv, selector

from .const import (
ATTR_ATTACHMENTS,
ATTR_INSTRUCTIONS,
ATTR_REQUIRED,
ATTR_STRUCTURE,
ATTR_TASK_NAME,
DOMAIN,
SERVICE_GENERATE_DATA,
SERVICE_GENERATE_IMAGE,
)
from .task import async_generate_data, async_generate_image

STRUCTURE_FIELD_SCHEMA = probatio.Schema(
{
probatio.Optional(CONF_DESCRIPTION): str,
probatio.Optional(ATTR_REQUIRED): bool,
probatio.Required(CONF_SELECTOR): selector.validate_selector,
}
)


def _validate_structure_fields(value: dict[str, Any]) -> probatio.Schema:
"""Validate the structure fields as a probatio Schema."""
if not isinstance(value, dict):
raise probatio.Invalid("Structure must be a dictionary")
fields = {}
for k, v in value.items():
field_class = (
probatio.Required if v.get(ATTR_REQUIRED, False) else probatio.Optional
)
fields[field_class(k, description=v.get(CONF_DESCRIPTION))] = selector.selector(
v[CONF_SELECTOR]
)
return probatio.Schema(fields, extra=probatio.PREVENT_EXTRA)


async def async_service_generate_data(call: ServiceCall) -> ServiceResponse:
"""Run the data task service."""
result = await async_generate_data(
hass=call.hass, context=call.context, **call.data
)
return result.as_dict()


async def async_service_generate_image(call: ServiceCall) -> ServiceResponse:
"""Run the image task service."""
return await async_generate_image(hass=call.hass, context=call.context, **call.data)


@callback
def async_setup_services(hass: HomeAssistant) -> None:
"""Register the AI Task services."""
hass.services.async_register(
DOMAIN,
SERVICE_GENERATE_DATA,
async_service_generate_data,
schema=probatio.Schema(
{
probatio.Required(ATTR_TASK_NAME): cv.string,
probatio.Optional(ATTR_ENTITY_ID): cv.entity_id,
probatio.Required(ATTR_INSTRUCTIONS): cv.string,
probatio.Optional(ATTR_STRUCTURE): probatio.All(
probatio.Schema({str: STRUCTURE_FIELD_SCHEMA}),
_validate_structure_fields,
),
probatio.Optional(ATTR_ATTACHMENTS): selector.MediaSelector(
{"accept": ["*/*"], "multiple": True}
),
}
),
supports_response=SupportsResponse.ONLY,
job_type=HassJobType.Coroutinefunction,
)
hass.services.async_register(
DOMAIN,
SERVICE_GENERATE_IMAGE,
async_service_generate_image,
schema=probatio.Schema(
{
probatio.Required(ATTR_TASK_NAME): cv.string,
probatio.Optional(ATTR_ENTITY_ID): cv.entity_id,
probatio.Required(ATTR_INSTRUCTIONS): cv.string,
probatio.Optional(ATTR_ATTACHMENTS): selector.MediaSelector(
{"accept": ["*/*"], "multiple": True}
),
}
),
supports_response=SupportsResponse.ONLY,
job_type=HassJobType.Coroutinefunction,
)
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==15.2.0"]
"requirements": ["aioamazondevices==16.3.0"]
}
Loading
Loading