mirror of
https://github.com/home-assistant/core.git
synced 2025-07-19 19:27:45 +00:00
Merge pull request #54676 from home-assistant/rc
This commit is contained in:
commit
e0873493e2
@ -672,6 +672,7 @@ omit =
|
|||||||
homeassistant/components/mystrom/light.py
|
homeassistant/components/mystrom/light.py
|
||||||
homeassistant/components/mystrom/switch.py
|
homeassistant/components/mystrom/switch.py
|
||||||
homeassistant/components/myq/__init__.py
|
homeassistant/components/myq/__init__.py
|
||||||
|
homeassistant/components/myq/cover.py
|
||||||
homeassistant/components/nad/media_player.py
|
homeassistant/components/nad/media_player.py
|
||||||
homeassistant/components/nanoleaf/light.py
|
homeassistant/components/nanoleaf/light.py
|
||||||
homeassistant/components/neato/__init__.py
|
homeassistant/components/neato/__init__.py
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
"config_flow": true,
|
"config_flow": true,
|
||||||
"documentation": "https://www.home-assistant.io/integrations/adax",
|
"documentation": "https://www.home-assistant.io/integrations/adax",
|
||||||
"requirements": [
|
"requirements": [
|
||||||
"adax==0.0.1"
|
"adax==0.1.1"
|
||||||
],
|
],
|
||||||
"codeowners": [
|
"codeowners": [
|
||||||
"@danielhiversen"
|
"@danielhiversen"
|
||||||
|
@ -154,8 +154,6 @@ class AmbiclimateEntity(ClimateEntity):
|
|||||||
"name": self.name,
|
"name": self.name,
|
||||||
"manufacturer": "Ambiclimate",
|
"manufacturer": "Ambiclimate",
|
||||||
}
|
}
|
||||||
self._attr_min_temp = heater.get_min_temp()
|
|
||||||
self._attr_max_temp = heater.get_max_temp()
|
|
||||||
|
|
||||||
async def async_set_temperature(self, **kwargs: Any) -> None:
|
async def async_set_temperature(self, **kwargs: Any) -> None:
|
||||||
"""Set new target temperature."""
|
"""Set new target temperature."""
|
||||||
@ -184,6 +182,8 @@ class AmbiclimateEntity(ClimateEntity):
|
|||||||
await self._store.async_save(token_info)
|
await self._store.async_save(token_info)
|
||||||
|
|
||||||
data = await self._heater.update_device()
|
data = await self._heater.update_device()
|
||||||
|
self._attr_min_temp = self._heater.get_min_temp()
|
||||||
|
self._attr_max_temp = self._heater.get_max_temp()
|
||||||
self._attr_target_temperature = data.get("target_temperature")
|
self._attr_target_temperature = data.get("target_temperature")
|
||||||
self._attr_current_temperature = data.get("temperature")
|
self._attr_current_temperature = data.get("temperature")
|
||||||
self._attr_current_humidity = data.get("humidity")
|
self._attr_current_humidity = data.get("humidity")
|
||||||
|
@ -335,11 +335,6 @@ class BMWConnectedDriveBaseEntity(Entity):
|
|||||||
"manufacturer": vehicle.attributes.get("brand"),
|
"manufacturer": vehicle.attributes.get("brand"),
|
||||||
}
|
}
|
||||||
|
|
||||||
@property
|
|
||||||
def extra_state_attributes(self):
|
|
||||||
"""Return the state attributes of the sensor."""
|
|
||||||
return self._attrs
|
|
||||||
|
|
||||||
def update_callback(self):
|
def update_callback(self):
|
||||||
"""Schedule a state update."""
|
"""Schedule a state update."""
|
||||||
self.schedule_update_ha_state(True)
|
self.schedule_update_ha_state(True)
|
||||||
|
@ -85,54 +85,38 @@ class BMWConnectedDriveSensor(BMWConnectedDriveBaseEntity, BinarySensorEntity):
|
|||||||
def update(self):
|
def update(self):
|
||||||
"""Read new state data from the library."""
|
"""Read new state data from the library."""
|
||||||
vehicle_state = self._vehicle.state
|
vehicle_state = self._vehicle.state
|
||||||
|
result = self._attrs.copy()
|
||||||
|
|
||||||
# device class opening: On means open, Off means closed
|
# device class opening: On means open, Off means closed
|
||||||
if self._attribute == "lids":
|
if self._attribute == "lids":
|
||||||
_LOGGER.debug("Status of lid: %s", vehicle_state.all_lids_closed)
|
_LOGGER.debug("Status of lid: %s", vehicle_state.all_lids_closed)
|
||||||
self._attr_state = not vehicle_state.all_lids_closed
|
self._attr_is_on = not vehicle_state.all_lids_closed
|
||||||
if self._attribute == "windows":
|
|
||||||
self._attr_state = not vehicle_state.all_windows_closed
|
|
||||||
# device class lock: On means unlocked, Off means locked
|
|
||||||
if self._attribute == "door_lock_state":
|
|
||||||
# Possible values: LOCKED, SECURED, SELECTIVE_LOCKED, UNLOCKED
|
|
||||||
self._attr_state = vehicle_state.door_lock_state not in [
|
|
||||||
LockState.LOCKED,
|
|
||||||
LockState.SECURED,
|
|
||||||
]
|
|
||||||
# device class light: On means light detected, Off means no light
|
|
||||||
if self._attribute == "lights_parking":
|
|
||||||
self._attr_state = vehicle_state.are_parking_lights_on
|
|
||||||
# device class problem: On means problem detected, Off means no problem
|
|
||||||
if self._attribute == "condition_based_services":
|
|
||||||
self._attr_state = not vehicle_state.are_all_cbs_ok
|
|
||||||
if self._attribute == "check_control_messages":
|
|
||||||
self._attr_state = vehicle_state.has_check_control_messages
|
|
||||||
# device class power: On means power detected, Off means no power
|
|
||||||
if self._attribute == "charging_status":
|
|
||||||
self._attr_state = vehicle_state.charging_status in [ChargingState.CHARGING]
|
|
||||||
# device class plug: On means device is plugged in,
|
|
||||||
# Off means device is unplugged
|
|
||||||
if self._attribute == "connection_status":
|
|
||||||
self._attr_state = vehicle_state.connection_status == "CONNECTED"
|
|
||||||
|
|
||||||
vehicle_state = self._vehicle.state
|
|
||||||
result = self._attrs.copy()
|
|
||||||
|
|
||||||
if self._attribute == "lids":
|
|
||||||
for lid in vehicle_state.lids:
|
for lid in vehicle_state.lids:
|
||||||
result[lid.name] = lid.state.value
|
result[lid.name] = lid.state.value
|
||||||
elif self._attribute == "windows":
|
elif self._attribute == "windows":
|
||||||
|
self._attr_is_on = not vehicle_state.all_windows_closed
|
||||||
for window in vehicle_state.windows:
|
for window in vehicle_state.windows:
|
||||||
result[window.name] = window.state.value
|
result[window.name] = window.state.value
|
||||||
|
# device class lock: On means unlocked, Off means locked
|
||||||
elif self._attribute == "door_lock_state":
|
elif self._attribute == "door_lock_state":
|
||||||
|
# Possible values: LOCKED, SECURED, SELECTIVE_LOCKED, UNLOCKED
|
||||||
|
self._attr_is_on = vehicle_state.door_lock_state not in [
|
||||||
|
LockState.LOCKED,
|
||||||
|
LockState.SECURED,
|
||||||
|
]
|
||||||
result["door_lock_state"] = vehicle_state.door_lock_state.value
|
result["door_lock_state"] = vehicle_state.door_lock_state.value
|
||||||
result["last_update_reason"] = vehicle_state.last_update_reason
|
result["last_update_reason"] = vehicle_state.last_update_reason
|
||||||
|
# device class light: On means light detected, Off means no light
|
||||||
elif self._attribute == "lights_parking":
|
elif self._attribute == "lights_parking":
|
||||||
|
self._attr_is_on = vehicle_state.are_parking_lights_on
|
||||||
result["lights_parking"] = vehicle_state.parking_lights.value
|
result["lights_parking"] = vehicle_state.parking_lights.value
|
||||||
|
# device class problem: On means problem detected, Off means no problem
|
||||||
elif self._attribute == "condition_based_services":
|
elif self._attribute == "condition_based_services":
|
||||||
|
self._attr_is_on = not vehicle_state.are_all_cbs_ok
|
||||||
for report in vehicle_state.condition_based_services:
|
for report in vehicle_state.condition_based_services:
|
||||||
result.update(self._format_cbs_report(report))
|
result.update(self._format_cbs_report(report))
|
||||||
elif self._attribute == "check_control_messages":
|
elif self._attribute == "check_control_messages":
|
||||||
|
self._attr_is_on = vehicle_state.has_check_control_messages
|
||||||
check_control_messages = vehicle_state.check_control_messages
|
check_control_messages = vehicle_state.check_control_messages
|
||||||
has_check_control_messages = vehicle_state.has_check_control_messages
|
has_check_control_messages = vehicle_state.has_check_control_messages
|
||||||
if has_check_control_messages:
|
if has_check_control_messages:
|
||||||
@ -142,13 +126,18 @@ class BMWConnectedDriveSensor(BMWConnectedDriveBaseEntity, BinarySensorEntity):
|
|||||||
result["check_control_messages"] = cbs_list
|
result["check_control_messages"] = cbs_list
|
||||||
else:
|
else:
|
||||||
result["check_control_messages"] = "OK"
|
result["check_control_messages"] = "OK"
|
||||||
|
# device class power: On means power detected, Off means no power
|
||||||
elif self._attribute == "charging_status":
|
elif self._attribute == "charging_status":
|
||||||
|
self._attr_is_on = vehicle_state.charging_status in [ChargingState.CHARGING]
|
||||||
result["charging_status"] = vehicle_state.charging_status.value
|
result["charging_status"] = vehicle_state.charging_status.value
|
||||||
result["last_charging_end_result"] = vehicle_state.last_charging_end_result
|
result["last_charging_end_result"] = vehicle_state.last_charging_end_result
|
||||||
|
# device class plug: On means device is plugged in,
|
||||||
|
# Off means device is unplugged
|
||||||
elif self._attribute == "connection_status":
|
elif self._attribute == "connection_status":
|
||||||
|
self._attr_is_on = vehicle_state.connection_status == "CONNECTED"
|
||||||
result["connection_status"] = vehicle_state.connection_status
|
result["connection_status"] = vehicle_state.connection_status
|
||||||
|
|
||||||
self._attr_extra_state_attributes = sorted(result.items())
|
self._attr_extra_state_attributes = result
|
||||||
|
|
||||||
def _format_cbs_report(self, report):
|
def _format_cbs_report(self, report):
|
||||||
result = {}
|
result = {}
|
||||||
|
@ -59,6 +59,7 @@ class BMWDeviceTracker(BMWConnectedDriveBaseEntity, TrackerEntity):
|
|||||||
|
|
||||||
def update(self):
|
def update(self):
|
||||||
"""Update state of the decvice tracker."""
|
"""Update state of the decvice tracker."""
|
||||||
|
self._attr_extra_state_attributes = self._attrs
|
||||||
self._location = (
|
self._location = (
|
||||||
self._vehicle.state.gps_position
|
self._vehicle.state.gps_position
|
||||||
if self._vehicle.state.is_vehicle_tracking_enabled
|
if self._vehicle.state.is_vehicle_tracking_enabled
|
||||||
|
@ -105,8 +105,8 @@ class EsphomeLight(EsphomeEntity[LightInfo, LightState], LightEntity):
|
|||||||
color_bri = max(rgb)
|
color_bri = max(rgb)
|
||||||
# normalize rgb
|
# normalize rgb
|
||||||
data["rgb"] = tuple(x / (color_bri or 1) for x in rgb)
|
data["rgb"] = tuple(x / (color_bri or 1) for x in rgb)
|
||||||
|
data["color_brightness"] = color_bri
|
||||||
if self._supports_color_mode:
|
if self._supports_color_mode:
|
||||||
data["color_brightness"] = color_bri
|
|
||||||
data["color_mode"] = LightColorMode.RGB
|
data["color_mode"] = LightColorMode.RGB
|
||||||
|
|
||||||
if (rgbw_ha := kwargs.get(ATTR_RGBW_COLOR)) is not None:
|
if (rgbw_ha := kwargs.get(ATTR_RGBW_COLOR)) is not None:
|
||||||
@ -116,8 +116,8 @@ class EsphomeLight(EsphomeEntity[LightInfo, LightState], LightEntity):
|
|||||||
# normalize rgb
|
# normalize rgb
|
||||||
data["rgb"] = tuple(x / (color_bri or 1) for x in rgb)
|
data["rgb"] = tuple(x / (color_bri or 1) for x in rgb)
|
||||||
data["white"] = w
|
data["white"] = w
|
||||||
|
data["color_brightness"] = color_bri
|
||||||
if self._supports_color_mode:
|
if self._supports_color_mode:
|
||||||
data["color_brightness"] = color_bri
|
|
||||||
data["color_mode"] = LightColorMode.RGB_WHITE
|
data["color_mode"] = LightColorMode.RGB_WHITE
|
||||||
|
|
||||||
if (rgbww_ha := kwargs.get(ATTR_RGBWW_COLOR)) is not None:
|
if (rgbww_ha := kwargs.get(ATTR_RGBWW_COLOR)) is not None:
|
||||||
@ -144,8 +144,8 @@ class EsphomeLight(EsphomeEntity[LightInfo, LightState], LightEntity):
|
|||||||
data["color_temperature"] = min_ct + ct_ratio * (max_ct - min_ct)
|
data["color_temperature"] = min_ct + ct_ratio * (max_ct - min_ct)
|
||||||
target_mode = LightColorMode.RGB_COLOR_TEMPERATURE
|
target_mode = LightColorMode.RGB_COLOR_TEMPERATURE
|
||||||
|
|
||||||
|
data["color_brightness"] = color_bri
|
||||||
if self._supports_color_mode:
|
if self._supports_color_mode:
|
||||||
data["color_brightness"] = color_bri
|
|
||||||
data["color_mode"] = target_mode
|
data["color_mode"] = target_mode
|
||||||
|
|
||||||
if (flash := kwargs.get(ATTR_FLASH)) is not None:
|
if (flash := kwargs.get(ATTR_FLASH)) is not None:
|
||||||
@ -230,7 +230,7 @@ class EsphomeLight(EsphomeEntity[LightInfo, LightState], LightEntity):
|
|||||||
# Try to reverse white + color temp to cwww
|
# Try to reverse white + color temp to cwww
|
||||||
min_ct = self._static_info.min_mireds
|
min_ct = self._static_info.min_mireds
|
||||||
max_ct = self._static_info.max_mireds
|
max_ct = self._static_info.max_mireds
|
||||||
color_temp = self._state.color_temperature
|
color_temp = min(max(self._state.color_temperature, min_ct), max_ct)
|
||||||
white = self._state.white
|
white = self._state.white
|
||||||
|
|
||||||
ww_frac = (color_temp - min_ct) / (max_ct - min_ct)
|
ww_frac = (color_temp - min_ct) / (max_ct - min_ct)
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
"""Class to hold all light accessories."""
|
"""Class to hold all light accessories."""
|
||||||
import logging
|
import logging
|
||||||
|
import math
|
||||||
|
|
||||||
from pyhap.const import CATEGORY_LIGHTBULB
|
from pyhap.const import CATEGORY_LIGHTBULB
|
||||||
|
|
||||||
@ -115,8 +116,8 @@ class Light(HomeAccessory):
|
|||||||
)
|
)
|
||||||
|
|
||||||
if self.is_color_temp_supported:
|
if self.is_color_temp_supported:
|
||||||
min_mireds = attributes.get(ATTR_MIN_MIREDS, 153)
|
min_mireds = math.floor(attributes.get(ATTR_MIN_MIREDS, 153))
|
||||||
max_mireds = attributes.get(ATTR_MAX_MIREDS, 500)
|
max_mireds = math.ceil(attributes.get(ATTR_MAX_MIREDS, 500))
|
||||||
serv_light = serv_light_secondary or serv_light_primary
|
serv_light = serv_light_secondary or serv_light_primary
|
||||||
self.char_color_temperature = serv_light.configure_char(
|
self.char_color_temperature = serv_light.configure_char(
|
||||||
CHAR_COLOR_TEMPERATURE,
|
CHAR_COLOR_TEMPERATURE,
|
||||||
|
@ -65,6 +65,11 @@ def async_setup_forwarded(
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
from hass_nabucasa import remote # pylint: disable=import-outside-toplevel
|
from hass_nabucasa import remote # pylint: disable=import-outside-toplevel
|
||||||
|
|
||||||
|
# venv users might have already loaded it before it got upgraded so guard for this
|
||||||
|
# This can only happen when people upgrade from before 2021.8.5.
|
||||||
|
if not hasattr(remote, "is_cloud_request"):
|
||||||
|
remote = None
|
||||||
except ImportError:
|
except ImportError:
|
||||||
remote = None
|
remote = None
|
||||||
|
|
||||||
|
@ -665,9 +665,9 @@ class HuaweiLteBaseEntity(Entity):
|
|||||||
async_dispatcher_connect(self.hass, UPDATE_SIGNAL, self._async_maybe_update)
|
async_dispatcher_connect(self.hass, UPDATE_SIGNAL, self._async_maybe_update)
|
||||||
)
|
)
|
||||||
|
|
||||||
async def _async_maybe_update(self, url: str) -> None:
|
async def _async_maybe_update(self, config_entry_unique_id: str) -> None:
|
||||||
"""Update state if the update signal comes from our router."""
|
"""Update state if the update signal comes from our router."""
|
||||||
if url == self.router.url:
|
if config_entry_unique_id == self.router.config_entry.unique_id:
|
||||||
self.async_schedule_update_ha_state(True)
|
self.async_schedule_update_ha_state(True)
|
||||||
|
|
||||||
async def async_will_remove_from_hass(self) -> None:
|
async def async_will_remove_from_hass(self) -> None:
|
||||||
|
@ -189,9 +189,9 @@ class BaseSwitch(BasePlatform, RestoreEntity):
|
|||||||
self._verify_address = config[CONF_VERIFY].get(
|
self._verify_address = config[CONF_VERIFY].get(
|
||||||
CONF_ADDRESS, config[CONF_ADDRESS]
|
CONF_ADDRESS, config[CONF_ADDRESS]
|
||||||
)
|
)
|
||||||
self._verify_type = config[CONF_VERIFY].get(
|
self._verify_type = convert[
|
||||||
CONF_INPUT_TYPE, convert[config[CONF_WRITE_TYPE]][0]
|
config[CONF_VERIFY].get(CONF_INPUT_TYPE, config[CONF_WRITE_TYPE])
|
||||||
)
|
][0]
|
||||||
self._state_on = config[CONF_VERIFY].get(CONF_STATE_ON, self.command_on)
|
self._state_on = config[CONF_VERIFY].get(CONF_STATE_ON, self.command_on)
|
||||||
self._state_off = config[CONF_VERIFY].get(CONF_STATE_OFF, self._command_off)
|
self._state_off = config[CONF_VERIFY].get(CONF_STATE_OFF, self._command_off)
|
||||||
else:
|
else:
|
||||||
|
@ -31,7 +31,7 @@ class ConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
|
|||||||
"""Validate the user input allows us to connect."""
|
"""Validate the user input allows us to connect."""
|
||||||
websession = aiohttp_client.async_get_clientsession(self.hass)
|
websession = aiohttp_client.async_get_clientsession(self.hass)
|
||||||
try:
|
try:
|
||||||
await pymyq.login(username, password, websession)
|
await pymyq.login(username, password, websession, True)
|
||||||
except InvalidCredentialsError:
|
except InvalidCredentialsError:
|
||||||
return {CONF_PASSWORD: "invalid_auth"}
|
return {CONF_PASSWORD: "invalid_auth"}
|
||||||
except MyQError:
|
except MyQError:
|
||||||
|
@ -115,7 +115,9 @@ class MyQDevice(CoordinatorEntity, CoverEntity):
|
|||||||
# Write closing state to HASS
|
# Write closing state to HASS
|
||||||
self.async_write_ha_state()
|
self.async_write_ha_state()
|
||||||
|
|
||||||
if not await wait_task:
|
result = wait_task if isinstance(wait_task, bool) else await wait_task
|
||||||
|
|
||||||
|
if not result:
|
||||||
_LOGGER.error("Closing of cover %s failed", self._device.name)
|
_LOGGER.error("Closing of cover %s failed", self._device.name)
|
||||||
|
|
||||||
# Write final state to HASS
|
# Write final state to HASS
|
||||||
@ -137,7 +139,9 @@ class MyQDevice(CoordinatorEntity, CoverEntity):
|
|||||||
# Write opening state to HASS
|
# Write opening state to HASS
|
||||||
self.async_write_ha_state()
|
self.async_write_ha_state()
|
||||||
|
|
||||||
if not await wait_task:
|
result = wait_task if isinstance(wait_task, bool) else await wait_task
|
||||||
|
|
||||||
|
if not result:
|
||||||
_LOGGER.error("Opening of cover %s failed", self._device.name)
|
_LOGGER.error("Opening of cover %s failed", self._device.name)
|
||||||
|
|
||||||
# Write final state to HASS
|
# Write final state to HASS
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
"domain": "myq",
|
"domain": "myq",
|
||||||
"name": "MyQ",
|
"name": "MyQ",
|
||||||
"documentation": "https://www.home-assistant.io/integrations/myq",
|
"documentation": "https://www.home-assistant.io/integrations/myq",
|
||||||
"requirements": ["pymyq==3.0.4"],
|
"requirements": ["pymyq==3.1.2"],
|
||||||
"codeowners": ["@bdraco"],
|
"codeowners": ["@bdraco"],
|
||||||
"config_flow": true,
|
"config_flow": true,
|
||||||
"homekit": {
|
"homekit": {
|
||||||
|
@ -1,6 +1,4 @@
|
|||||||
"""The NFAndroidTV integration."""
|
"""The NFAndroidTV integration."""
|
||||||
import logging
|
|
||||||
|
|
||||||
from notifications_android_tv.notifications import ConnectError, Notifications
|
from notifications_android_tv.notifications import ConnectError, Notifications
|
||||||
|
|
||||||
from homeassistant.components.notify import DOMAIN as NOTIFY
|
from homeassistant.components.notify import DOMAIN as NOTIFY
|
||||||
@ -12,8 +10,6 @@ from homeassistant.helpers import discovery
|
|||||||
|
|
||||||
from .const import DOMAIN
|
from .const import DOMAIN
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
|
||||||
|
|
||||||
PLATFORMS = [NOTIFY]
|
PLATFORMS = [NOTIFY]
|
||||||
|
|
||||||
|
|
||||||
@ -41,8 +37,7 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
|||||||
try:
|
try:
|
||||||
await hass.async_add_executor_job(Notifications, host)
|
await hass.async_add_executor_job(Notifications, host)
|
||||||
except ConnectError as ex:
|
except ConnectError as ex:
|
||||||
_LOGGER.warning("Failed to connect: %s", ex)
|
raise ConfigEntryNotReady("Failed to connect") from ex
|
||||||
raise ConfigEntryNotReady from ex
|
|
||||||
|
|
||||||
hass.data.setdefault(DOMAIN, {})
|
hass.data.setdefault(DOMAIN, {})
|
||||||
hass.data[DOMAIN][entry.entry_id] = {
|
hass.data[DOMAIN][entry.entry_id] = {
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
"domain": "nfandroidtv",
|
"domain": "nfandroidtv",
|
||||||
"name": "Notifications for Android TV / Fire TV",
|
"name": "Notifications for Android TV / Fire TV",
|
||||||
"documentation": "https://www.home-assistant.io/integrations/nfandroidtv",
|
"documentation": "https://www.home-assistant.io/integrations/nfandroidtv",
|
||||||
"requirements": ["notifications-android-tv==0.1.2"],
|
"requirements": ["notifications-android-tv==0.1.3"],
|
||||||
"codeowners": ["@tkdrob"],
|
"codeowners": ["@tkdrob"],
|
||||||
"config_flow": true,
|
"config_flow": true,
|
||||||
"iot_class": "local_push"
|
"iot_class": "local_push"
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
"domain": "nissan_leaf",
|
"domain": "nissan_leaf",
|
||||||
"name": "Nissan Leaf",
|
"name": "Nissan Leaf",
|
||||||
"documentation": "https://www.home-assistant.io/integrations/nissan_leaf",
|
"documentation": "https://www.home-assistant.io/integrations/nissan_leaf",
|
||||||
"requirements": ["pycarwings2==2.10"],
|
"requirements": ["pycarwings2==2.11"],
|
||||||
"codeowners": ["@filcole"],
|
"codeowners": ["@filcole"],
|
||||||
"iot_class": "cloud_polling"
|
"iot_class": "cloud_polling"
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
"domain": "qnap",
|
"domain": "qnap",
|
||||||
"name": "QNAP",
|
"name": "QNAP",
|
||||||
"documentation": "https://www.home-assistant.io/integrations/qnap",
|
"documentation": "https://www.home-assistant.io/integrations/qnap",
|
||||||
"requirements": ["qnapstats==0.3.1"],
|
"requirements": ["qnapstats==0.4.0"],
|
||||||
"codeowners": ["@colinodell"],
|
"codeowners": ["@colinodell"],
|
||||||
"iot_class": "local_polling"
|
"iot_class": "local_polling"
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
"domain": "synology_dsm",
|
"domain": "synology_dsm",
|
||||||
"name": "Synology DSM",
|
"name": "Synology DSM",
|
||||||
"documentation": "https://www.home-assistant.io/integrations/synology_dsm",
|
"documentation": "https://www.home-assistant.io/integrations/synology_dsm",
|
||||||
"requirements": ["py-synologydsm-api==1.0.3"],
|
"requirements": ["py-synologydsm-api==1.0.4"],
|
||||||
"codeowners": ["@hacf-fr", "@Quentame", "@mib1185"],
|
"codeowners": ["@hacf-fr", "@Quentame", "@mib1185"],
|
||||||
"config_flow": true,
|
"config_flow": true,
|
||||||
"ssdp": [
|
"ssdp": [
|
||||||
|
@ -177,6 +177,15 @@ async def async_setup_entry(hass, config_entry):
|
|||||||
await async_client.aclose()
|
await async_client.aclose()
|
||||||
if ex.code == HTTP_UNAUTHORIZED:
|
if ex.code == HTTP_UNAUTHORIZED:
|
||||||
raise ConfigEntryAuthFailed from ex
|
raise ConfigEntryAuthFailed from ex
|
||||||
|
if ex.message in [
|
||||||
|
"VEHICLE_UNAVAILABLE",
|
||||||
|
"TOO_MANY_REQUESTS",
|
||||||
|
"SERVICE_MAINTENANCE",
|
||||||
|
"UPSTREAM_TIMEOUT",
|
||||||
|
]:
|
||||||
|
raise ConfigEntryNotReady(
|
||||||
|
f"Temporarily unable to communicate with Tesla API: {ex.message}"
|
||||||
|
) from ex
|
||||||
_LOGGER.error("Unable to communicate with Tesla API: %s", ex.message)
|
_LOGGER.error("Unable to communicate with Tesla API: %s", ex.message)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
@ -175,7 +175,7 @@ async def validate_input(hass: core.HomeAssistant, data):
|
|||||||
if ex.code == HTTP_UNAUTHORIZED:
|
if ex.code == HTTP_UNAUTHORIZED:
|
||||||
_LOGGER.error("Invalid credentials: %s", ex)
|
_LOGGER.error("Invalid credentials: %s", ex)
|
||||||
raise InvalidAuth() from ex
|
raise InvalidAuth() from ex
|
||||||
_LOGGER.error("Unable to communicate with Tesla API: %s", ex)
|
_LOGGER.error("Unable to communicate with Tesla API: %s", ex.message)
|
||||||
raise CannotConnect() from ex
|
raise CannotConnect() from ex
|
||||||
finally:
|
finally:
|
||||||
await async_client.aclose()
|
await async_client.aclose()
|
||||||
|
@ -137,6 +137,7 @@ RT_SENSOR_MAP: dict[str, TibberSensorEntityDescription] = {
|
|||||||
device_class=DEVICE_CLASS_ENERGY,
|
device_class=DEVICE_CLASS_ENERGY,
|
||||||
unit_of_measurement=ENERGY_KILO_WATT_HOUR,
|
unit_of_measurement=ENERGY_KILO_WATT_HOUR,
|
||||||
state_class=STATE_CLASS_MEASUREMENT,
|
state_class=STATE_CLASS_MEASUREMENT,
|
||||||
|
reset_type=ResetType.NEVER,
|
||||||
),
|
),
|
||||||
"lastMeterProduction": TibberSensorEntityDescription(
|
"lastMeterProduction": TibberSensorEntityDescription(
|
||||||
key="lastMeterProduction",
|
key="lastMeterProduction",
|
||||||
@ -144,6 +145,7 @@ RT_SENSOR_MAP: dict[str, TibberSensorEntityDescription] = {
|
|||||||
device_class=DEVICE_CLASS_ENERGY,
|
device_class=DEVICE_CLASS_ENERGY,
|
||||||
unit_of_measurement=ENERGY_KILO_WATT_HOUR,
|
unit_of_measurement=ENERGY_KILO_WATT_HOUR,
|
||||||
state_class=STATE_CLASS_MEASUREMENT,
|
state_class=STATE_CLASS_MEASUREMENT,
|
||||||
|
reset_type=ResetType.NEVER,
|
||||||
),
|
),
|
||||||
"voltagePhase1": TibberSensorEntityDescription(
|
"voltagePhase1": TibberSensorEntityDescription(
|
||||||
key="voltagePhase1",
|
key="voltagePhase1",
|
||||||
|
@ -158,7 +158,7 @@ class UniversalMediaPlayer(MediaPlayerEntity):
|
|||||||
self._cmds = commands
|
self._cmds = commands
|
||||||
self._attrs = {}
|
self._attrs = {}
|
||||||
for key, val in attributes.items():
|
for key, val in attributes.items():
|
||||||
attr = val.split("|", 1)
|
attr = list(map(str.strip, val.split("|", 1)))
|
||||||
if len(attr) == 1:
|
if len(attr) == 1:
|
||||||
attr.append(None)
|
attr.append(None)
|
||||||
self._attrs[key] = attr
|
self._attrs[key] = attr
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
"domain": "zeroconf",
|
"domain": "zeroconf",
|
||||||
"name": "Zero-configuration networking (zeroconf)",
|
"name": "Zero-configuration networking (zeroconf)",
|
||||||
"documentation": "https://www.home-assistant.io/integrations/zeroconf",
|
"documentation": "https://www.home-assistant.io/integrations/zeroconf",
|
||||||
"requirements": ["zeroconf==0.34.3"],
|
"requirements": ["zeroconf==0.35.0"],
|
||||||
"dependencies": ["network", "api"],
|
"dependencies": ["network", "api"],
|
||||||
"codeowners": ["@bdraco"],
|
"codeowners": ["@bdraco"],
|
||||||
"quality_scale": "internal",
|
"quality_scale": "internal",
|
||||||
|
@ -5,7 +5,7 @@ from typing import Final
|
|||||||
|
|
||||||
MAJOR_VERSION: Final = 2021
|
MAJOR_VERSION: Final = 2021
|
||||||
MINOR_VERSION: Final = 8
|
MINOR_VERSION: Final = 8
|
||||||
PATCH_VERSION: Final = "6"
|
PATCH_VERSION: Final = "7"
|
||||||
__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, 8, 0)
|
REQUIRED_PYTHON_VER: Final[tuple[int, int, int]] = (3, 8, 0)
|
||||||
|
@ -33,7 +33,7 @@ sqlalchemy==1.4.17
|
|||||||
voluptuous-serialize==2.4.0
|
voluptuous-serialize==2.4.0
|
||||||
voluptuous==0.12.1
|
voluptuous==0.12.1
|
||||||
yarl==1.6.3
|
yarl==1.6.3
|
||||||
zeroconf==0.34.3
|
zeroconf==0.35.0
|
||||||
|
|
||||||
pycryptodome>=3.6.6
|
pycryptodome>=3.6.6
|
||||||
|
|
||||||
|
@ -5,6 +5,7 @@ from numbers import Number
|
|||||||
|
|
||||||
from homeassistant.const import (
|
from homeassistant.const import (
|
||||||
PRESSURE,
|
PRESSURE,
|
||||||
|
PRESSURE_BAR,
|
||||||
PRESSURE_HPA,
|
PRESSURE_HPA,
|
||||||
PRESSURE_INHG,
|
PRESSURE_INHG,
|
||||||
PRESSURE_MBAR,
|
PRESSURE_MBAR,
|
||||||
@ -16,6 +17,7 @@ from homeassistant.const import (
|
|||||||
VALID_UNITS: tuple[str, ...] = (
|
VALID_UNITS: tuple[str, ...] = (
|
||||||
PRESSURE_PA,
|
PRESSURE_PA,
|
||||||
PRESSURE_HPA,
|
PRESSURE_HPA,
|
||||||
|
PRESSURE_BAR,
|
||||||
PRESSURE_MBAR,
|
PRESSURE_MBAR,
|
||||||
PRESSURE_INHG,
|
PRESSURE_INHG,
|
||||||
PRESSURE_PSI,
|
PRESSURE_PSI,
|
||||||
@ -24,6 +26,7 @@ VALID_UNITS: tuple[str, ...] = (
|
|||||||
UNIT_CONVERSION: dict[str, float] = {
|
UNIT_CONVERSION: dict[str, float] = {
|
||||||
PRESSURE_PA: 1,
|
PRESSURE_PA: 1,
|
||||||
PRESSURE_HPA: 1 / 100,
|
PRESSURE_HPA: 1 / 100,
|
||||||
|
PRESSURE_BAR: 1 / 100000,
|
||||||
PRESSURE_MBAR: 1 / 100,
|
PRESSURE_MBAR: 1 / 100,
|
||||||
PRESSURE_INHG: 1 / 3386.389,
|
PRESSURE_INHG: 1 / 3386.389,
|
||||||
PRESSURE_PSI: 1 / 6894.757,
|
PRESSURE_PSI: 1 / 6894.757,
|
||||||
|
@ -106,7 +106,7 @@ adafruit-circuitpython-dht==3.6.0
|
|||||||
adafruit-circuitpython-mcp230xx==2.2.2
|
adafruit-circuitpython-mcp230xx==2.2.2
|
||||||
|
|
||||||
# homeassistant.components.adax
|
# homeassistant.components.adax
|
||||||
adax==0.0.1
|
adax==0.1.1
|
||||||
|
|
||||||
# homeassistant.components.androidtv
|
# homeassistant.components.androidtv
|
||||||
adb-shell[async]==0.3.4
|
adb-shell[async]==0.3.4
|
||||||
@ -1038,7 +1038,7 @@ niluclient==0.1.2
|
|||||||
noaa-coops==0.1.8
|
noaa-coops==0.1.8
|
||||||
|
|
||||||
# homeassistant.components.nfandroidtv
|
# homeassistant.components.nfandroidtv
|
||||||
notifications-android-tv==0.1.2
|
notifications-android-tv==0.1.3
|
||||||
|
|
||||||
# homeassistant.components.notify_events
|
# homeassistant.components.notify_events
|
||||||
notify-events==1.0.4
|
notify-events==1.0.4
|
||||||
@ -1254,7 +1254,7 @@ py-nightscout==1.2.2
|
|||||||
py-schluter==0.1.7
|
py-schluter==0.1.7
|
||||||
|
|
||||||
# homeassistant.components.synology_dsm
|
# homeassistant.components.synology_dsm
|
||||||
py-synologydsm-api==1.0.3
|
py-synologydsm-api==1.0.4
|
||||||
|
|
||||||
# homeassistant.components.zabbix
|
# homeassistant.components.zabbix
|
||||||
py-zabbix==1.1.7
|
py-zabbix==1.1.7
|
||||||
@ -1342,7 +1342,7 @@ pyblackbird==0.5
|
|||||||
pybotvac==0.0.21
|
pybotvac==0.0.21
|
||||||
|
|
||||||
# homeassistant.components.nissan_leaf
|
# homeassistant.components.nissan_leaf
|
||||||
pycarwings2==2.10
|
pycarwings2==2.11
|
||||||
|
|
||||||
# homeassistant.components.cloudflare
|
# homeassistant.components.cloudflare
|
||||||
pycfdns==1.2.1
|
pycfdns==1.2.1
|
||||||
@ -1610,7 +1610,7 @@ pymonoprice==0.3
|
|||||||
pymsteams==0.1.12
|
pymsteams==0.1.12
|
||||||
|
|
||||||
# homeassistant.components.myq
|
# homeassistant.components.myq
|
||||||
pymyq==3.0.4
|
pymyq==3.1.2
|
||||||
|
|
||||||
# homeassistant.components.mysensors
|
# homeassistant.components.mysensors
|
||||||
pymysensors==0.21.0
|
pymysensors==0.21.0
|
||||||
@ -1990,7 +1990,7 @@ pyzbar==0.1.7
|
|||||||
pyzerproc==0.4.8
|
pyzerproc==0.4.8
|
||||||
|
|
||||||
# homeassistant.components.qnap
|
# homeassistant.components.qnap
|
||||||
qnapstats==0.3.1
|
qnapstats==0.4.0
|
||||||
|
|
||||||
# homeassistant.components.quantum_gateway
|
# homeassistant.components.quantum_gateway
|
||||||
quantum-gateway==0.0.5
|
quantum-gateway==0.0.5
|
||||||
@ -2439,7 +2439,7 @@ zeep[async]==4.0.0
|
|||||||
zengge==0.2
|
zengge==0.2
|
||||||
|
|
||||||
# homeassistant.components.zeroconf
|
# homeassistant.components.zeroconf
|
||||||
zeroconf==0.34.3
|
zeroconf==0.35.0
|
||||||
|
|
||||||
# homeassistant.components.zha
|
# homeassistant.components.zha
|
||||||
zha-quirks==0.0.59
|
zha-quirks==0.0.59
|
||||||
|
@ -48,7 +48,7 @@ abodepy==1.2.0
|
|||||||
accuweather==0.2.0
|
accuweather==0.2.0
|
||||||
|
|
||||||
# homeassistant.components.adax
|
# homeassistant.components.adax
|
||||||
adax==0.0.1
|
adax==0.1.1
|
||||||
|
|
||||||
# homeassistant.components.androidtv
|
# homeassistant.components.androidtv
|
||||||
adb-shell[async]==0.3.4
|
adb-shell[async]==0.3.4
|
||||||
@ -579,7 +579,7 @@ nettigo-air-monitor==1.0.0
|
|||||||
nexia==0.9.11
|
nexia==0.9.11
|
||||||
|
|
||||||
# homeassistant.components.nfandroidtv
|
# homeassistant.components.nfandroidtv
|
||||||
notifications-android-tv==0.1.2
|
notifications-android-tv==0.1.3
|
||||||
|
|
||||||
# homeassistant.components.notify_events
|
# homeassistant.components.notify_events
|
||||||
notify-events==1.0.4
|
notify-events==1.0.4
|
||||||
@ -702,7 +702,7 @@ py-melissa-climate==2.1.4
|
|||||||
py-nightscout==1.2.2
|
py-nightscout==1.2.2
|
||||||
|
|
||||||
# homeassistant.components.synology_dsm
|
# homeassistant.components.synology_dsm
|
||||||
py-synologydsm-api==1.0.3
|
py-synologydsm-api==1.0.4
|
||||||
|
|
||||||
# homeassistant.components.seventeentrack
|
# homeassistant.components.seventeentrack
|
||||||
py17track==3.2.1
|
py17track==3.2.1
|
||||||
@ -917,7 +917,7 @@ pymodbus==2.5.2
|
|||||||
pymonoprice==0.3
|
pymonoprice==0.3
|
||||||
|
|
||||||
# homeassistant.components.myq
|
# homeassistant.components.myq
|
||||||
pymyq==3.0.4
|
pymyq==3.1.2
|
||||||
|
|
||||||
# homeassistant.components.mysensors
|
# homeassistant.components.mysensors
|
||||||
pymysensors==0.21.0
|
pymysensors==0.21.0
|
||||||
@ -1341,7 +1341,7 @@ youless-api==0.10
|
|||||||
zeep[async]==4.0.0
|
zeep[async]==4.0.0
|
||||||
|
|
||||||
# homeassistant.components.zeroconf
|
# homeassistant.components.zeroconf
|
||||||
zeroconf==0.34.3
|
zeroconf==0.35.0
|
||||||
|
|
||||||
# homeassistant.components.zha
|
# homeassistant.components.zha
|
||||||
zha-quirks==0.0.59
|
zha-quirks==0.0.59
|
||||||
|
Loading…
x
Reference in New Issue
Block a user