mirror of
https://github.com/home-assistant/core.git
synced 2025-07-21 12:17:07 +00:00
commit
a3bcf69adf
@ -216,15 +216,15 @@ class DeconzFlowHandler(config_entries.ConfigFlow, domain=DOMAIN):
|
|||||||
This flow is triggered by the discovery component.
|
This flow is triggered by the discovery component.
|
||||||
"""
|
"""
|
||||||
self.bridge_id = normalize_bridge_id(user_input[CONF_SERIAL])
|
self.bridge_id = normalize_bridge_id(user_input[CONF_SERIAL])
|
||||||
gateway = self.hass.data.get(DOMAIN, {}).get(self.bridge_id)
|
|
||||||
|
|
||||||
if gateway:
|
for entry in self.hass.config_entries.async_entries(DOMAIN):
|
||||||
return self._update_entry(
|
if self.bridge_id == entry.unique_id:
|
||||||
gateway.config_entry,
|
return self._update_entry(
|
||||||
user_input[CONF_HOST],
|
entry,
|
||||||
user_input[CONF_PORT],
|
user_input[CONF_HOST],
|
||||||
user_input[CONF_API_KEY],
|
user_input[CONF_PORT],
|
||||||
)
|
user_input[CONF_API_KEY],
|
||||||
|
)
|
||||||
|
|
||||||
await self.async_set_unique_id(self.bridge_id)
|
await self.async_set_unique_id(self.bridge_id)
|
||||||
self._hassio_discovery = user_input
|
self._hassio_discovery = user_input
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
"name": "Emulated Roku",
|
"name": "Emulated Roku",
|
||||||
"config_flow": true,
|
"config_flow": true,
|
||||||
"documentation": "https://www.home-assistant.io/integrations/emulated_roku",
|
"documentation": "https://www.home-assistant.io/integrations/emulated_roku",
|
||||||
"requirements": ["emulated_roku==0.1.9"],
|
"requirements": ["emulated_roku==0.2.0"],
|
||||||
"dependencies": [],
|
"dependencies": [],
|
||||||
"codeowners": []
|
"codeowners": []
|
||||||
}
|
}
|
||||||
|
@ -785,7 +785,7 @@ class MediaPlayerDevice(Entity):
|
|||||||
@property
|
@property
|
||||||
def capability_attributes(self):
|
def capability_attributes(self):
|
||||||
"""Return capabilitiy attributes."""
|
"""Return capabilitiy attributes."""
|
||||||
supported_features = self.supported_features
|
supported_features = self.supported_features or 0
|
||||||
data = {}
|
data = {}
|
||||||
|
|
||||||
if supported_features & SUPPORT_SELECT_SOURCE:
|
if supported_features & SUPPORT_SELECT_SOURCE:
|
||||||
|
@ -7,6 +7,7 @@ from pathlib import Path
|
|||||||
from typing import Optional
|
from typing import Optional
|
||||||
|
|
||||||
from oauthlib.oauth2 import AccessDeniedError
|
from oauthlib.oauth2 import AccessDeniedError
|
||||||
|
import requests
|
||||||
from ring_doorbell import Auth, Ring
|
from ring_doorbell import Auth, Ring
|
||||||
import voluptuous as vol
|
import voluptuous as vol
|
||||||
|
|
||||||
@ -95,13 +96,19 @@ async def async_setup_entry(hass, entry):
|
|||||||
"api": ring,
|
"api": ring,
|
||||||
"devices": ring.devices(),
|
"devices": ring.devices(),
|
||||||
"device_data": GlobalDataUpdater(
|
"device_data": GlobalDataUpdater(
|
||||||
hass, entry.entry_id, ring, "update_devices", timedelta(minutes=1)
|
hass, "device", entry.entry_id, ring, "update_devices", timedelta(minutes=1)
|
||||||
),
|
),
|
||||||
"dings_data": GlobalDataUpdater(
|
"dings_data": GlobalDataUpdater(
|
||||||
hass, entry.entry_id, ring, "update_dings", timedelta(seconds=10)
|
hass,
|
||||||
|
"active dings",
|
||||||
|
entry.entry_id,
|
||||||
|
ring,
|
||||||
|
"update_dings",
|
||||||
|
timedelta(seconds=5),
|
||||||
),
|
),
|
||||||
"history_data": DeviceDataUpdater(
|
"history_data": DeviceDataUpdater(
|
||||||
hass,
|
hass,
|
||||||
|
"history",
|
||||||
entry.entry_id,
|
entry.entry_id,
|
||||||
ring,
|
ring,
|
||||||
lambda device: device.history(limit=10),
|
lambda device: device.history(limit=10),
|
||||||
@ -109,6 +116,7 @@ async def async_setup_entry(hass, entry):
|
|||||||
),
|
),
|
||||||
"health_data": DeviceDataUpdater(
|
"health_data": DeviceDataUpdater(
|
||||||
hass,
|
hass,
|
||||||
|
"health",
|
||||||
entry.entry_id,
|
entry.entry_id,
|
||||||
ring,
|
ring,
|
||||||
lambda device: device.update_health_data(),
|
lambda device: device.update_health_data(),
|
||||||
@ -168,6 +176,7 @@ class GlobalDataUpdater:
|
|||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
hass: HomeAssistant,
|
hass: HomeAssistant,
|
||||||
|
data_type: str,
|
||||||
config_entry_id: str,
|
config_entry_id: str,
|
||||||
ring: Ring,
|
ring: Ring,
|
||||||
update_method: str,
|
update_method: str,
|
||||||
@ -175,6 +184,7 @@ class GlobalDataUpdater:
|
|||||||
):
|
):
|
||||||
"""Initialize global data updater."""
|
"""Initialize global data updater."""
|
||||||
self.hass = hass
|
self.hass = hass
|
||||||
|
self.data_type = data_type
|
||||||
self.config_entry_id = config_entry_id
|
self.config_entry_id = config_entry_id
|
||||||
self.ring = ring
|
self.ring = ring
|
||||||
self.update_method = update_method
|
self.update_method = update_method
|
||||||
@ -215,6 +225,11 @@ class GlobalDataUpdater:
|
|||||||
_LOGGER.error("Ring access token is no longer valid. Set up Ring again")
|
_LOGGER.error("Ring access token is no longer valid. Set up Ring again")
|
||||||
await self.hass.config_entries.async_unload(self.config_entry_id)
|
await self.hass.config_entries.async_unload(self.config_entry_id)
|
||||||
return
|
return
|
||||||
|
except requests.Timeout:
|
||||||
|
_LOGGER.warning(
|
||||||
|
"Time out fetching Ring %s data", self.data_type,
|
||||||
|
)
|
||||||
|
return
|
||||||
|
|
||||||
for update_callback in self.listeners:
|
for update_callback in self.listeners:
|
||||||
update_callback()
|
update_callback()
|
||||||
@ -226,12 +241,14 @@ class DeviceDataUpdater:
|
|||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
hass: HomeAssistant,
|
hass: HomeAssistant,
|
||||||
|
data_type: str,
|
||||||
config_entry_id: str,
|
config_entry_id: str,
|
||||||
ring: Ring,
|
ring: Ring,
|
||||||
update_method: str,
|
update_method: str,
|
||||||
update_interval: timedelta,
|
update_interval: timedelta,
|
||||||
):
|
):
|
||||||
"""Initialize device data updater."""
|
"""Initialize device data updater."""
|
||||||
|
self.data_type = data_type
|
||||||
self.hass = hass
|
self.hass = hass
|
||||||
self.config_entry_id = config_entry_id
|
self.config_entry_id = config_entry_id
|
||||||
self.ring = ring
|
self.ring = ring
|
||||||
@ -282,7 +299,7 @@ class DeviceDataUpdater:
|
|||||||
|
|
||||||
def refresh_all(self, _=None):
|
def refresh_all(self, _=None):
|
||||||
"""Refresh all registered devices."""
|
"""Refresh all registered devices."""
|
||||||
for info in self.devices.values():
|
for device_id, info in self.devices.items():
|
||||||
try:
|
try:
|
||||||
data = info["data"] = self.update_method(info["device"])
|
data = info["data"] = self.update_method(info["device"])
|
||||||
except AccessDeniedError:
|
except AccessDeniedError:
|
||||||
@ -291,6 +308,13 @@ class DeviceDataUpdater:
|
|||||||
self.hass.config_entries.async_unload(self.config_entry_id)
|
self.hass.config_entries.async_unload(self.config_entry_id)
|
||||||
)
|
)
|
||||||
return
|
return
|
||||||
|
except requests.Timeout:
|
||||||
|
_LOGGER.warning(
|
||||||
|
"Time out fetching Ring %s data for device %s",
|
||||||
|
self.data_type,
|
||||||
|
device_id,
|
||||||
|
)
|
||||||
|
continue
|
||||||
|
|
||||||
for update_callback in info["update_callbacks"]:
|
for update_callback in info["update_callbacks"]:
|
||||||
self.hass.loop.call_soon_threadsafe(update_callback, data)
|
self.hass.loop.call_soon_threadsafe(update_callback, data)
|
||||||
|
@ -51,8 +51,7 @@ class RingCam(RingEntityMixin, Camera):
|
|||||||
self._last_event = None
|
self._last_event = None
|
||||||
self._last_video_id = None
|
self._last_video_id = None
|
||||||
self._video_url = None
|
self._video_url = None
|
||||||
self._utcnow = dt_util.utcnow()
|
self._expires_at = dt_util.utcnow() - FORCE_REFRESH_INTERVAL
|
||||||
self._expires_at = self._utcnow - FORCE_REFRESH_INTERVAL
|
|
||||||
|
|
||||||
async def async_added_to_hass(self):
|
async def async_added_to_hass(self):
|
||||||
"""Register callbacks."""
|
"""Register callbacks."""
|
||||||
@ -80,7 +79,7 @@ class RingCam(RingEntityMixin, Camera):
|
|||||||
self._last_event = None
|
self._last_event = None
|
||||||
self._last_video_id = None
|
self._last_video_id = None
|
||||||
self._video_url = None
|
self._video_url = None
|
||||||
self._expires_at = self._utcnow
|
self._expires_at = dt_util.utcnow()
|
||||||
self.async_write_ha_state()
|
self.async_write_ha_state()
|
||||||
|
|
||||||
@property
|
@property
|
||||||
@ -141,10 +140,8 @@ class RingCam(RingEntityMixin, Camera):
|
|||||||
if self._last_event["recording"]["status"] != "ready":
|
if self._last_event["recording"]["status"] != "ready":
|
||||||
return
|
return
|
||||||
|
|
||||||
if (
|
utcnow = dt_util.utcnow()
|
||||||
self._last_video_id == self._last_event["id"]
|
if self._last_video_id == self._last_event["id"] and utcnow <= self._expires_at:
|
||||||
and self._utcnow <= self._expires_at
|
|
||||||
):
|
|
||||||
return
|
return
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@ -160,4 +157,4 @@ class RingCam(RingEntityMixin, Camera):
|
|||||||
if video_url:
|
if video_url:
|
||||||
self._last_video_id = self._last_event["id"]
|
self._last_video_id = self._last_event["id"]
|
||||||
self._video_url = video_url
|
self._video_url = video_url
|
||||||
self._expires_at = FORCE_REFRESH_INTERVAL + self._utcnow
|
self._expires_at = FORCE_REFRESH_INTERVAL + utcnow
|
||||||
|
@ -2,6 +2,8 @@
|
|||||||
from datetime import timedelta
|
from datetime import timedelta
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
|
import requests
|
||||||
|
|
||||||
from homeassistant.components.light import Light
|
from homeassistant.components.light import Light
|
||||||
from homeassistant.core import callback
|
from homeassistant.core import callback
|
||||||
import homeassistant.util.dt as dt_util
|
import homeassistant.util.dt as dt_util
|
||||||
@ -72,7 +74,12 @@ class RingLight(RingEntityMixin, Light):
|
|||||||
|
|
||||||
def _set_light(self, new_state):
|
def _set_light(self, new_state):
|
||||||
"""Update light state, and causes Home Assistant to correctly update."""
|
"""Update light state, and causes Home Assistant to correctly update."""
|
||||||
self._device.lights = new_state
|
try:
|
||||||
|
self._device.lights = new_state
|
||||||
|
except requests.Timeout:
|
||||||
|
_LOGGER.error("Time out setting %s light to %s", self.entity_id, new_state)
|
||||||
|
return
|
||||||
|
|
||||||
self._light_on = new_state == ON_STATE
|
self._light_on = new_state == ON_STATE
|
||||||
self._no_updates_until = dt_util.utcnow() + SKIP_UPDATES_DELAY
|
self._no_updates_until = dt_util.utcnow() + SKIP_UPDATES_DELAY
|
||||||
self.async_schedule_update_ha_state()
|
self.async_schedule_update_ha_state()
|
||||||
|
@ -15,9 +15,6 @@ async def async_setup_entry(hass, config_entry, async_add_entities):
|
|||||||
"""Set up a sensor for a Ring device."""
|
"""Set up a sensor for a Ring device."""
|
||||||
devices = hass.data[DOMAIN][config_entry.entry_id]["devices"]
|
devices = hass.data[DOMAIN][config_entry.entry_id]["devices"]
|
||||||
|
|
||||||
# Makes a ton of requests. We will make this a config entry option in the future
|
|
||||||
wifi_enabled = False
|
|
||||||
|
|
||||||
sensors = []
|
sensors = []
|
||||||
|
|
||||||
for device_type in ("chimes", "doorbots", "authorized_doorbots", "stickup_cams"):
|
for device_type in ("chimes", "doorbots", "authorized_doorbots", "stickup_cams"):
|
||||||
@ -25,9 +22,6 @@ async def async_setup_entry(hass, config_entry, async_add_entities):
|
|||||||
if device_type not in SENSOR_TYPES[sensor_type][1]:
|
if device_type not in SENSOR_TYPES[sensor_type][1]:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
if not wifi_enabled and sensor_type.startswith("wifi_"):
|
|
||||||
continue
|
|
||||||
|
|
||||||
for device in devices[device_type]:
|
for device in devices[device_type]:
|
||||||
if device_type == "battery" and device.battery_life is None:
|
if device_type == "battery" and device.battery_life is None:
|
||||||
continue
|
continue
|
||||||
@ -124,6 +118,12 @@ class HealthDataRingSensor(RingSensor):
|
|||||||
"""Call update method."""
|
"""Call update method."""
|
||||||
self.async_write_ha_state()
|
self.async_write_ha_state()
|
||||||
|
|
||||||
|
@property
|
||||||
|
def entity_registry_enabled_default(self) -> bool:
|
||||||
|
"""Return if the entity should be enabled when first added to the entity registry."""
|
||||||
|
# These sensors are data hungry and not useful. Disable by default.
|
||||||
|
return False
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def state(self):
|
def state(self):
|
||||||
"""Return the state of the sensor."""
|
"""Return the state of the sensor."""
|
||||||
|
@ -2,6 +2,8 @@
|
|||||||
from datetime import timedelta
|
from datetime import timedelta
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
|
import requests
|
||||||
|
|
||||||
from homeassistant.components.switch import SwitchDevice
|
from homeassistant.components.switch import SwitchDevice
|
||||||
from homeassistant.core import callback
|
from homeassistant.core import callback
|
||||||
import homeassistant.util.dt as dt_util
|
import homeassistant.util.dt as dt_util
|
||||||
@ -74,7 +76,12 @@ class SirenSwitch(BaseRingSwitch):
|
|||||||
|
|
||||||
def _set_switch(self, new_state):
|
def _set_switch(self, new_state):
|
||||||
"""Update switch state, and causes Home Assistant to correctly update."""
|
"""Update switch state, and causes Home Assistant to correctly update."""
|
||||||
self._device.siren = new_state
|
try:
|
||||||
|
self._device.siren = new_state
|
||||||
|
except requests.Timeout:
|
||||||
|
_LOGGER.error("Time out setting %s siren to %s", self.entity_id, new_state)
|
||||||
|
return
|
||||||
|
|
||||||
self._siren_on = new_state > 0
|
self._siren_on = new_state > 0
|
||||||
self._no_updates_until = dt_util.utcnow() + SKIP_UPDATES_DELAY
|
self._no_updates_until = dt_util.utcnow() + SKIP_UPDATES_DELAY
|
||||||
self.schedule_update_ha_state()
|
self.schedule_update_ha_state()
|
||||||
|
@ -146,7 +146,7 @@ class WaterHeaterDevice(Entity):
|
|||||||
@property
|
@property
|
||||||
def capability_attributes(self):
|
def capability_attributes(self):
|
||||||
"""Return capabilitiy attributes."""
|
"""Return capabilitiy attributes."""
|
||||||
supported_features = self.supported_features
|
supported_features = self.supported_features or 0
|
||||||
|
|
||||||
data = {
|
data = {
|
||||||
ATTR_MIN_TEMP: show_temp(
|
ATTR_MIN_TEMP: show_temp(
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
"""Constants used by Home Assistant components."""
|
"""Constants used by Home Assistant components."""
|
||||||
MAJOR_VERSION = 0
|
MAJOR_VERSION = 0
|
||||||
MINOR_VERSION = 104
|
MINOR_VERSION = 104
|
||||||
PATCH_VERSION = "2"
|
PATCH_VERSION = "3"
|
||||||
__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, 7, 0)
|
REQUIRED_PYTHON_VER = (3, 7, 0)
|
||||||
|
@ -477,7 +477,7 @@ eliqonline==1.2.2
|
|||||||
elkm1-lib==0.7.15
|
elkm1-lib==0.7.15
|
||||||
|
|
||||||
# homeassistant.components.emulated_roku
|
# homeassistant.components.emulated_roku
|
||||||
emulated_roku==0.1.9
|
emulated_roku==0.2.0
|
||||||
|
|
||||||
# homeassistant.components.enocean
|
# homeassistant.components.enocean
|
||||||
enocean==0.50
|
enocean==0.50
|
||||||
|
@ -171,7 +171,7 @@ eebrightbox==0.0.4
|
|||||||
elgato==0.2.0
|
elgato==0.2.0
|
||||||
|
|
||||||
# homeassistant.components.emulated_roku
|
# homeassistant.components.emulated_roku
|
||||||
emulated_roku==0.1.9
|
emulated_roku==0.2.0
|
||||||
|
|
||||||
# homeassistant.components.season
|
# homeassistant.components.season
|
||||||
ephem==3.7.7.0
|
ephem==3.7.7.0
|
||||||
|
Loading…
x
Reference in New Issue
Block a user