mirror of
https://github.com/home-assistant/core.git
synced 2025-07-31 09:17:10 +00:00
Merge pull request #48954 from home-assistant/rc
This commit is contained in:
commit
7b7cfd71de
@ -473,7 +473,7 @@ class CastDevice(MediaPlayerEntity):
|
|||||||
self.hass,
|
self.hass,
|
||||||
refresh_token.id,
|
refresh_token.id,
|
||||||
media_id,
|
media_id,
|
||||||
timedelta(minutes=5),
|
timedelta(seconds=media_source.DEFAULT_EXPIRY_TIME),
|
||||||
)
|
)
|
||||||
|
|
||||||
# prepend external URL
|
# prepend external URL
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
"name": "Home Assistant Frontend",
|
"name": "Home Assistant Frontend",
|
||||||
"documentation": "https://www.home-assistant.io/integrations/frontend",
|
"documentation": "https://www.home-assistant.io/integrations/frontend",
|
||||||
"requirements": [
|
"requirements": [
|
||||||
"home-assistant-frontend==20210407.2"
|
"home-assistant-frontend==20210407.3"
|
||||||
],
|
],
|
||||||
"dependencies": [
|
"dependencies": [
|
||||||
"api",
|
"api",
|
||||||
|
@ -148,7 +148,7 @@ class HassIO:
|
|||||||
|
|
||||||
This method return a coroutine.
|
This method return a coroutine.
|
||||||
"""
|
"""
|
||||||
return self.send_command("/discovery", method="get")
|
return self.send_command("/discovery", method="get", timeout=60)
|
||||||
|
|
||||||
@api_data
|
@api_data
|
||||||
def get_discovery_message(self, uuid):
|
def get_discovery_message(self, uuid):
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
"name": "Kodi",
|
"name": "Kodi",
|
||||||
"documentation": "https://www.home-assistant.io/integrations/kodi",
|
"documentation": "https://www.home-assistant.io/integrations/kodi",
|
||||||
"requirements": [
|
"requirements": [
|
||||||
"pykodi==0.2.3"
|
"pykodi==0.2.5"
|
||||||
],
|
],
|
||||||
"codeowners": [
|
"codeowners": [
|
||||||
"@OnFreund",
|
"@OnFreund",
|
||||||
|
@ -19,6 +19,8 @@ from . import local_source, models
|
|||||||
from .const import DOMAIN, URI_SCHEME, URI_SCHEME_REGEX
|
from .const import DOMAIN, URI_SCHEME, URI_SCHEME_REGEX
|
||||||
from .error import Unresolvable
|
from .error import Unresolvable
|
||||||
|
|
||||||
|
DEFAULT_EXPIRY_TIME = 3600 * 24
|
||||||
|
|
||||||
|
|
||||||
def is_media_source_id(media_content_id: str):
|
def is_media_source_id(media_content_id: str):
|
||||||
"""Test if identifier is a media source."""
|
"""Test if identifier is a media source."""
|
||||||
@ -105,7 +107,7 @@ async def websocket_browse_media(hass, connection, msg):
|
|||||||
{
|
{
|
||||||
vol.Required("type"): "media_source/resolve_media",
|
vol.Required("type"): "media_source/resolve_media",
|
||||||
vol.Required(ATTR_MEDIA_CONTENT_ID): str,
|
vol.Required(ATTR_MEDIA_CONTENT_ID): str,
|
||||||
vol.Optional("expires", default=30): int,
|
vol.Optional("expires", default=DEFAULT_EXPIRY_TIME): int,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
@websocket_api.async_response
|
@websocket_api.async_response
|
||||||
|
@ -116,12 +116,9 @@ class NotifyEventsNotificationService(BaseNotificationService):
|
|||||||
|
|
||||||
def send_message(self, message, **kwargs):
|
def send_message(self, message, **kwargs):
|
||||||
"""Send a message."""
|
"""Send a message."""
|
||||||
token = self.token
|
|
||||||
data = kwargs.get(ATTR_DATA) or {}
|
data = kwargs.get(ATTR_DATA) or {}
|
||||||
|
token = data.get(ATTR_TOKEN, self.token)
|
||||||
|
|
||||||
msg = self.prepare_message(message, data)
|
msg = self.prepare_message(message, data)
|
||||||
|
|
||||||
if data.get(ATTR_TOKEN, "").trim():
|
|
||||||
token = data[ATTR_TOKEN]
|
|
||||||
|
|
||||||
msg.send(token)
|
msg.send(token)
|
||||||
|
@ -122,7 +122,7 @@ class WeatherUpdateCoordinator(DataUpdateCoordinator):
|
|||||||
ATTR_API_FEELS_LIKE_TEMPERATURE: current_weather.temperature("celsius").get(
|
ATTR_API_FEELS_LIKE_TEMPERATURE: current_weather.temperature("celsius").get(
|
||||||
"feels_like"
|
"feels_like"
|
||||||
),
|
),
|
||||||
ATTR_API_DEW_POINT: (round(current_weather.dewpoint / 100, 1)),
|
ATTR_API_DEW_POINT: self._fmt_dewpoint(current_weather.dewpoint),
|
||||||
ATTR_API_PRESSURE: current_weather.pressure.get("press"),
|
ATTR_API_PRESSURE: current_weather.pressure.get("press"),
|
||||||
ATTR_API_HUMIDITY: current_weather.humidity,
|
ATTR_API_HUMIDITY: current_weather.humidity,
|
||||||
ATTR_API_WIND_BEARING: current_weather.wind().get("deg"),
|
ATTR_API_WIND_BEARING: current_weather.wind().get("deg"),
|
||||||
@ -178,6 +178,12 @@ class WeatherUpdateCoordinator(DataUpdateCoordinator):
|
|||||||
|
|
||||||
return forecast
|
return forecast
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _fmt_dewpoint(dewpoint):
|
||||||
|
if dewpoint is not None:
|
||||||
|
return round(dewpoint / 100, 1)
|
||||||
|
return None
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _get_rain(rain):
|
def _get_rain(rain):
|
||||||
"""Get rain data from weather data."""
|
"""Get rain data from weather data."""
|
||||||
|
@ -7,7 +7,7 @@ from homeassistant.components.media_player.const import (
|
|||||||
)
|
)
|
||||||
from homeassistant.util import dt as dt_util
|
from homeassistant.util import dt as dt_util
|
||||||
|
|
||||||
LIVE_TV_SECTION = "-4"
|
LIVE_TV_SECTION = -4
|
||||||
|
|
||||||
|
|
||||||
class PlexSession:
|
class PlexSession:
|
||||||
|
@ -1,10 +1,15 @@
|
|||||||
"""Support for Rituals Perfume Genie switches."""
|
"""Support for Rituals Perfume Genie switches."""
|
||||||
from datetime import timedelta
|
from datetime import timedelta
|
||||||
|
import logging
|
||||||
|
|
||||||
|
import aiohttp
|
||||||
|
|
||||||
from homeassistant.components.switch import SwitchEntity
|
from homeassistant.components.switch import SwitchEntity
|
||||||
|
|
||||||
from .const import DOMAIN
|
from .const import DOMAIN
|
||||||
|
|
||||||
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
SCAN_INTERVAL = timedelta(seconds=30)
|
SCAN_INTERVAL = timedelta(seconds=30)
|
||||||
|
|
||||||
ON_STATE = "1"
|
ON_STATE = "1"
|
||||||
@ -33,6 +38,7 @@ class DiffuserSwitch(SwitchEntity):
|
|||||||
def __init__(self, diffuser):
|
def __init__(self, diffuser):
|
||||||
"""Initialize the switch."""
|
"""Initialize the switch."""
|
||||||
self._diffuser = diffuser
|
self._diffuser = diffuser
|
||||||
|
self._available = True
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def device_info(self):
|
def device_info(self):
|
||||||
@ -53,7 +59,7 @@ class DiffuserSwitch(SwitchEntity):
|
|||||||
@property
|
@property
|
||||||
def available(self):
|
def available(self):
|
||||||
"""Return if the device is available."""
|
"""Return if the device is available."""
|
||||||
return self._diffuser.data["hub"]["status"] == AVAILABLE_STATE
|
return self._available
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def name(self):
|
def name(self):
|
||||||
@ -89,4 +95,10 @@ class DiffuserSwitch(SwitchEntity):
|
|||||||
|
|
||||||
async def async_update(self):
|
async def async_update(self):
|
||||||
"""Update the data of the device."""
|
"""Update the data of the device."""
|
||||||
await self._diffuser.update_data()
|
try:
|
||||||
|
await self._diffuser.update_data()
|
||||||
|
except aiohttp.ClientError:
|
||||||
|
self._available = False
|
||||||
|
_LOGGER.error("Unable to retrieve data from rituals.sense-company.com")
|
||||||
|
else:
|
||||||
|
self._available = self._diffuser.data["hub"]["status"] == AVAILABLE_STATE
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
"""Sensor that can display the current Home Assistant versions."""
|
"""Sensor that can display the current Home Assistant versions."""
|
||||||
from datetime import timedelta
|
from datetime import timedelta
|
||||||
|
import logging
|
||||||
|
|
||||||
from pyhaversion import HaVersion, HaVersionChannel, HaVersionSource
|
from pyhaversion import HaVersion, HaVersionChannel, HaVersionSource
|
||||||
|
from pyhaversion.exceptions import HaVersionFetchException, HaVersionParseException
|
||||||
import voluptuous as vol
|
import voluptuous as vol
|
||||||
|
|
||||||
from homeassistant.components.sensor import PLATFORM_SCHEMA, SensorEntity
|
from homeassistant.components.sensor import PLATFORM_SCHEMA, SensorEntity
|
||||||
@ -59,6 +61,8 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend(
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
_LOGGER: logging.Logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
async def async_setup_platform(hass, config, async_add_entities, discovery_info=None):
|
async def async_setup_platform(hass, config, async_add_entities, discovery_info=None):
|
||||||
"""Set up the Version sensor platform."""
|
"""Set up the Version sensor platform."""
|
||||||
@ -114,7 +118,14 @@ class VersionData:
|
|||||||
@Throttle(TIME_BETWEEN_UPDATES)
|
@Throttle(TIME_BETWEEN_UPDATES)
|
||||||
async def async_update(self):
|
async def async_update(self):
|
||||||
"""Get the latest version information."""
|
"""Get the latest version information."""
|
||||||
await self.api.get_version()
|
try:
|
||||||
|
await self.api.get_version()
|
||||||
|
except HaVersionFetchException as exception:
|
||||||
|
_LOGGER.warning(exception)
|
||||||
|
except HaVersionParseException as exception:
|
||||||
|
_LOGGER.warning(
|
||||||
|
"Could not parse data received for %s - %s", self.api.source, exception
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class VersionSensor(SensorEntity):
|
class VersionSensor(SensorEntity):
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
"bellows==0.23.1",
|
"bellows==0.23.1",
|
||||||
"pyserial==3.5",
|
"pyserial==3.5",
|
||||||
"pyserial-asyncio==0.5",
|
"pyserial-asyncio==0.5",
|
||||||
"zha-quirks==0.0.55",
|
"zha-quirks==0.0.56",
|
||||||
"zigpy-cc==0.5.2",
|
"zigpy-cc==0.5.2",
|
||||||
"zigpy-deconz==0.12.0",
|
"zigpy-deconz==0.12.0",
|
||||||
"zigpy==0.33.0",
|
"zigpy==0.33.0",
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
"""Constants used by Home Assistant components."""
|
"""Constants used by Home Assistant components."""
|
||||||
MAJOR_VERSION = 2021
|
MAJOR_VERSION = 2021
|
||||||
MINOR_VERSION = 4
|
MINOR_VERSION = 4
|
||||||
PATCH_VERSION = "1"
|
PATCH_VERSION = "2"
|
||||||
__short_version__ = f"{MAJOR_VERSION}.{MINOR_VERSION}"
|
__short_version__ = f"{MAJOR_VERSION}.{MINOR_VERSION}"
|
||||||
__version__ = f"{__short_version__}.{PATCH_VERSION}"
|
__version__ = f"{__short_version__}.{PATCH_VERSION}"
|
||||||
REQUIRED_PYTHON_VER = (3, 8, 0)
|
REQUIRED_PYTHON_VER = (3, 8, 0)
|
||||||
|
@ -16,7 +16,7 @@ defusedxml==0.6.0
|
|||||||
distro==1.5.0
|
distro==1.5.0
|
||||||
emoji==1.2.0
|
emoji==1.2.0
|
||||||
hass-nabucasa==0.42.0
|
hass-nabucasa==0.42.0
|
||||||
home-assistant-frontend==20210407.2
|
home-assistant-frontend==20210407.3
|
||||||
httpx==0.17.1
|
httpx==0.17.1
|
||||||
jinja2>=2.11.3
|
jinja2>=2.11.3
|
||||||
netdisco==2.8.2
|
netdisco==2.8.2
|
||||||
|
@ -763,7 +763,7 @@ hole==0.5.1
|
|||||||
holidays==0.10.5.2
|
holidays==0.10.5.2
|
||||||
|
|
||||||
# homeassistant.components.frontend
|
# homeassistant.components.frontend
|
||||||
home-assistant-frontend==20210407.2
|
home-assistant-frontend==20210407.3
|
||||||
|
|
||||||
# homeassistant.components.zwave
|
# homeassistant.components.zwave
|
||||||
homeassistant-pyozw==0.1.10
|
homeassistant-pyozw==0.1.10
|
||||||
@ -1476,7 +1476,7 @@ pykira==0.1.1
|
|||||||
pykmtronic==0.0.3
|
pykmtronic==0.0.3
|
||||||
|
|
||||||
# homeassistant.components.kodi
|
# homeassistant.components.kodi
|
||||||
pykodi==0.2.3
|
pykodi==0.2.5
|
||||||
|
|
||||||
# homeassistant.components.kulersky
|
# homeassistant.components.kulersky
|
||||||
pykulersky==0.5.2
|
pykulersky==0.5.2
|
||||||
@ -2372,7 +2372,7 @@ zengge==0.2
|
|||||||
zeroconf==0.29.0
|
zeroconf==0.29.0
|
||||||
|
|
||||||
# homeassistant.components.zha
|
# homeassistant.components.zha
|
||||||
zha-quirks==0.0.55
|
zha-quirks==0.0.56
|
||||||
|
|
||||||
# homeassistant.components.zhong_hong
|
# homeassistant.components.zhong_hong
|
||||||
zhong_hong_hvac==1.0.9
|
zhong_hong_hvac==1.0.9
|
||||||
|
@ -412,7 +412,7 @@ hole==0.5.1
|
|||||||
holidays==0.10.5.2
|
holidays==0.10.5.2
|
||||||
|
|
||||||
# homeassistant.components.frontend
|
# homeassistant.components.frontend
|
||||||
home-assistant-frontend==20210407.2
|
home-assistant-frontend==20210407.3
|
||||||
|
|
||||||
# homeassistant.components.zwave
|
# homeassistant.components.zwave
|
||||||
homeassistant-pyozw==0.1.10
|
homeassistant-pyozw==0.1.10
|
||||||
@ -518,6 +518,9 @@ netdisco==2.8.2
|
|||||||
# homeassistant.components.nexia
|
# homeassistant.components.nexia
|
||||||
nexia==0.9.5
|
nexia==0.9.5
|
||||||
|
|
||||||
|
# homeassistant.components.notify_events
|
||||||
|
notify-events==1.0.4
|
||||||
|
|
||||||
# homeassistant.components.nsw_fuel_station
|
# homeassistant.components.nsw_fuel_station
|
||||||
nsw-fuel-api-client==1.0.10
|
nsw-fuel-api-client==1.0.10
|
||||||
|
|
||||||
@ -784,7 +787,7 @@ pykira==0.1.1
|
|||||||
pykmtronic==0.0.3
|
pykmtronic==0.0.3
|
||||||
|
|
||||||
# homeassistant.components.kodi
|
# homeassistant.components.kodi
|
||||||
pykodi==0.2.3
|
pykodi==0.2.5
|
||||||
|
|
||||||
# homeassistant.components.kulersky
|
# homeassistant.components.kulersky
|
||||||
pykulersky==0.5.2
|
pykulersky==0.5.2
|
||||||
@ -1230,7 +1233,7 @@ zeep[async]==4.0.0
|
|||||||
zeroconf==0.29.0
|
zeroconf==0.29.0
|
||||||
|
|
||||||
# homeassistant.components.zha
|
# homeassistant.components.zha
|
||||||
zha-quirks==0.0.55
|
zha-quirks==0.0.56
|
||||||
|
|
||||||
# homeassistant.components.zha
|
# homeassistant.components.zha
|
||||||
zigpy-cc==0.5.2
|
zigpy-cc==0.5.2
|
||||||
|
1
tests/components/notify_events/__init__.py
Normal file
1
tests/components/notify_events/__init__.py
Normal file
@ -0,0 +1 @@
|
|||||||
|
"""Tests for the notify_events integration."""
|
12
tests/components/notify_events/test_init.py
Normal file
12
tests/components/notify_events/test_init.py
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
"""The tests for notify_events."""
|
||||||
|
from homeassistant.components.notify_events.const import DOMAIN
|
||||||
|
from homeassistant.setup import async_setup_component
|
||||||
|
|
||||||
|
|
||||||
|
async def test_setup(hass):
|
||||||
|
"""Test setup of the integration."""
|
||||||
|
config = {"notify_events": {"token": "ABC"}}
|
||||||
|
assert await async_setup_component(hass, DOMAIN, config)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
assert DOMAIN in hass.data
|
38
tests/components/notify_events/test_notify.py
Normal file
38
tests/components/notify_events/test_notify.py
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
"""The tests for notify_events."""
|
||||||
|
from homeassistant.components.notify import ATTR_DATA, ATTR_MESSAGE, DOMAIN
|
||||||
|
from homeassistant.components.notify_events.notify import (
|
||||||
|
ATTR_LEVEL,
|
||||||
|
ATTR_PRIORITY,
|
||||||
|
ATTR_TOKEN,
|
||||||
|
)
|
||||||
|
|
||||||
|
from tests.common import async_mock_service
|
||||||
|
|
||||||
|
|
||||||
|
async def test_send_msg(hass):
|
||||||
|
"""Test notify.events service."""
|
||||||
|
notify_calls = async_mock_service(hass, DOMAIN, "events")
|
||||||
|
|
||||||
|
await hass.services.async_call(
|
||||||
|
DOMAIN,
|
||||||
|
"events",
|
||||||
|
{
|
||||||
|
ATTR_MESSAGE: "message content",
|
||||||
|
ATTR_DATA: {
|
||||||
|
ATTR_TOKEN: "XYZ",
|
||||||
|
ATTR_LEVEL: "warning",
|
||||||
|
ATTR_PRIORITY: "high",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
blocking=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
assert len(notify_calls) == 1
|
||||||
|
call = notify_calls[-1]
|
||||||
|
|
||||||
|
assert call.domain == DOMAIN
|
||||||
|
assert call.service == "events"
|
||||||
|
assert call.data.get(ATTR_MESSAGE) == "message content"
|
||||||
|
assert call.data.get(ATTR_DATA).get(ATTR_TOKEN) == "XYZ"
|
||||||
|
assert call.data.get(ATTR_DATA).get(ATTR_LEVEL) == "warning"
|
||||||
|
assert call.data.get(ATTR_DATA).get(ATTR_PRIORITY) == "high"
|
Loading…
x
Reference in New Issue
Block a user