mirror of
https://github.com/home-assistant/core.git
synced 2025-07-26 06:37:52 +00:00
2025.7.1 (#148171)
This commit is contained in:
commit
5d6b02f470
2
.github/workflows/ci.yaml
vendored
2
.github/workflows/ci.yaml
vendored
@ -37,7 +37,7 @@ on:
|
|||||||
type: boolean
|
type: boolean
|
||||||
|
|
||||||
env:
|
env:
|
||||||
CACHE_VERSION: 3
|
CACHE_VERSION: 4
|
||||||
UV_CACHE_VERSION: 1
|
UV_CACHE_VERSION: 1
|
||||||
MYPY_CACHE_VERSION: 1
|
MYPY_CACHE_VERSION: 1
|
||||||
HA_SHORT_VERSION: "2025.7"
|
HA_SHORT_VERSION: "2025.7"
|
||||||
|
@ -8,5 +8,5 @@
|
|||||||
"iot_class": "cloud_polling",
|
"iot_class": "cloud_polling",
|
||||||
"loggers": ["aioamazondevices"],
|
"loggers": ["aioamazondevices"],
|
||||||
"quality_scale": "bronze",
|
"quality_scale": "bronze",
|
||||||
"requirements": ["aioamazondevices==3.2.2"]
|
"requirements": ["aioamazondevices==3.2.3"]
|
||||||
}
|
}
|
||||||
|
@ -13,6 +13,6 @@
|
|||||||
"integration_type": "system",
|
"integration_type": "system",
|
||||||
"iot_class": "cloud_push",
|
"iot_class": "cloud_push",
|
||||||
"loggers": ["acme", "hass_nabucasa", "snitun"],
|
"loggers": ["acme", "hass_nabucasa", "snitun"],
|
||||||
"requirements": ["hass-nabucasa==0.104.0"],
|
"requirements": ["hass-nabucasa==0.105.0"],
|
||||||
"single_config_entry": true
|
"single_config_entry": true
|
||||||
}
|
}
|
||||||
|
@ -63,6 +63,7 @@ async def async_unload_entry(hass: HomeAssistant, entry: EnphaseConfigEntry) ->
|
|||||||
coordinator = entry.runtime_data
|
coordinator = entry.runtime_data
|
||||||
coordinator.async_cancel_token_refresh()
|
coordinator.async_cancel_token_refresh()
|
||||||
coordinator.async_cancel_firmware_refresh()
|
coordinator.async_cancel_firmware_refresh()
|
||||||
|
coordinator.async_cancel_mac_verification()
|
||||||
return await hass.config_entries.async_unload_platforms(entry, PLATFORMS)
|
return await hass.config_entries.async_unload_platforms(entry, PLATFORMS)
|
||||||
|
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
"iot_class": "local_polling",
|
"iot_class": "local_polling",
|
||||||
"loggers": ["pyenphase"],
|
"loggers": ["pyenphase"],
|
||||||
"quality_scale": "platinum",
|
"quality_scale": "platinum",
|
||||||
"requirements": ["pyenphase==2.1.0"],
|
"requirements": ["pyenphase==2.2.0"],
|
||||||
"zeroconf": [
|
"zeroconf": [
|
||||||
{
|
{
|
||||||
"type": "_enphase-envoy._tcp.local."
|
"type": "_enphase-envoy._tcp.local."
|
||||||
|
@ -20,5 +20,5 @@
|
|||||||
"documentation": "https://www.home-assistant.io/integrations/frontend",
|
"documentation": "https://www.home-assistant.io/integrations/frontend",
|
||||||
"integration_type": "system",
|
"integration_type": "system",
|
||||||
"quality_scale": "internal",
|
"quality_scale": "internal",
|
||||||
"requirements": ["home-assistant-frontend==20250702.0"]
|
"requirements": ["home-assistant-frontend==20250702.1"]
|
||||||
}
|
}
|
||||||
|
@ -64,7 +64,7 @@ def setup_bans(hass: HomeAssistant, app: Application, login_threshold: int) -> N
|
|||||||
"""Initialize bans when app starts up."""
|
"""Initialize bans when app starts up."""
|
||||||
await app[KEY_BAN_MANAGER].async_load()
|
await app[KEY_BAN_MANAGER].async_load()
|
||||||
|
|
||||||
app.on_startup.append(ban_startup)
|
app.on_startup.append(ban_startup) # type: ignore[arg-type]
|
||||||
|
|
||||||
|
|
||||||
@middleware
|
@middleware
|
||||||
|
@ -7,6 +7,6 @@
|
|||||||
"documentation": "https://www.home-assistant.io/integrations/music_assistant",
|
"documentation": "https://www.home-assistant.io/integrations/music_assistant",
|
||||||
"iot_class": "local_push",
|
"iot_class": "local_push",
|
||||||
"loggers": ["music_assistant"],
|
"loggers": ["music_assistant"],
|
||||||
"requirements": ["music-assistant-client==1.2.3"],
|
"requirements": ["music-assistant-client==1.2.4"],
|
||||||
"zeroconf": ["_mass._tcp.local."]
|
"zeroconf": ["_mass._tcp.local."]
|
||||||
}
|
}
|
||||||
|
@ -248,8 +248,6 @@ class MusicAssistantPlayer(MusicAssistantEntity, MediaPlayerEntity):
|
|||||||
player = self.player
|
player = self.player
|
||||||
active_queue = self.active_queue
|
active_queue = self.active_queue
|
||||||
# update generic attributes
|
# update generic attributes
|
||||||
if player.powered and active_queue is not None:
|
|
||||||
self._attr_state = MediaPlayerState(active_queue.state.value)
|
|
||||||
if player.powered and player.playback_state is not None:
|
if player.powered and player.playback_state is not None:
|
||||||
self._attr_state = MediaPlayerState(player.playback_state.value)
|
self._attr_state = MediaPlayerState(player.playback_state.value)
|
||||||
else:
|
else:
|
||||||
|
12
homeassistant/components/remote_calendar/client.py
Normal file
12
homeassistant/components/remote_calendar/client.py
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
"""Specifies the parameter for the httpx download."""
|
||||||
|
|
||||||
|
from httpx import AsyncClient, Response, Timeout
|
||||||
|
|
||||||
|
|
||||||
|
async def get_calendar(client: AsyncClient, url: str) -> Response:
|
||||||
|
"""Make an HTTP GET request using Home Assistant's async HTTPX client with timeout."""
|
||||||
|
return await client.get(
|
||||||
|
url,
|
||||||
|
follow_redirects=True,
|
||||||
|
timeout=Timeout(5, read=30, write=5, pool=5),
|
||||||
|
)
|
@ -4,13 +4,14 @@ from http import HTTPStatus
|
|||||||
import logging
|
import logging
|
||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
from httpx import HTTPError, InvalidURL
|
from httpx import HTTPError, InvalidURL, TimeoutException
|
||||||
import voluptuous as vol
|
import voluptuous as vol
|
||||||
|
|
||||||
from homeassistant.config_entries import ConfigFlow, ConfigFlowResult
|
from homeassistant.config_entries import ConfigFlow, ConfigFlowResult
|
||||||
from homeassistant.const import CONF_URL
|
from homeassistant.const import CONF_URL
|
||||||
from homeassistant.helpers.httpx_client import get_async_client
|
from homeassistant.helpers.httpx_client import get_async_client
|
||||||
|
|
||||||
|
from .client import get_calendar
|
||||||
from .const import CONF_CALENDAR_NAME, DOMAIN
|
from .const import CONF_CALENDAR_NAME, DOMAIN
|
||||||
from .ics import InvalidIcsException, parse_calendar
|
from .ics import InvalidIcsException, parse_calendar
|
||||||
|
|
||||||
@ -49,7 +50,7 @@ class RemoteCalendarConfigFlow(ConfigFlow, domain=DOMAIN):
|
|||||||
self._async_abort_entries_match({CONF_URL: user_input[CONF_URL]})
|
self._async_abort_entries_match({CONF_URL: user_input[CONF_URL]})
|
||||||
client = get_async_client(self.hass)
|
client = get_async_client(self.hass)
|
||||||
try:
|
try:
|
||||||
res = await client.get(user_input[CONF_URL], follow_redirects=True)
|
res = await get_calendar(client, user_input[CONF_URL])
|
||||||
if res.status_code == HTTPStatus.FORBIDDEN:
|
if res.status_code == HTTPStatus.FORBIDDEN:
|
||||||
errors["base"] = "forbidden"
|
errors["base"] = "forbidden"
|
||||||
return self.async_show_form(
|
return self.async_show_form(
|
||||||
@ -58,9 +59,14 @@ class RemoteCalendarConfigFlow(ConfigFlow, domain=DOMAIN):
|
|||||||
errors=errors,
|
errors=errors,
|
||||||
)
|
)
|
||||||
res.raise_for_status()
|
res.raise_for_status()
|
||||||
|
except TimeoutException as err:
|
||||||
|
errors["base"] = "timeout_connect"
|
||||||
|
_LOGGER.debug(
|
||||||
|
"A timeout error occurred: %s", str(err) or type(err).__name__
|
||||||
|
)
|
||||||
except (HTTPError, InvalidURL) as err:
|
except (HTTPError, InvalidURL) as err:
|
||||||
errors["base"] = "cannot_connect"
|
errors["base"] = "cannot_connect"
|
||||||
_LOGGER.debug("An error occurred: %s", err)
|
_LOGGER.debug("An error occurred: %s", str(err) or type(err).__name__)
|
||||||
else:
|
else:
|
||||||
try:
|
try:
|
||||||
await parse_calendar(self.hass, res.text)
|
await parse_calendar(self.hass, res.text)
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
from datetime import timedelta
|
from datetime import timedelta
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
from httpx import HTTPError, InvalidURL
|
from httpx import HTTPError, InvalidURL, TimeoutException
|
||||||
from ical.calendar import Calendar
|
from ical.calendar import Calendar
|
||||||
|
|
||||||
from homeassistant.config_entries import ConfigEntry
|
from homeassistant.config_entries import ConfigEntry
|
||||||
@ -12,6 +12,7 @@ from homeassistant.core import HomeAssistant
|
|||||||
from homeassistant.helpers.httpx_client import get_async_client
|
from homeassistant.helpers.httpx_client import get_async_client
|
||||||
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed
|
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed
|
||||||
|
|
||||||
|
from .client import get_calendar
|
||||||
from .const import DOMAIN
|
from .const import DOMAIN
|
||||||
from .ics import InvalidIcsException, parse_calendar
|
from .ics import InvalidIcsException, parse_calendar
|
||||||
|
|
||||||
@ -36,7 +37,7 @@ class RemoteCalendarDataUpdateCoordinator(DataUpdateCoordinator[Calendar]):
|
|||||||
super().__init__(
|
super().__init__(
|
||||||
hass,
|
hass,
|
||||||
_LOGGER,
|
_LOGGER,
|
||||||
name=DOMAIN,
|
name=f"{DOMAIN}_{config_entry.title}",
|
||||||
update_interval=SCAN_INTERVAL,
|
update_interval=SCAN_INTERVAL,
|
||||||
always_update=True,
|
always_update=True,
|
||||||
)
|
)
|
||||||
@ -46,13 +47,19 @@ class RemoteCalendarDataUpdateCoordinator(DataUpdateCoordinator[Calendar]):
|
|||||||
async def _async_update_data(self) -> Calendar:
|
async def _async_update_data(self) -> Calendar:
|
||||||
"""Update data from the url."""
|
"""Update data from the url."""
|
||||||
try:
|
try:
|
||||||
res = await self._client.get(self._url, follow_redirects=True)
|
res = await get_calendar(self._client, self._url)
|
||||||
res.raise_for_status()
|
res.raise_for_status()
|
||||||
|
except TimeoutException as err:
|
||||||
|
_LOGGER.debug("%s: %s", self._url, str(err) or type(err).__name__)
|
||||||
|
raise UpdateFailed(
|
||||||
|
translation_domain=DOMAIN,
|
||||||
|
translation_key="timeout",
|
||||||
|
) from err
|
||||||
except (HTTPError, InvalidURL) as err:
|
except (HTTPError, InvalidURL) as err:
|
||||||
|
_LOGGER.debug("%s: %s", self._url, str(err) or type(err).__name__)
|
||||||
raise UpdateFailed(
|
raise UpdateFailed(
|
||||||
translation_domain=DOMAIN,
|
translation_domain=DOMAIN,
|
||||||
translation_key="unable_to_fetch",
|
translation_key="unable_to_fetch",
|
||||||
translation_placeholders={"err": str(err)},
|
|
||||||
) from err
|
) from err
|
||||||
try:
|
try:
|
||||||
self.ics = res.text
|
self.ics = res.text
|
||||||
|
@ -18,14 +18,18 @@
|
|||||||
"already_configured": "[%key:common::config_flow::abort::already_configured_service%]"
|
"already_configured": "[%key:common::config_flow::abort::already_configured_service%]"
|
||||||
},
|
},
|
||||||
"error": {
|
"error": {
|
||||||
|
"timeout_connect": "[%key:common::config_flow::error::timeout_connect%]",
|
||||||
"cannot_connect": "[%key:common::config_flow::error::cannot_connect%]",
|
"cannot_connect": "[%key:common::config_flow::error::cannot_connect%]",
|
||||||
"forbidden": "The server understood the request but refuses to authorize it.",
|
"forbidden": "The server understood the request but refuses to authorize it.",
|
||||||
"invalid_ics_file": "There was a problem reading the calendar information. See the error log for additional details."
|
"invalid_ics_file": "There was a problem reading the calendar information. See the error log for additional details."
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"exceptions": {
|
"exceptions": {
|
||||||
|
"timeout": {
|
||||||
|
"message": "The connection timed out. See the debug log for additional details."
|
||||||
|
},
|
||||||
"unable_to_fetch": {
|
"unable_to_fetch": {
|
||||||
"message": "Unable to fetch calendar data: {err}"
|
"message": "Unable to fetch calendar data. See the debug log for additional details."
|
||||||
},
|
},
|
||||||
"unable_to_parse": {
|
"unable_to_parse": {
|
||||||
"message": "Unable to parse calendar data: {err}"
|
"message": "Unable to parse calendar data: {err}"
|
||||||
|
@ -124,6 +124,7 @@ class SamsungTVConfigFlow(ConfigFlow, domain=DOMAIN):
|
|||||||
self._model: str | None = None
|
self._model: str | None = None
|
||||||
self._connect_result: str | None = None
|
self._connect_result: str | None = None
|
||||||
self._method: str | None = None
|
self._method: str | None = None
|
||||||
|
self._port: int | None = None
|
||||||
self._name: str | None = None
|
self._name: str | None = None
|
||||||
self._title: str = ""
|
self._title: str = ""
|
||||||
self._id: int | None = None
|
self._id: int | None = None
|
||||||
@ -199,33 +200,37 @@ class SamsungTVConfigFlow(ConfigFlow, domain=DOMAIN):
|
|||||||
|
|
||||||
async def _async_create_bridge(self) -> None:
|
async def _async_create_bridge(self) -> None:
|
||||||
"""Create the bridge."""
|
"""Create the bridge."""
|
||||||
result, method, _info = await self._async_get_device_info_and_method()
|
result = await self._async_load_device_info()
|
||||||
if result not in SUCCESSFUL_RESULTS:
|
if result not in SUCCESSFUL_RESULTS:
|
||||||
LOGGER.debug("No working config found for %s", self._host)
|
LOGGER.debug("No working config found for %s", self._host)
|
||||||
raise AbortFlow(result)
|
raise AbortFlow(result)
|
||||||
assert method is not None
|
assert self._method is not None
|
||||||
self._bridge = SamsungTVBridge.get_bridge(self.hass, method, self._host)
|
self._bridge = SamsungTVBridge.get_bridge(
|
||||||
|
self.hass, self._method, self._host, self._port
|
||||||
|
)
|
||||||
|
|
||||||
async def _async_get_device_info_and_method(
|
async def _async_load_device_info(
|
||||||
self,
|
self,
|
||||||
) -> tuple[str, str | None, dict[str, Any] | None]:
|
) -> str:
|
||||||
"""Get device info and method only once."""
|
"""Get device info and method only once."""
|
||||||
if self._connect_result is None:
|
if self._connect_result is None:
|
||||||
result, _, method, info = await async_get_device_info(self.hass, self._host)
|
result, port, method, info = await async_get_device_info(
|
||||||
|
self.hass, self._host
|
||||||
|
)
|
||||||
self._connect_result = result
|
self._connect_result = result
|
||||||
self._method = method
|
self._method = method
|
||||||
|
self._port = port
|
||||||
self._device_info = info
|
self._device_info = info
|
||||||
if not method:
|
if not method:
|
||||||
LOGGER.debug("Host:%s did not return device info", self._host)
|
LOGGER.debug("Host:%s did not return device info", self._host)
|
||||||
return result, None, None
|
return self._connect_result
|
||||||
return self._connect_result, self._method, self._device_info
|
|
||||||
|
|
||||||
async def _async_get_and_check_device_info(self) -> bool:
|
async def _async_get_and_check_device_info(self) -> bool:
|
||||||
"""Try to get the device info."""
|
"""Try to get the device info."""
|
||||||
result, _method, info = await self._async_get_device_info_and_method()
|
result = await self._async_load_device_info()
|
||||||
if result not in SUCCESSFUL_RESULTS:
|
if result not in SUCCESSFUL_RESULTS:
|
||||||
raise AbortFlow(result)
|
raise AbortFlow(result)
|
||||||
if not info:
|
if not (info := self._device_info):
|
||||||
return False
|
return False
|
||||||
dev_info = info.get("device", {})
|
dev_info = info.get("device", {})
|
||||||
assert dev_info is not None
|
assert dev_info is not None
|
||||||
|
@ -374,9 +374,7 @@ class TelegramNotificationService:
|
|||||||
}
|
}
|
||||||
if data is not None:
|
if data is not None:
|
||||||
if ATTR_PARSER in data:
|
if ATTR_PARSER in data:
|
||||||
params[ATTR_PARSER] = self._parsers.get(
|
params[ATTR_PARSER] = data[ATTR_PARSER]
|
||||||
data[ATTR_PARSER], self.parse_mode
|
|
||||||
)
|
|
||||||
if ATTR_TIMEOUT in data:
|
if ATTR_TIMEOUT in data:
|
||||||
params[ATTR_TIMEOUT] = data[ATTR_TIMEOUT]
|
params[ATTR_TIMEOUT] = data[ATTR_TIMEOUT]
|
||||||
if ATTR_DISABLE_NOTIF in data:
|
if ATTR_DISABLE_NOTIF in data:
|
||||||
@ -408,6 +406,8 @@ class TelegramNotificationService:
|
|||||||
params[ATTR_REPLYMARKUP] = InlineKeyboardMarkup(
|
params[ATTR_REPLYMARKUP] = InlineKeyboardMarkup(
|
||||||
[_make_row_inline_keyboard(row) for row in keys]
|
[_make_row_inline_keyboard(row) for row in keys]
|
||||||
)
|
)
|
||||||
|
if params[ATTR_PARSER] == PARSER_PLAIN_TEXT:
|
||||||
|
params[ATTR_PARSER] = None
|
||||||
return params
|
return params
|
||||||
|
|
||||||
async def _send_msg(
|
async def _send_msg(
|
||||||
|
@ -159,8 +159,6 @@ class OptionsFlowHandler(OptionsFlow):
|
|||||||
"""Manage the options."""
|
"""Manage the options."""
|
||||||
|
|
||||||
if user_input is not None:
|
if user_input is not None:
|
||||||
if user_input[ATTR_PARSER] == PARSER_PLAIN_TEXT:
|
|
||||||
user_input[ATTR_PARSER] = None
|
|
||||||
return self.async_create_entry(data=user_input)
|
return self.async_create_entry(data=user_input)
|
||||||
|
|
||||||
return self.async_show_form(
|
return self.async_show_form(
|
||||||
|
@ -109,6 +109,7 @@ send_photo:
|
|||||||
- "markdown"
|
- "markdown"
|
||||||
- "markdownv2"
|
- "markdownv2"
|
||||||
- "plain_text"
|
- "plain_text"
|
||||||
|
translation_key: "parse_mode"
|
||||||
disable_notification:
|
disable_notification:
|
||||||
selector:
|
selector:
|
||||||
boolean:
|
boolean:
|
||||||
@ -261,6 +262,7 @@ send_animation:
|
|||||||
- "markdown"
|
- "markdown"
|
||||||
- "markdownv2"
|
- "markdownv2"
|
||||||
- "plain_text"
|
- "plain_text"
|
||||||
|
translation_key: "parse_mode"
|
||||||
disable_notification:
|
disable_notification:
|
||||||
selector:
|
selector:
|
||||||
boolean:
|
boolean:
|
||||||
@ -341,6 +343,7 @@ send_video:
|
|||||||
- "markdown"
|
- "markdown"
|
||||||
- "markdownv2"
|
- "markdownv2"
|
||||||
- "plain_text"
|
- "plain_text"
|
||||||
|
translation_key: "parse_mode"
|
||||||
disable_notification:
|
disable_notification:
|
||||||
selector:
|
selector:
|
||||||
boolean:
|
boolean:
|
||||||
@ -493,6 +496,7 @@ send_document:
|
|||||||
- "markdown"
|
- "markdown"
|
||||||
- "markdownv2"
|
- "markdownv2"
|
||||||
- "plain_text"
|
- "plain_text"
|
||||||
|
translation_key: "parse_mode"
|
||||||
disable_notification:
|
disable_notification:
|
||||||
selector:
|
selector:
|
||||||
boolean:
|
boolean:
|
||||||
@ -670,6 +674,7 @@ edit_message:
|
|||||||
- "markdown"
|
- "markdown"
|
||||||
- "markdownv2"
|
- "markdownv2"
|
||||||
- "plain_text"
|
- "plain_text"
|
||||||
|
translation_key: "parse_mode"
|
||||||
disable_web_page_preview:
|
disable_web_page_preview:
|
||||||
selector:
|
selector:
|
||||||
boolean:
|
boolean:
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
"integration_type": "hub",
|
"integration_type": "hub",
|
||||||
"iot_class": "local_push",
|
"iot_class": "local_push",
|
||||||
"loggers": ["aiounifi"],
|
"loggers": ["aiounifi"],
|
||||||
"requirements": ["aiounifi==83"],
|
"requirements": ["aiounifi==84"],
|
||||||
"ssdp": [
|
"ssdp": [
|
||||||
{
|
{
|
||||||
"manufacturer": "Ubiquiti Networks",
|
"manufacturer": "Ubiquiti Networks",
|
||||||
|
@ -6,5 +6,5 @@
|
|||||||
"documentation": "https://www.home-assistant.io/integrations/venstar",
|
"documentation": "https://www.home-assistant.io/integrations/venstar",
|
||||||
"iot_class": "local_polling",
|
"iot_class": "local_polling",
|
||||||
"loggers": ["venstarcolortouch"],
|
"loggers": ["venstarcolortouch"],
|
||||||
"requirements": ["venstarcolortouch==0.19"]
|
"requirements": ["venstarcolortouch==0.21"]
|
||||||
}
|
}
|
||||||
|
@ -21,7 +21,7 @@
|
|||||||
"zha",
|
"zha",
|
||||||
"universal_silabs_flasher"
|
"universal_silabs_flasher"
|
||||||
],
|
],
|
||||||
"requirements": ["zha==0.0.61"],
|
"requirements": ["zha==0.0.62"],
|
||||||
"usb": [
|
"usb": [
|
||||||
{
|
{
|
||||||
"vid": "10C4",
|
"vid": "10C4",
|
||||||
|
@ -25,7 +25,7 @@ if TYPE_CHECKING:
|
|||||||
APPLICATION_NAME: Final = "HomeAssistant"
|
APPLICATION_NAME: Final = "HomeAssistant"
|
||||||
MAJOR_VERSION: Final = 2025
|
MAJOR_VERSION: Final = 2025
|
||||||
MINOR_VERSION: Final = 7
|
MINOR_VERSION: Final = 7
|
||||||
PATCH_VERSION: Final = "0"
|
PATCH_VERSION: Final = "1"
|
||||||
__short_version__: Final = f"{MAJOR_VERSION}.{MINOR_VERSION}"
|
__short_version__: Final = f"{MAJOR_VERSION}.{MINOR_VERSION}"
|
||||||
__version__: Final = f"{__short_version__}.{PATCH_VERSION}"
|
__version__: Final = f"{__short_version__}.{PATCH_VERSION}"
|
||||||
REQUIRED_PYTHON_VER: Final[tuple[int, int, int]] = (3, 13, 2)
|
REQUIRED_PYTHON_VER: Final[tuple[int, int, int]] = (3, 13, 2)
|
||||||
|
@ -35,10 +35,10 @@ fnv-hash-fast==1.5.0
|
|||||||
go2rtc-client==0.2.1
|
go2rtc-client==0.2.1
|
||||||
ha-ffmpeg==3.2.2
|
ha-ffmpeg==3.2.2
|
||||||
habluetooth==3.49.0
|
habluetooth==3.49.0
|
||||||
hass-nabucasa==0.104.0
|
hass-nabucasa==0.105.0
|
||||||
hassil==2.2.3
|
hassil==2.2.3
|
||||||
home-assistant-bluetooth==1.13.1
|
home-assistant-bluetooth==1.13.1
|
||||||
home-assistant-frontend==20250702.0
|
home-assistant-frontend==20250702.1
|
||||||
home-assistant-intents==2025.6.23
|
home-assistant-intents==2025.6.23
|
||||||
httpx==0.28.1
|
httpx==0.28.1
|
||||||
ifaddr==0.2.0
|
ifaddr==0.2.0
|
||||||
|
@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|||||||
|
|
||||||
[project]
|
[project]
|
||||||
name = "homeassistant"
|
name = "homeassistant"
|
||||||
version = "2025.7.0"
|
version = "2025.7.1"
|
||||||
license = "Apache-2.0"
|
license = "Apache-2.0"
|
||||||
license-files = ["LICENSE*", "homeassistant/backports/LICENSE*"]
|
license-files = ["LICENSE*", "homeassistant/backports/LICENSE*"]
|
||||||
description = "Open-source home automation platform running on Python 3."
|
description = "Open-source home automation platform running on Python 3."
|
||||||
@ -47,7 +47,7 @@ dependencies = [
|
|||||||
"fnv-hash-fast==1.5.0",
|
"fnv-hash-fast==1.5.0",
|
||||||
# hass-nabucasa is imported by helpers which don't depend on the cloud
|
# hass-nabucasa is imported by helpers which don't depend on the cloud
|
||||||
# integration
|
# integration
|
||||||
"hass-nabucasa==0.104.0",
|
"hass-nabucasa==0.105.0",
|
||||||
# When bumping httpx, please check the version pins of
|
# When bumping httpx, please check the version pins of
|
||||||
# httpcore, anyio, and h11 in gen_requirements_all
|
# httpcore, anyio, and h11 in gen_requirements_all
|
||||||
"httpx==0.28.1",
|
"httpx==0.28.1",
|
||||||
|
2
requirements.txt
generated
2
requirements.txt
generated
@ -22,7 +22,7 @@ certifi>=2021.5.30
|
|||||||
ciso8601==2.3.2
|
ciso8601==2.3.2
|
||||||
cronsim==2.6
|
cronsim==2.6
|
||||||
fnv-hash-fast==1.5.0
|
fnv-hash-fast==1.5.0
|
||||||
hass-nabucasa==0.104.0
|
hass-nabucasa==0.105.0
|
||||||
httpx==0.28.1
|
httpx==0.28.1
|
||||||
home-assistant-bluetooth==1.13.1
|
home-assistant-bluetooth==1.13.1
|
||||||
ifaddr==0.2.0
|
ifaddr==0.2.0
|
||||||
|
16
requirements_all.txt
generated
16
requirements_all.txt
generated
@ -185,7 +185,7 @@ aioairzone-cloud==0.6.12
|
|||||||
aioairzone==1.0.0
|
aioairzone==1.0.0
|
||||||
|
|
||||||
# homeassistant.components.alexa_devices
|
# homeassistant.components.alexa_devices
|
||||||
aioamazondevices==3.2.2
|
aioamazondevices==3.2.3
|
||||||
|
|
||||||
# homeassistant.components.ambient_network
|
# homeassistant.components.ambient_network
|
||||||
# homeassistant.components.ambient_station
|
# homeassistant.components.ambient_station
|
||||||
@ -414,7 +414,7 @@ aiotedee==0.2.25
|
|||||||
aiotractive==0.6.0
|
aiotractive==0.6.0
|
||||||
|
|
||||||
# homeassistant.components.unifi
|
# homeassistant.components.unifi
|
||||||
aiounifi==83
|
aiounifi==84
|
||||||
|
|
||||||
# homeassistant.components.usb
|
# homeassistant.components.usb
|
||||||
aiousbwatcher==1.1.1
|
aiousbwatcher==1.1.1
|
||||||
@ -1127,7 +1127,7 @@ habiticalib==0.4.0
|
|||||||
habluetooth==3.49.0
|
habluetooth==3.49.0
|
||||||
|
|
||||||
# homeassistant.components.cloud
|
# homeassistant.components.cloud
|
||||||
hass-nabucasa==0.104.0
|
hass-nabucasa==0.105.0
|
||||||
|
|
||||||
# homeassistant.components.splunk
|
# homeassistant.components.splunk
|
||||||
hass-splunk==0.1.1
|
hass-splunk==0.1.1
|
||||||
@ -1168,7 +1168,7 @@ hole==0.8.0
|
|||||||
holidays==0.75
|
holidays==0.75
|
||||||
|
|
||||||
# homeassistant.components.frontend
|
# homeassistant.components.frontend
|
||||||
home-assistant-frontend==20250702.0
|
home-assistant-frontend==20250702.1
|
||||||
|
|
||||||
# homeassistant.components.conversation
|
# homeassistant.components.conversation
|
||||||
home-assistant-intents==2025.6.23
|
home-assistant-intents==2025.6.23
|
||||||
@ -1467,7 +1467,7 @@ mozart-api==4.1.1.116.4
|
|||||||
mullvad-api==1.0.0
|
mullvad-api==1.0.0
|
||||||
|
|
||||||
# homeassistant.components.music_assistant
|
# homeassistant.components.music_assistant
|
||||||
music-assistant-client==1.2.3
|
music-assistant-client==1.2.4
|
||||||
|
|
||||||
# homeassistant.components.tts
|
# homeassistant.components.tts
|
||||||
mutagen==1.47.0
|
mutagen==1.47.0
|
||||||
@ -1962,7 +1962,7 @@ pyeiscp==0.0.7
|
|||||||
pyemoncms==0.1.1
|
pyemoncms==0.1.1
|
||||||
|
|
||||||
# homeassistant.components.enphase_envoy
|
# homeassistant.components.enphase_envoy
|
||||||
pyenphase==2.1.0
|
pyenphase==2.2.0
|
||||||
|
|
||||||
# homeassistant.components.envisalink
|
# homeassistant.components.envisalink
|
||||||
pyenvisalink==4.7
|
pyenvisalink==4.7
|
||||||
@ -3041,7 +3041,7 @@ vehicle==2.2.2
|
|||||||
velbus-aio==2025.5.0
|
velbus-aio==2025.5.0
|
||||||
|
|
||||||
# homeassistant.components.venstar
|
# homeassistant.components.venstar
|
||||||
venstarcolortouch==0.19
|
venstarcolortouch==0.21
|
||||||
|
|
||||||
# homeassistant.components.vilfo
|
# homeassistant.components.vilfo
|
||||||
vilfo-api-client==0.5.0
|
vilfo-api-client==0.5.0
|
||||||
@ -3190,7 +3190,7 @@ zeroconf==0.147.0
|
|||||||
zeversolar==0.3.2
|
zeversolar==0.3.2
|
||||||
|
|
||||||
# homeassistant.components.zha
|
# homeassistant.components.zha
|
||||||
zha==0.0.61
|
zha==0.0.62
|
||||||
|
|
||||||
# homeassistant.components.zhong_hong
|
# homeassistant.components.zhong_hong
|
||||||
zhong-hong-hvac==1.0.13
|
zhong-hong-hvac==1.0.13
|
||||||
|
16
requirements_test_all.txt
generated
16
requirements_test_all.txt
generated
@ -173,7 +173,7 @@ aioairzone-cloud==0.6.12
|
|||||||
aioairzone==1.0.0
|
aioairzone==1.0.0
|
||||||
|
|
||||||
# homeassistant.components.alexa_devices
|
# homeassistant.components.alexa_devices
|
||||||
aioamazondevices==3.2.2
|
aioamazondevices==3.2.3
|
||||||
|
|
||||||
# homeassistant.components.ambient_network
|
# homeassistant.components.ambient_network
|
||||||
# homeassistant.components.ambient_station
|
# homeassistant.components.ambient_station
|
||||||
@ -396,7 +396,7 @@ aiotedee==0.2.25
|
|||||||
aiotractive==0.6.0
|
aiotractive==0.6.0
|
||||||
|
|
||||||
# homeassistant.components.unifi
|
# homeassistant.components.unifi
|
||||||
aiounifi==83
|
aiounifi==84
|
||||||
|
|
||||||
# homeassistant.components.usb
|
# homeassistant.components.usb
|
||||||
aiousbwatcher==1.1.1
|
aiousbwatcher==1.1.1
|
||||||
@ -988,7 +988,7 @@ habiticalib==0.4.0
|
|||||||
habluetooth==3.49.0
|
habluetooth==3.49.0
|
||||||
|
|
||||||
# homeassistant.components.cloud
|
# homeassistant.components.cloud
|
||||||
hass-nabucasa==0.104.0
|
hass-nabucasa==0.105.0
|
||||||
|
|
||||||
# homeassistant.components.assist_satellite
|
# homeassistant.components.assist_satellite
|
||||||
# homeassistant.components.conversation
|
# homeassistant.components.conversation
|
||||||
@ -1017,7 +1017,7 @@ hole==0.8.0
|
|||||||
holidays==0.75
|
holidays==0.75
|
||||||
|
|
||||||
# homeassistant.components.frontend
|
# homeassistant.components.frontend
|
||||||
home-assistant-frontend==20250702.0
|
home-assistant-frontend==20250702.1
|
||||||
|
|
||||||
# homeassistant.components.conversation
|
# homeassistant.components.conversation
|
||||||
home-assistant-intents==2025.6.23
|
home-assistant-intents==2025.6.23
|
||||||
@ -1259,7 +1259,7 @@ mozart-api==4.1.1.116.4
|
|||||||
mullvad-api==1.0.0
|
mullvad-api==1.0.0
|
||||||
|
|
||||||
# homeassistant.components.music_assistant
|
# homeassistant.components.music_assistant
|
||||||
music-assistant-client==1.2.3
|
music-assistant-client==1.2.4
|
||||||
|
|
||||||
# homeassistant.components.tts
|
# homeassistant.components.tts
|
||||||
mutagen==1.47.0
|
mutagen==1.47.0
|
||||||
@ -1637,7 +1637,7 @@ pyeiscp==0.0.7
|
|||||||
pyemoncms==0.1.1
|
pyemoncms==0.1.1
|
||||||
|
|
||||||
# homeassistant.components.enphase_envoy
|
# homeassistant.components.enphase_envoy
|
||||||
pyenphase==2.1.0
|
pyenphase==2.2.0
|
||||||
|
|
||||||
# homeassistant.components.everlights
|
# homeassistant.components.everlights
|
||||||
pyeverlights==0.1.0
|
pyeverlights==0.1.0
|
||||||
@ -2509,7 +2509,7 @@ vehicle==2.2.2
|
|||||||
velbus-aio==2025.5.0
|
velbus-aio==2025.5.0
|
||||||
|
|
||||||
# homeassistant.components.venstar
|
# homeassistant.components.venstar
|
||||||
venstarcolortouch==0.19
|
venstarcolortouch==0.21
|
||||||
|
|
||||||
# homeassistant.components.vilfo
|
# homeassistant.components.vilfo
|
||||||
vilfo-api-client==0.5.0
|
vilfo-api-client==0.5.0
|
||||||
@ -2634,7 +2634,7 @@ zeroconf==0.147.0
|
|||||||
zeversolar==0.3.2
|
zeversolar==0.3.2
|
||||||
|
|
||||||
# homeassistant.components.zha
|
# homeassistant.components.zha
|
||||||
zha==0.0.61
|
zha==0.0.62
|
||||||
|
|
||||||
# homeassistant.components.zwave_js
|
# homeassistant.components.zwave_js
|
||||||
zwave-js-server-python==0.65.0
|
zwave-js-server-python==0.65.0
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
"""Test the Remote Calendar config flow."""
|
"""Test the Remote Calendar config flow."""
|
||||||
|
|
||||||
from httpx import ConnectError, Response, UnsupportedProtocol
|
from httpx import HTTPError, InvalidURL, Response, TimeoutException
|
||||||
import pytest
|
import pytest
|
||||||
import respx
|
import respx
|
||||||
|
|
||||||
@ -75,10 +75,11 @@ async def test_form_import_webcal(hass: HomeAssistant, ics_content: str) -> None
|
|||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
("side_effect"),
|
("side_effect", "base_error"),
|
||||||
[
|
[
|
||||||
ConnectError("Connection failed"),
|
(TimeoutException("Connection timed out"), "timeout_connect"),
|
||||||
UnsupportedProtocol("Unsupported protocol"),
|
(HTTPError("Connection failed"), "cannot_connect"),
|
||||||
|
(InvalidURL("Unsupported protocol"), "cannot_connect"),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
@respx.mock
|
@respx.mock
|
||||||
@ -86,6 +87,7 @@ async def test_form_inavild_url(
|
|||||||
hass: HomeAssistant,
|
hass: HomeAssistant,
|
||||||
side_effect: Exception,
|
side_effect: Exception,
|
||||||
ics_content: str,
|
ics_content: str,
|
||||||
|
base_error: str,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Test we get the import form."""
|
"""Test we get the import form."""
|
||||||
result = await hass.config_entries.flow.async_init(
|
result = await hass.config_entries.flow.async_init(
|
||||||
@ -102,7 +104,7 @@ async def test_form_inavild_url(
|
|||||||
},
|
},
|
||||||
)
|
)
|
||||||
assert result2["type"] is FlowResultType.FORM
|
assert result2["type"] is FlowResultType.FORM
|
||||||
assert result2["errors"] == {"base": "cannot_connect"}
|
assert result2["errors"] == {"base": base_error}
|
||||||
respx.get(CALENDER_URL).mock(
|
respx.get(CALENDER_URL).mock(
|
||||||
return_value=Response(
|
return_value=Response(
|
||||||
status_code=200,
|
status_code=200,
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
"""Tests for init platform of Remote Calendar."""
|
"""Tests for init platform of Remote Calendar."""
|
||||||
|
|
||||||
from httpx import ConnectError, Response, UnsupportedProtocol
|
from httpx import HTTPError, InvalidURL, Response, TimeoutException
|
||||||
import pytest
|
import pytest
|
||||||
import respx
|
import respx
|
||||||
|
|
||||||
@ -56,8 +56,9 @@ async def test_raise_for_status(
|
|||||||
@pytest.mark.parametrize(
|
@pytest.mark.parametrize(
|
||||||
"side_effect",
|
"side_effect",
|
||||||
[
|
[
|
||||||
ConnectError("Connection failed"),
|
TimeoutException("Connection timed out"),
|
||||||
UnsupportedProtocol("Unsupported protocol"),
|
HTTPError("Connection failed"),
|
||||||
|
InvalidURL("Unsupported protocol"),
|
||||||
ValueError("Invalid response"),
|
ValueError("Invalid response"),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
@ -161,6 +161,7 @@ async def test_user_legacy(hass: HomeAssistant) -> None:
|
|||||||
assert result["data"][CONF_METHOD] == METHOD_LEGACY
|
assert result["data"][CONF_METHOD] == METHOD_LEGACY
|
||||||
assert result["data"][CONF_MANUFACTURER] == DEFAULT_MANUFACTURER
|
assert result["data"][CONF_MANUFACTURER] == DEFAULT_MANUFACTURER
|
||||||
assert result["data"][CONF_MODEL] is None
|
assert result["data"][CONF_MODEL] is None
|
||||||
|
assert result["data"][CONF_PORT] == 55000
|
||||||
assert result["result"].unique_id is None
|
assert result["result"].unique_id is None
|
||||||
|
|
||||||
|
|
||||||
@ -195,6 +196,7 @@ async def test_user_legacy_does_not_ok_first_time(hass: HomeAssistant) -> None:
|
|||||||
assert result3["data"][CONF_METHOD] == METHOD_LEGACY
|
assert result3["data"][CONF_METHOD] == METHOD_LEGACY
|
||||||
assert result3["data"][CONF_MANUFACTURER] == DEFAULT_MANUFACTURER
|
assert result3["data"][CONF_MANUFACTURER] == DEFAULT_MANUFACTURER
|
||||||
assert result3["data"][CONF_MODEL] is None
|
assert result3["data"][CONF_MODEL] is None
|
||||||
|
assert result3["data"][CONF_PORT] == 55000
|
||||||
assert result3["result"].unique_id is None
|
assert result3["result"].unique_id is None
|
||||||
|
|
||||||
|
|
||||||
@ -224,6 +226,7 @@ async def test_user_websocket(hass: HomeAssistant) -> None:
|
|||||||
assert result["data"][CONF_METHOD] == "websocket"
|
assert result["data"][CONF_METHOD] == "websocket"
|
||||||
assert result["data"][CONF_MANUFACTURER] == "Samsung"
|
assert result["data"][CONF_MANUFACTURER] == "Samsung"
|
||||||
assert result["data"][CONF_MODEL] == "82GXARRS"
|
assert result["data"][CONF_MODEL] == "82GXARRS"
|
||||||
|
assert result["data"][CONF_PORT] == 8002
|
||||||
assert result["result"].unique_id == "be9554b9-c9fb-41f4-8920-22da015376a4"
|
assert result["result"].unique_id == "be9554b9-c9fb-41f4-8920-22da015376a4"
|
||||||
|
|
||||||
|
|
||||||
@ -272,6 +275,7 @@ async def test_user_encrypted_websocket(
|
|||||||
assert result4["data"][CONF_MAC] == "aa:bb:aa:aa:aa:aa"
|
assert result4["data"][CONF_MAC] == "aa:bb:aa:aa:aa:aa"
|
||||||
assert result4["data"][CONF_MANUFACTURER] == "Samsung"
|
assert result4["data"][CONF_MANUFACTURER] == "Samsung"
|
||||||
assert result4["data"][CONF_MODEL] == "UE48JU6400"
|
assert result4["data"][CONF_MODEL] == "UE48JU6400"
|
||||||
|
assert result4["data"][CONF_PORT] == 8000
|
||||||
assert result4["data"][CONF_SSDP_RENDERING_CONTROL_LOCATION] is None
|
assert result4["data"][CONF_SSDP_RENDERING_CONTROL_LOCATION] is None
|
||||||
assert result4["data"][CONF_TOKEN] == "037739871315caef138547b03e348b72"
|
assert result4["data"][CONF_TOKEN] == "037739871315caef138547b03e348b72"
|
||||||
assert result4["data"][CONF_SESSION_ID] == "1"
|
assert result4["data"][CONF_SESSION_ID] == "1"
|
||||||
@ -402,6 +406,7 @@ async def test_user_websocket_auth_retry(hass: HomeAssistant) -> None:
|
|||||||
assert result["data"][CONF_HOST] == "10.20.43.21"
|
assert result["data"][CONF_HOST] == "10.20.43.21"
|
||||||
assert result["data"][CONF_MANUFACTURER] == "Samsung"
|
assert result["data"][CONF_MANUFACTURER] == "Samsung"
|
||||||
assert result["data"][CONF_MODEL] == "82GXARRS"
|
assert result["data"][CONF_MODEL] == "82GXARRS"
|
||||||
|
assert result["data"][CONF_PORT] == 8002
|
||||||
assert result["result"].unique_id == "be9554b9-c9fb-41f4-8920-22da015376a4"
|
assert result["result"].unique_id == "be9554b9-c9fb-41f4-8920-22da015376a4"
|
||||||
|
|
||||||
|
|
||||||
@ -464,6 +469,7 @@ async def test_ssdp(hass: HomeAssistant) -> None:
|
|||||||
assert result["data"][CONF_HOST] == "10.10.12.34"
|
assert result["data"][CONF_HOST] == "10.10.12.34"
|
||||||
assert result["data"][CONF_MANUFACTURER] == "Samsung Electronics"
|
assert result["data"][CONF_MANUFACTURER] == "Samsung Electronics"
|
||||||
assert result["data"][CONF_MODEL] == "UE55H6400"
|
assert result["data"][CONF_MODEL] == "UE55H6400"
|
||||||
|
assert result["data"][CONF_PORT] == 55000
|
||||||
assert result["result"].unique_id == "068e7781-006e-1000-bbbf-84a4668d8423"
|
assert result["result"].unique_id == "068e7781-006e-1000-bbbf-84a4668d8423"
|
||||||
|
|
||||||
|
|
||||||
@ -522,6 +528,7 @@ async def test_ssdp_noprefix(hass: HomeAssistant) -> None:
|
|||||||
assert result["data"][CONF_HOST] == "10.10.12.34"
|
assert result["data"][CONF_HOST] == "10.10.12.34"
|
||||||
assert result["data"][CONF_MANUFACTURER] == "Samsung Electronics"
|
assert result["data"][CONF_MANUFACTURER] == "Samsung Electronics"
|
||||||
assert result["data"][CONF_MODEL] == "UE55H6400"
|
assert result["data"][CONF_MODEL] == "UE55H6400"
|
||||||
|
assert result["data"][CONF_PORT] == 55000
|
||||||
assert result["result"].unique_id == "068e7781-006e-1000-bbbf-84a4668d8423"
|
assert result["result"].unique_id == "068e7781-006e-1000-bbbf-84a4668d8423"
|
||||||
|
|
||||||
|
|
||||||
@ -557,6 +564,7 @@ async def test_ssdp_legacy_missing_auth(hass: HomeAssistant) -> None:
|
|||||||
assert result["data"][CONF_HOST] == "10.10.12.34"
|
assert result["data"][CONF_HOST] == "10.10.12.34"
|
||||||
assert result["data"][CONF_MANUFACTURER] == "Samsung Electronics"
|
assert result["data"][CONF_MANUFACTURER] == "Samsung Electronics"
|
||||||
assert result["data"][CONF_MODEL] == "UE55H6400"
|
assert result["data"][CONF_MODEL] == "UE55H6400"
|
||||||
|
assert result["data"][CONF_PORT] == 55000
|
||||||
assert result["result"].unique_id == "068e7781-006e-1000-bbbf-84a4668d8423"
|
assert result["result"].unique_id == "068e7781-006e-1000-bbbf-84a4668d8423"
|
||||||
|
|
||||||
|
|
||||||
@ -599,6 +607,7 @@ async def test_ssdp_websocket_success_populates_mac_address_and_ssdp_location(
|
|||||||
assert result["data"][CONF_MAC] == "aa:bb:aa:aa:aa:aa"
|
assert result["data"][CONF_MAC] == "aa:bb:aa:aa:aa:aa"
|
||||||
assert result["data"][CONF_MANUFACTURER] == "Samsung Electronics"
|
assert result["data"][CONF_MANUFACTURER] == "Samsung Electronics"
|
||||||
assert result["data"][CONF_MODEL] == "82GXARRS"
|
assert result["data"][CONF_MODEL] == "82GXARRS"
|
||||||
|
assert result["data"][CONF_PORT] == 8002
|
||||||
assert (
|
assert (
|
||||||
result["data"][CONF_SSDP_RENDERING_CONTROL_LOCATION]
|
result["data"][CONF_SSDP_RENDERING_CONTROL_LOCATION]
|
||||||
== "http://10.10.12.34:7676/smp_15_"
|
== "http://10.10.12.34:7676/smp_15_"
|
||||||
@ -630,6 +639,7 @@ async def test_ssdp_websocket_success_populates_mac_address_and_main_tv_ssdp_loc
|
|||||||
assert result["data"][CONF_MAC] == "aa:bb:aa:aa:aa:aa"
|
assert result["data"][CONF_MAC] == "aa:bb:aa:aa:aa:aa"
|
||||||
assert result["data"][CONF_MANUFACTURER] == "Samsung Electronics"
|
assert result["data"][CONF_MANUFACTURER] == "Samsung Electronics"
|
||||||
assert result["data"][CONF_MODEL] == "82GXARRS"
|
assert result["data"][CONF_MODEL] == "82GXARRS"
|
||||||
|
assert result["data"][CONF_PORT] == 8002
|
||||||
assert (
|
assert (
|
||||||
result["data"][CONF_SSDP_MAIN_TV_AGENT_LOCATION]
|
result["data"][CONF_SSDP_MAIN_TV_AGENT_LOCATION]
|
||||||
== "http://10.10.12.34:7676/smp_2_"
|
== "http://10.10.12.34:7676/smp_2_"
|
||||||
@ -681,6 +691,7 @@ async def test_ssdp_encrypted_websocket_success_populates_mac_address_and_ssdp_l
|
|||||||
assert result4["data"][CONF_MAC] == "aa:bb:aa:aa:aa:aa"
|
assert result4["data"][CONF_MAC] == "aa:bb:aa:aa:aa:aa"
|
||||||
assert result4["data"][CONF_MANUFACTURER] == "Samsung Electronics"
|
assert result4["data"][CONF_MANUFACTURER] == "Samsung Electronics"
|
||||||
assert result4["data"][CONF_MODEL] == "UE48JU6400"
|
assert result4["data"][CONF_MODEL] == "UE48JU6400"
|
||||||
|
assert result4["data"][CONF_PORT] == 8000
|
||||||
assert (
|
assert (
|
||||||
result4["data"][CONF_SSDP_RENDERING_CONTROL_LOCATION]
|
result4["data"][CONF_SSDP_RENDERING_CONTROL_LOCATION]
|
||||||
== "http://10.10.12.34:7676/smp_15_"
|
== "http://10.10.12.34:7676/smp_15_"
|
||||||
@ -887,6 +898,7 @@ async def test_dhcp_wireless(hass: HomeAssistant) -> None:
|
|||||||
assert result["data"][CONF_MAC] == "aa:bb:aa:aa:aa:aa"
|
assert result["data"][CONF_MAC] == "aa:bb:aa:aa:aa:aa"
|
||||||
assert result["data"][CONF_MANUFACTURER] == "Samsung"
|
assert result["data"][CONF_MANUFACTURER] == "Samsung"
|
||||||
assert result["data"][CONF_MODEL] == "UE48JU6400"
|
assert result["data"][CONF_MODEL] == "UE48JU6400"
|
||||||
|
assert result["data"][CONF_PORT] == 8002
|
||||||
assert result["result"].unique_id == "223da676-497a-4e06-9507-5e27ec4f0fb3"
|
assert result["result"].unique_id == "223da676-497a-4e06-9507-5e27ec4f0fb3"
|
||||||
|
|
||||||
|
|
||||||
@ -919,6 +931,7 @@ async def test_dhcp_wired(hass: HomeAssistant, rest_api: Mock) -> None:
|
|||||||
assert result["data"][CONF_MAC] == "aa:ee:tt:hh:ee:rr"
|
assert result["data"][CONF_MAC] == "aa:ee:tt:hh:ee:rr"
|
||||||
assert result["data"][CONF_MANUFACTURER] == "Samsung"
|
assert result["data"][CONF_MANUFACTURER] == "Samsung"
|
||||||
assert result["data"][CONF_MODEL] == "UE43LS003"
|
assert result["data"][CONF_MODEL] == "UE43LS003"
|
||||||
|
assert result["data"][CONF_PORT] == 8002
|
||||||
assert result["result"].unique_id == "be9554b9-c9fb-41f4-8920-22da015376a4"
|
assert result["result"].unique_id == "be9554b9-c9fb-41f4-8920-22da015376a4"
|
||||||
|
|
||||||
|
|
||||||
@ -1020,6 +1033,7 @@ async def test_zeroconf(hass: HomeAssistant) -> None:
|
|||||||
assert result["data"][CONF_MAC] == "aa:bb:aa:aa:aa:aa"
|
assert result["data"][CONF_MAC] == "aa:bb:aa:aa:aa:aa"
|
||||||
assert result["data"][CONF_MANUFACTURER] == "Samsung"
|
assert result["data"][CONF_MANUFACTURER] == "Samsung"
|
||||||
assert result["data"][CONF_MODEL] == "82GXARRS"
|
assert result["data"][CONF_MODEL] == "82GXARRS"
|
||||||
|
assert result["data"][CONF_PORT] == 8002
|
||||||
assert result["result"].unique_id == "be9554b9-c9fb-41f4-8920-22da015376a4"
|
assert result["result"].unique_id == "be9554b9-c9fb-41f4-8920-22da015376a4"
|
||||||
|
|
||||||
|
|
||||||
@ -1129,6 +1143,7 @@ async def test_autodetect_websocket(hass: HomeAssistant) -> None:
|
|||||||
assert result["type"] is FlowResultType.CREATE_ENTRY
|
assert result["type"] is FlowResultType.CREATE_ENTRY
|
||||||
assert result["data"][CONF_METHOD] == "websocket"
|
assert result["data"][CONF_METHOD] == "websocket"
|
||||||
assert result["data"][CONF_TOKEN] == "123456789"
|
assert result["data"][CONF_TOKEN] == "123456789"
|
||||||
|
assert result["data"][CONF_PORT] == 8002
|
||||||
remote_websocket.assert_called_once_with(**AUTODETECT_WEBSOCKET_SSL)
|
remote_websocket.assert_called_once_with(**AUTODETECT_WEBSOCKET_SSL)
|
||||||
rest_api_class.assert_called_once_with(**DEVICEINFO_WEBSOCKET_SSL)
|
rest_api_class.assert_called_once_with(**DEVICEINFO_WEBSOCKET_SSL)
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
@ -1180,6 +1195,7 @@ async def test_websocket_no_mac(hass: HomeAssistant, mac_address: Mock) -> None:
|
|||||||
assert result["data"][CONF_METHOD] == "websocket"
|
assert result["data"][CONF_METHOD] == "websocket"
|
||||||
assert result["data"][CONF_TOKEN] == "123456789"
|
assert result["data"][CONF_TOKEN] == "123456789"
|
||||||
assert result["data"][CONF_MAC] == "gg:ee:tt:mm:aa:cc"
|
assert result["data"][CONF_MAC] == "gg:ee:tt:mm:aa:cc"
|
||||||
|
assert result["data"][CONF_PORT] == 8002
|
||||||
remote_websocket.assert_called_once_with(**AUTODETECT_WEBSOCKET_SSL)
|
remote_websocket.assert_called_once_with(**AUTODETECT_WEBSOCKET_SSL)
|
||||||
rest_api_class.assert_called_once_with(**DEVICEINFO_WEBSOCKET_SSL)
|
rest_api_class.assert_called_once_with(**DEVICEINFO_WEBSOCKET_SSL)
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
@ -2091,6 +2107,7 @@ async def test_ssdp_update_mac(hass: HomeAssistant) -> None:
|
|||||||
assert entry.data[CONF_MANUFACTURER] == DEFAULT_MANUFACTURER
|
assert entry.data[CONF_MANUFACTURER] == DEFAULT_MANUFACTURER
|
||||||
assert entry.data[CONF_MODEL] == "fake_model"
|
assert entry.data[CONF_MODEL] == "fake_model"
|
||||||
assert entry.data[CONF_MAC] is None
|
assert entry.data[CONF_MAC] is None
|
||||||
|
assert entry.data[CONF_PORT] == 8002
|
||||||
assert entry.unique_id == "123"
|
assert entry.unique_id == "123"
|
||||||
|
|
||||||
device_info = deepcopy(MOCK_DEVICE_INFO)
|
device_info = deepcopy(MOCK_DEVICE_INFO)
|
||||||
|
@ -63,7 +63,7 @@ async def test_options_flow(
|
|||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
assert result["type"] == FlowResultType.CREATE_ENTRY
|
assert result["type"] == FlowResultType.CREATE_ENTRY
|
||||||
assert result["data"][ATTR_PARSER] is None
|
assert result["data"][ATTR_PARSER] == PARSER_PLAIN_TEXT
|
||||||
|
|
||||||
|
|
||||||
async def test_reconfigure_flow_broadcast(
|
async def test_reconfigure_flow_broadcast(
|
||||||
|
@ -50,6 +50,7 @@ from homeassistant.components.telegram_bot.const import (
|
|||||||
ATTR_VERIFY_SSL,
|
ATTR_VERIFY_SSL,
|
||||||
CONF_CONFIG_ENTRY_ID,
|
CONF_CONFIG_ENTRY_ID,
|
||||||
DOMAIN,
|
DOMAIN,
|
||||||
|
PARSER_PLAIN_TEXT,
|
||||||
PLATFORM_BROADCAST,
|
PLATFORM_BROADCAST,
|
||||||
SECTION_ADVANCED_SETTINGS,
|
SECTION_ADVANCED_SETTINGS,
|
||||||
SERVICE_ANSWER_CALLBACK_QUERY,
|
SERVICE_ANSWER_CALLBACK_QUERY,
|
||||||
@ -183,6 +184,7 @@ async def test_send_message(
|
|||||||
(
|
(
|
||||||
{
|
{
|
||||||
ATTR_MESSAGE: "test_message",
|
ATTR_MESSAGE: "test_message",
|
||||||
|
ATTR_PARSER: PARSER_PLAIN_TEXT,
|
||||||
ATTR_KEYBOARD_INLINE: "command1:/cmd1,/cmd2,mock_link:https://mock_link",
|
ATTR_KEYBOARD_INLINE: "command1:/cmd1,/cmd2,mock_link:https://mock_link",
|
||||||
},
|
},
|
||||||
InlineKeyboardMarkup(
|
InlineKeyboardMarkup(
|
||||||
@ -199,6 +201,7 @@ async def test_send_message(
|
|||||||
(
|
(
|
||||||
{
|
{
|
||||||
ATTR_MESSAGE: "test_message",
|
ATTR_MESSAGE: "test_message",
|
||||||
|
ATTR_PARSER: PARSER_PLAIN_TEXT,
|
||||||
ATTR_KEYBOARD_INLINE: [
|
ATTR_KEYBOARD_INLINE: [
|
||||||
[["command1", "/cmd1"]],
|
[["command1", "/cmd1"]],
|
||||||
[["mock_link", "https://mock_link"]],
|
[["mock_link", "https://mock_link"]],
|
||||||
@ -250,7 +253,7 @@ async def test_send_message_with_inline_keyboard(
|
|||||||
mock_send_message.assert_called_once_with(
|
mock_send_message.assert_called_once_with(
|
||||||
12345678,
|
12345678,
|
||||||
"test_message",
|
"test_message",
|
||||||
parse_mode=ParseMode.MARKDOWN,
|
parse_mode=None,
|
||||||
disable_web_page_preview=None,
|
disable_web_page_preview=None,
|
||||||
disable_notification=False,
|
disable_notification=False,
|
||||||
reply_to_message_id=None,
|
reply_to_message_id=None,
|
||||||
|
@ -168,7 +168,6 @@
|
|||||||
dict({
|
dict({
|
||||||
'id': '0x0010',
|
'id': '0x0010',
|
||||||
'name': 'cie_addr',
|
'name': 'cie_addr',
|
||||||
'unsupported': False,
|
|
||||||
'value': list([
|
'value': list([
|
||||||
50,
|
50,
|
||||||
79,
|
79,
|
||||||
@ -181,68 +180,18 @@
|
|||||||
]),
|
]),
|
||||||
'zcl_type': 'EUI64',
|
'zcl_type': 'EUI64',
|
||||||
}),
|
}),
|
||||||
dict({
|
|
||||||
'id': '0x0013',
|
|
||||||
'name': 'current_zone_sensitivity_level',
|
|
||||||
'unsupported': False,
|
|
||||||
'value': None,
|
|
||||||
'zcl_type': 'uint8',
|
|
||||||
}),
|
|
||||||
dict({
|
dict({
|
||||||
'id': '0x0012',
|
'id': '0x0012',
|
||||||
'name': 'num_zone_sensitivity_levels_supported',
|
'name': 'num_zone_sensitivity_levels_supported',
|
||||||
'unsupported': True,
|
'unsupported': True,
|
||||||
'value': None,
|
|
||||||
'zcl_type': 'uint8',
|
'zcl_type': 'uint8',
|
||||||
}),
|
}),
|
||||||
dict({
|
|
||||||
'id': '0x0011',
|
|
||||||
'name': 'zone_id',
|
|
||||||
'unsupported': False,
|
|
||||||
'value': None,
|
|
||||||
'zcl_type': 'uint8',
|
|
||||||
}),
|
|
||||||
dict({
|
|
||||||
'id': '0x0000',
|
|
||||||
'name': 'zone_state',
|
|
||||||
'unsupported': False,
|
|
||||||
'value': None,
|
|
||||||
'zcl_type': 'enum8',
|
|
||||||
}),
|
|
||||||
dict({
|
|
||||||
'id': '0x0002',
|
|
||||||
'name': 'zone_status',
|
|
||||||
'unsupported': False,
|
|
||||||
'value': None,
|
|
||||||
'zcl_type': 'map16',
|
|
||||||
}),
|
|
||||||
dict({
|
|
||||||
'id': '0x0001',
|
|
||||||
'name': 'zone_type',
|
|
||||||
'unsupported': False,
|
|
||||||
'value': None,
|
|
||||||
'zcl_type': 'uint16',
|
|
||||||
}),
|
|
||||||
]),
|
]),
|
||||||
'cluster_id': '0x0500',
|
'cluster_id': '0x0500',
|
||||||
'endpoint_attribute': 'ias_zone',
|
'endpoint_attribute': 'ias_zone',
|
||||||
}),
|
}),
|
||||||
dict({
|
dict({
|
||||||
'attributes': list([
|
'attributes': list([
|
||||||
dict({
|
|
||||||
'id': '0xfffd',
|
|
||||||
'name': 'cluster_revision',
|
|
||||||
'unsupported': False,
|
|
||||||
'value': None,
|
|
||||||
'zcl_type': 'uint16',
|
|
||||||
}),
|
|
||||||
dict({
|
|
||||||
'id': '0xfffe',
|
|
||||||
'name': 'reporting_status',
|
|
||||||
'unsupported': False,
|
|
||||||
'value': None,
|
|
||||||
'zcl_type': 'enum8',
|
|
||||||
}),
|
|
||||||
]),
|
]),
|
||||||
'cluster_id': '0x0501',
|
'cluster_id': '0x0501',
|
||||||
'endpoint_attribute': 'ias_ace',
|
'endpoint_attribute': 'ias_ace',
|
||||||
|
Loading…
x
Reference in New Issue
Block a user