mirror of
https://github.com/home-assistant/core.git
synced 2025-07-26 06:37:52 +00:00
Merge branch 'whirlpool_bronze' of github.com:home-assistant/core into whirlpool_bronze
This commit is contained in:
commit
1bb74d36e9
4
.github/workflows/ci.yaml
vendored
4
.github/workflows/ci.yaml
vendored
@ -1317,7 +1317,7 @@ jobs:
|
|||||||
pattern: coverage-*
|
pattern: coverage-*
|
||||||
- name: Upload coverage to Codecov
|
- name: Upload coverage to Codecov
|
||||||
if: needs.info.outputs.test_full_suite == 'true'
|
if: needs.info.outputs.test_full_suite == 'true'
|
||||||
uses: codecov/codecov-action@v5.4.0
|
uses: codecov/codecov-action@v5.4.2
|
||||||
with:
|
with:
|
||||||
fail_ci_if_error: true
|
fail_ci_if_error: true
|
||||||
flags: full-suite
|
flags: full-suite
|
||||||
@ -1459,7 +1459,7 @@ jobs:
|
|||||||
pattern: coverage-*
|
pattern: coverage-*
|
||||||
- name: Upload coverage to Codecov
|
- name: Upload coverage to Codecov
|
||||||
if: needs.info.outputs.test_full_suite == 'false'
|
if: needs.info.outputs.test_full_suite == 'false'
|
||||||
uses: codecov/codecov-action@v5.4.0
|
uses: codecov/codecov-action@v5.4.2
|
||||||
with:
|
with:
|
||||||
fail_ci_if_error: true
|
fail_ci_if_error: true
|
||||||
token: ${{ secrets.CODECOV_TOKEN }}
|
token: ${{ secrets.CODECOV_TOKEN }}
|
||||||
|
@ -31,7 +31,7 @@
|
|||||||
"state_attributes": {
|
"state_attributes": {
|
||||||
"preset_mode": {
|
"preset_mode": {
|
||||||
"state": {
|
"state": {
|
||||||
"auto": "[%key:component::climate::entity_component::_::state_attributes::fan_mode::state::auto%]"
|
"auto": "[%key:common::state::auto%]"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -28,10 +28,10 @@
|
|||||||
"name": "Thermostat",
|
"name": "Thermostat",
|
||||||
"state": {
|
"state": {
|
||||||
"off": "[%key:common::state::off%]",
|
"off": "[%key:common::state::off%]",
|
||||||
|
"auto": "[%key:common::state::auto%]",
|
||||||
"heat": "Heat",
|
"heat": "Heat",
|
||||||
"cool": "Cool",
|
"cool": "Cool",
|
||||||
"heat_cool": "Heat/Cool",
|
"heat_cool": "Heat/Cool",
|
||||||
"auto": "Auto",
|
|
||||||
"dry": "Dry",
|
"dry": "Dry",
|
||||||
"fan_only": "Fan only"
|
"fan_only": "Fan only"
|
||||||
},
|
},
|
||||||
@ -50,7 +50,7 @@
|
|||||||
"state": {
|
"state": {
|
||||||
"off": "[%key:common::state::off%]",
|
"off": "[%key:common::state::off%]",
|
||||||
"on": "[%key:common::state::on%]",
|
"on": "[%key:common::state::on%]",
|
||||||
"auto": "Auto",
|
"auto": "[%key:common::state::auto%]",
|
||||||
"low": "[%key:common::state::low%]",
|
"low": "[%key:common::state::low%]",
|
||||||
"medium": "[%key:common::state::medium%]",
|
"medium": "[%key:common::state::medium%]",
|
||||||
"high": "[%key:common::state::high%]",
|
"high": "[%key:common::state::high%]",
|
||||||
@ -69,13 +69,13 @@
|
|||||||
"hvac_action": {
|
"hvac_action": {
|
||||||
"name": "Current action",
|
"name": "Current action",
|
||||||
"state": {
|
"state": {
|
||||||
|
"off": "[%key:common::state::off%]",
|
||||||
|
"idle": "[%key:common::state::idle%]",
|
||||||
"cooling": "Cooling",
|
"cooling": "Cooling",
|
||||||
"defrosting": "Defrosting",
|
"defrosting": "Defrosting",
|
||||||
"drying": "Drying",
|
"drying": "Drying",
|
||||||
"fan": "Fan",
|
"fan": "Fan",
|
||||||
"heating": "Heating",
|
"heating": "Heating",
|
||||||
"idle": "[%key:common::state::idle%]",
|
|
||||||
"off": "[%key:common::state::off%]",
|
|
||||||
"preheating": "Preheating"
|
"preheating": "Preheating"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -258,7 +258,7 @@
|
|||||||
"hvac_mode": {
|
"hvac_mode": {
|
||||||
"options": {
|
"options": {
|
||||||
"off": "[%key:common::state::off%]",
|
"off": "[%key:common::state::off%]",
|
||||||
"auto": "Auto",
|
"auto": "[%key:common::state::auto%]",
|
||||||
"cool": "Cool",
|
"cool": "Cool",
|
||||||
"dry": "Dry",
|
"dry": "Dry",
|
||||||
"fan_only": "Fan only",
|
"fan_only": "Fan only",
|
||||||
|
@ -75,4 +75,7 @@ class ComelitSwitchEntity(ComelitBridgeBaseEntity, SwitchEntity):
|
|||||||
@property
|
@property
|
||||||
def is_on(self) -> bool:
|
def is_on(self) -> bool:
|
||||||
"""Return True if switch is on."""
|
"""Return True if switch is on."""
|
||||||
return self.coordinator.data[OTHER][self._device.index].status == STATE_ON
|
return (
|
||||||
|
self.coordinator.data[self._device.type][self._device.index].status
|
||||||
|
== STATE_ON
|
||||||
|
)
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
"integration_type": "device",
|
"integration_type": "device",
|
||||||
"iot_class": "local_polling",
|
"iot_class": "local_polling",
|
||||||
"loggers": ["devolo_plc_api"],
|
"loggers": ["devolo_plc_api"],
|
||||||
"requirements": ["devolo-plc-api==1.4.1"],
|
"requirements": ["devolo-plc-api==1.5.1"],
|
||||||
"zeroconf": [
|
"zeroconf": [
|
||||||
{
|
{
|
||||||
"type": "_dvl-deviceapi._tcp.local.",
|
"type": "_dvl-deviceapi._tcp.local.",
|
||||||
|
@ -77,12 +77,11 @@ class FritzboxDataUpdateCoordinator(DataUpdateCoordinator[FritzboxCoordinatorDat
|
|||||||
self.configuration_url = self.fritz.get_prefixed_host()
|
self.configuration_url = self.fritz.get_prefixed_host()
|
||||||
|
|
||||||
await self.async_config_entry_first_refresh()
|
await self.async_config_entry_first_refresh()
|
||||||
self.cleanup_removed_devices(
|
self.cleanup_removed_devices(self.data)
|
||||||
list(self.data.devices) + list(self.data.templates)
|
|
||||||
)
|
|
||||||
|
|
||||||
def cleanup_removed_devices(self, available_ains: list[str]) -> None:
|
def cleanup_removed_devices(self, data: FritzboxCoordinatorData) -> None:
|
||||||
"""Cleanup entity and device registry from removed devices."""
|
"""Cleanup entity and device registry from removed devices."""
|
||||||
|
available_ains = list(data.devices) + list(data.templates)
|
||||||
entity_reg = er.async_get(self.hass)
|
entity_reg = er.async_get(self.hass)
|
||||||
for entity in er.async_entries_for_config_entry(
|
for entity in er.async_entries_for_config_entry(
|
||||||
entity_reg, self.config_entry.entry_id
|
entity_reg, self.config_entry.entry_id
|
||||||
@ -91,8 +90,13 @@ class FritzboxDataUpdateCoordinator(DataUpdateCoordinator[FritzboxCoordinatorDat
|
|||||||
LOGGER.debug("Removing obsolete entity entry %s", entity.entity_id)
|
LOGGER.debug("Removing obsolete entity entry %s", entity.entity_id)
|
||||||
entity_reg.async_remove(entity.entity_id)
|
entity_reg.async_remove(entity.entity_id)
|
||||||
|
|
||||||
|
available_main_ains = [
|
||||||
|
ain
|
||||||
|
for ain, dev in data.devices.items()
|
||||||
|
if dev.device_and_unit_id[1] is None
|
||||||
|
]
|
||||||
device_reg = dr.async_get(self.hass)
|
device_reg = dr.async_get(self.hass)
|
||||||
identifiers = {(DOMAIN, ain) for ain in available_ains}
|
identifiers = {(DOMAIN, ain) for ain in available_main_ains}
|
||||||
for device in dr.async_entries_for_config_entry(
|
for device in dr.async_entries_for_config_entry(
|
||||||
device_reg, self.config_entry.entry_id
|
device_reg, self.config_entry.entry_id
|
||||||
):
|
):
|
||||||
@ -165,12 +169,26 @@ class FritzboxDataUpdateCoordinator(DataUpdateCoordinator[FritzboxCoordinatorDat
|
|||||||
"""Fetch all device data."""
|
"""Fetch all device data."""
|
||||||
new_data = await self.hass.async_add_executor_job(self._update_fritz_devices)
|
new_data = await self.hass.async_add_executor_job(self._update_fritz_devices)
|
||||||
|
|
||||||
|
for device in new_data.devices.values():
|
||||||
|
# create device registry entry for new main devices
|
||||||
|
if (
|
||||||
|
device.ain not in self.data.devices
|
||||||
|
and device.device_and_unit_id[1] is None
|
||||||
|
):
|
||||||
|
dr.async_get(self.hass).async_get_or_create(
|
||||||
|
config_entry_id=self.config_entry.entry_id,
|
||||||
|
name=device.name,
|
||||||
|
identifiers={(DOMAIN, device.ain)},
|
||||||
|
manufacturer=device.manufacturer,
|
||||||
|
model=device.productname,
|
||||||
|
sw_version=device.fw_version,
|
||||||
|
configuration_url=self.configuration_url,
|
||||||
|
)
|
||||||
|
|
||||||
if (
|
if (
|
||||||
self.data.devices.keys() - new_data.devices.keys()
|
self.data.devices.keys() - new_data.devices.keys()
|
||||||
or self.data.templates.keys() - new_data.templates.keys()
|
or self.data.templates.keys() - new_data.templates.keys()
|
||||||
):
|
):
|
||||||
self.cleanup_removed_devices(
|
self.cleanup_removed_devices(new_data)
|
||||||
list(new_data.devices) + list(new_data.templates)
|
|
||||||
)
|
|
||||||
|
|
||||||
return new_data
|
return new_data
|
||||||
|
@ -58,11 +58,4 @@ class FritzBoxDeviceEntity(FritzBoxEntity):
|
|||||||
@property
|
@property
|
||||||
def device_info(self) -> DeviceInfo:
|
def device_info(self) -> DeviceInfo:
|
||||||
"""Return device specific attributes."""
|
"""Return device specific attributes."""
|
||||||
return DeviceInfo(
|
return DeviceInfo(identifiers={(DOMAIN, self.data.device_and_unit_id[0])})
|
||||||
name=self.data.name,
|
|
||||||
identifiers={(DOMAIN, self.ain)},
|
|
||||||
manufacturer=self.data.manufacturer,
|
|
||||||
model=self.data.productname,
|
|
||||||
sw_version=self.data.fw_version,
|
|
||||||
configuration_url=self.coordinator.configuration_url,
|
|
||||||
)
|
|
||||||
|
@ -5,5 +5,5 @@
|
|||||||
"config_flow": true,
|
"config_flow": true,
|
||||||
"documentation": "https://www.home-assistant.io/integrations/holiday",
|
"documentation": "https://www.home-assistant.io/integrations/holiday",
|
||||||
"iot_class": "local_polling",
|
"iot_class": "local_polling",
|
||||||
"requirements": ["holidays==0.69", "babel==2.15.0"]
|
"requirements": ["holidays==0.70", "babel==2.15.0"]
|
||||||
}
|
}
|
||||||
|
@ -37,6 +37,8 @@ class TimePattern:
|
|||||||
|
|
||||||
if isinstance(value, str) and value.startswith("/"):
|
if isinstance(value, str) and value.startswith("/"):
|
||||||
number = int(value[1:])
|
number = int(value[1:])
|
||||||
|
if number == 0:
|
||||||
|
raise vol.Invalid(f"must be a value between 1 and {self.maximum}")
|
||||||
else:
|
else:
|
||||||
value = number = int(value)
|
value = number = int(value)
|
||||||
|
|
||||||
|
@ -2,7 +2,6 @@
|
|||||||
|
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
from collections.abc import Callable
|
|
||||||
from datetime import timedelta
|
from datetime import timedelta
|
||||||
|
|
||||||
from homeassistant.helpers.device_registry import DeviceInfo
|
from homeassistant.helpers.device_registry import DeviceInfo
|
||||||
@ -25,7 +24,6 @@ class HuaweiLteBaseEntity(Entity):
|
|||||||
def __init__(self, router: Router) -> None:
|
def __init__(self, router: Router) -> None:
|
||||||
"""Initialize."""
|
"""Initialize."""
|
||||||
self.router = router
|
self.router = router
|
||||||
self._unsub_handlers: list[Callable] = []
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def _device_unique_id(self) -> str:
|
def _device_unique_id(self) -> str:
|
||||||
@ -48,7 +46,7 @@ class HuaweiLteBaseEntity(Entity):
|
|||||||
|
|
||||||
async def async_added_to_hass(self) -> None:
|
async def async_added_to_hass(self) -> None:
|
||||||
"""Connect to update signals."""
|
"""Connect to update signals."""
|
||||||
self._unsub_handlers.append(
|
self.async_on_remove(
|
||||||
async_dispatcher_connect(self.hass, UPDATE_SIGNAL, self._async_maybe_update)
|
async_dispatcher_connect(self.hass, UPDATE_SIGNAL, self._async_maybe_update)
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -57,12 +55,6 @@ class HuaweiLteBaseEntity(Entity):
|
|||||||
if config_entry_unique_id == self.router.config_entry.unique_id:
|
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:
|
|
||||||
"""Invoke unsubscription handlers."""
|
|
||||||
for unsub in self._unsub_handlers:
|
|
||||||
unsub()
|
|
||||||
self._unsub_handlers.clear()
|
|
||||||
|
|
||||||
|
|
||||||
class HuaweiLteBaseEntityWithDevice(HuaweiLteBaseEntity):
|
class HuaweiLteBaseEntityWithDevice(HuaweiLteBaseEntity):
|
||||||
"""Base entity with device info."""
|
"""Base entity with device info."""
|
||||||
|
@ -315,7 +315,7 @@
|
|||||||
"preset_mode": {
|
"preset_mode": {
|
||||||
"name": "[%key:component::climate::entity_component::_::state_attributes::preset_mode::name%]",
|
"name": "[%key:component::climate::entity_component::_::state_attributes::preset_mode::name%]",
|
||||||
"state": {
|
"state": {
|
||||||
"auto": "Auto",
|
"auto": "[%key:common::state::auto%]",
|
||||||
"building_protection": "Building protection",
|
"building_protection": "Building protection",
|
||||||
"comfort": "[%key:component::climate::entity_component::_::state_attributes::preset_mode::state::comfort%]",
|
"comfort": "[%key:component::climate::entity_component::_::state_attributes::preset_mode::state::comfort%]",
|
||||||
"economy": "[%key:component::climate::entity_component::_::state_attributes::preset_mode::state::eco%]",
|
"economy": "[%key:component::climate::entity_component::_::state_attributes::preset_mode::state::eco%]",
|
||||||
|
@ -123,7 +123,7 @@
|
|||||||
"mid": "[%key:common::state::medium%]",
|
"mid": "[%key:common::state::medium%]",
|
||||||
"high": "[%key:common::state::high%]",
|
"high": "[%key:common::state::high%]",
|
||||||
"power": "[%key:component::lg_thinq::entity::sensor::current_job_mode::state::high%]",
|
"power": "[%key:component::lg_thinq::entity::sensor::current_job_mode::state::high%]",
|
||||||
"auto": "[%key:component::lg_thinq::entity::sensor::growth_mode::state::standard%]"
|
"auto": "[%key:common::state::auto%]"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"preset_mode": {
|
"preset_mode": {
|
||||||
@ -343,7 +343,7 @@
|
|||||||
"growth_mode": {
|
"growth_mode": {
|
||||||
"name": "Mode",
|
"name": "Mode",
|
||||||
"state": {
|
"state": {
|
||||||
"standard": "Auto",
|
"standard": "[%key:common::state::auto%]",
|
||||||
"ext_leaf": "Vegetables",
|
"ext_leaf": "Vegetables",
|
||||||
"ext_herb": "Herbs",
|
"ext_herb": "Herbs",
|
||||||
"ext_flower": "Flowers",
|
"ext_flower": "Flowers",
|
||||||
@ -353,7 +353,7 @@
|
|||||||
"growth_mode_for_location": {
|
"growth_mode_for_location": {
|
||||||
"name": "{location} mode",
|
"name": "{location} mode",
|
||||||
"state": {
|
"state": {
|
||||||
"standard": "[%key:component::lg_thinq::entity::sensor::growth_mode::state::standard%]",
|
"standard": "[%key:common::state::auto%]",
|
||||||
"ext_leaf": "[%key:component::lg_thinq::entity::sensor::growth_mode::state::ext_leaf%]",
|
"ext_leaf": "[%key:component::lg_thinq::entity::sensor::growth_mode::state::ext_leaf%]",
|
||||||
"ext_herb": "[%key:component::lg_thinq::entity::sensor::growth_mode::state::ext_herb%]",
|
"ext_herb": "[%key:component::lg_thinq::entity::sensor::growth_mode::state::ext_herb%]",
|
||||||
"ext_flower": "[%key:component::lg_thinq::entity::sensor::growth_mode::state::ext_flower%]",
|
"ext_flower": "[%key:component::lg_thinq::entity::sensor::growth_mode::state::ext_flower%]",
|
||||||
@ -581,7 +581,7 @@
|
|||||||
"name": "[%key:component::lg_thinq::entity::binary_sensor::one_touch_filter::name%]",
|
"name": "[%key:component::lg_thinq::entity::binary_sensor::one_touch_filter::name%]",
|
||||||
"state": {
|
"state": {
|
||||||
"off": "[%key:common::state::off%]",
|
"off": "[%key:common::state::off%]",
|
||||||
"auto": "[%key:component::lg_thinq::entity::sensor::growth_mode::state::standard%]",
|
"auto": "[%key:common::state::auto%]",
|
||||||
"power": "[%key:component::lg_thinq::entity::sensor::current_job_mode::state::high%]",
|
"power": "[%key:component::lg_thinq::entity::sensor::current_job_mode::state::high%]",
|
||||||
"replace": "Replace filter",
|
"replace": "Replace filter",
|
||||||
"smart_power": "Smart safe storage",
|
"smart_power": "Smart safe storage",
|
||||||
@ -599,7 +599,7 @@
|
|||||||
"name": "Operating mode",
|
"name": "Operating mode",
|
||||||
"state": {
|
"state": {
|
||||||
"air_clean": "Purify",
|
"air_clean": "Purify",
|
||||||
"auto": "[%key:component::lg_thinq::entity::sensor::growth_mode::state::standard%]",
|
"auto": "[%key:common::state::auto%]",
|
||||||
"clothes_dry": "Laundry",
|
"clothes_dry": "Laundry",
|
||||||
"edge": "Edge cleaning",
|
"edge": "Edge cleaning",
|
||||||
"heat_pump": "Heat pump",
|
"heat_pump": "Heat pump",
|
||||||
@ -649,7 +649,7 @@
|
|||||||
"current_dish_washing_course": {
|
"current_dish_washing_course": {
|
||||||
"name": "Current cycle",
|
"name": "Current cycle",
|
||||||
"state": {
|
"state": {
|
||||||
"auto": "[%key:component::lg_thinq::entity::sensor::growth_mode::state::standard%]",
|
"auto": "[%key:common::state::auto%]",
|
||||||
"heavy": "Intensive",
|
"heavy": "Intensive",
|
||||||
"delicate": "Delicate",
|
"delicate": "Delicate",
|
||||||
"turbo": "[%key:component::lg_thinq::entity::select::wind_strength::state::power%]",
|
"turbo": "[%key:component::lg_thinq::entity::select::wind_strength::state::power%]",
|
||||||
@ -881,7 +881,7 @@
|
|||||||
"high": "[%key:common::state::high%]",
|
"high": "[%key:common::state::high%]",
|
||||||
"power": "Turbo",
|
"power": "Turbo",
|
||||||
"turbo": "[%key:component::lg_thinq::entity::select::wind_strength::state::power%]",
|
"turbo": "[%key:component::lg_thinq::entity::select::wind_strength::state::power%]",
|
||||||
"auto": "[%key:component::lg_thinq::entity::sensor::growth_mode::state::standard%]",
|
"auto": "[%key:common::state::auto%]",
|
||||||
"wind_1": "Step 1",
|
"wind_1": "Step 1",
|
||||||
"wind_2": "Step 2",
|
"wind_2": "Step 2",
|
||||||
"wind_3": "Step 3",
|
"wind_3": "Step 3",
|
||||||
@ -905,7 +905,7 @@
|
|||||||
"name": "Operating mode",
|
"name": "Operating mode",
|
||||||
"state": {
|
"state": {
|
||||||
"air_clean": "Purifying",
|
"air_clean": "Purifying",
|
||||||
"auto": "[%key:component::lg_thinq::entity::sensor::growth_mode::state::standard%]",
|
"auto": "[%key:common::state::auto%]",
|
||||||
"baby_care": "[%key:component::lg_thinq::entity::sensor::personalization_mode::state::baby%]",
|
"baby_care": "[%key:component::lg_thinq::entity::sensor::personalization_mode::state::baby%]",
|
||||||
"circulator": "Booster",
|
"circulator": "Booster",
|
||||||
"clean": "Single",
|
"clean": "Single",
|
||||||
@ -1016,7 +1016,7 @@
|
|||||||
"name": "[%key:component::lg_thinq::entity::binary_sensor::one_touch_filter::name%]",
|
"name": "[%key:component::lg_thinq::entity::binary_sensor::one_touch_filter::name%]",
|
||||||
"state": {
|
"state": {
|
||||||
"off": "[%key:common::state::off%]",
|
"off": "[%key:common::state::off%]",
|
||||||
"auto": "[%key:component::lg_thinq::entity::sensor::growth_mode::state::standard%]",
|
"auto": "[%key:common::state::auto%]",
|
||||||
"power": "[%key:component::lg_thinq::entity::sensor::current_job_mode::state::high%]",
|
"power": "[%key:component::lg_thinq::entity::sensor::current_job_mode::state::high%]",
|
||||||
"replace": "[%key:component::lg_thinq::entity::sensor::fresh_air_filter::state::replace%]",
|
"replace": "[%key:component::lg_thinq::entity::sensor::fresh_air_filter::state::replace%]",
|
||||||
"smart_power": "[%key:component::lg_thinq::entity::sensor::fresh_air_filter::state::smart_power%]",
|
"smart_power": "[%key:component::lg_thinq::entity::sensor::fresh_air_filter::state::smart_power%]",
|
||||||
|
@ -7,6 +7,6 @@
|
|||||||
"integration_type": "hub",
|
"integration_type": "hub",
|
||||||
"iot_class": "local_polling",
|
"iot_class": "local_polling",
|
||||||
"loggers": ["linkplay"],
|
"loggers": ["linkplay"],
|
||||||
"requirements": ["python-linkplay==0.2.2"],
|
"requirements": ["python-linkplay==0.2.3"],
|
||||||
"zeroconf": ["_linkplay._tcp.local."]
|
"zeroconf": ["_linkplay._tcp.local."]
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,6 @@
|
|||||||
"documentation": "https://www.home-assistant.io/integrations/lutron",
|
"documentation": "https://www.home-assistant.io/integrations/lutron",
|
||||||
"iot_class": "local_polling",
|
"iot_class": "local_polling",
|
||||||
"loggers": ["pylutron"],
|
"loggers": ["pylutron"],
|
||||||
"requirements": ["pylutron==0.2.16"],
|
"requirements": ["pylutron==0.2.18"],
|
||||||
"single_config_entry": true
|
"single_config_entry": true
|
||||||
}
|
}
|
||||||
|
@ -147,7 +147,7 @@
|
|||||||
"low": "[%key:common::state::low%]",
|
"low": "[%key:common::state::low%]",
|
||||||
"medium": "[%key:common::state::medium%]",
|
"medium": "[%key:common::state::medium%]",
|
||||||
"high": "[%key:common::state::high%]",
|
"high": "[%key:common::state::high%]",
|
||||||
"auto": "Auto",
|
"auto": "[%key:common::state::auto%]",
|
||||||
"natural_wind": "Natural wind",
|
"natural_wind": "Natural wind",
|
||||||
"sleep_wind": "Sleep wind"
|
"sleep_wind": "Sleep wind"
|
||||||
}
|
}
|
||||||
|
@ -55,12 +55,12 @@
|
|||||||
"heater_mode": {
|
"heater_mode": {
|
||||||
"name": "Heater mode",
|
"name": "Heater mode",
|
||||||
"state": {
|
"state": {
|
||||||
"auto": "Auto",
|
"off": "[%key:common::state::off%]",
|
||||||
|
"auto": "[%key:common::state::auto%]",
|
||||||
|
"manual": "[%key:common::state::manual%]",
|
||||||
"extraenergy": "Extra energy",
|
"extraenergy": "Extra energy",
|
||||||
"ffr": "Fast frequency reserve",
|
"ffr": "Fast frequency reserve",
|
||||||
"legionella": "Legionella",
|
"legionella": "Legionella",
|
||||||
"manual": "Manual",
|
|
||||||
"off": "[%key:common::state::off%]",
|
|
||||||
"powersave": "Power save",
|
"powersave": "Power save",
|
||||||
"voltage": "Voltage"
|
"voltage": "Voltage"
|
||||||
}
|
}
|
||||||
|
@ -23,7 +23,7 @@
|
|||||||
},
|
},
|
||||||
"data_description": {
|
"data_description": {
|
||||||
"password": "The Smile ID printed on the label on the back of your Adam, Smile-T, or P1.",
|
"password": "The Smile ID printed on the label on the back of your Adam, Smile-T, or P1.",
|
||||||
"host": "The hostname or IP-address of your Smile. You can find it in your router or the Plugwise App.",
|
"host": "The hostname or IP-address of your Smile. You can find it in your router or the Plugwise app.",
|
||||||
"port": "By default your Smile uses port 80, normally you should not have to change this.",
|
"port": "By default your Smile uses port 80, normally you should not have to change this.",
|
||||||
"username": "Default is `smile`, or `stretch` for the legacy Stretch."
|
"username": "Default is `smile`, or `stretch` for the legacy Stretch."
|
||||||
}
|
}
|
||||||
@ -113,7 +113,7 @@
|
|||||||
"name": "DHW mode",
|
"name": "DHW mode",
|
||||||
"state": {
|
"state": {
|
||||||
"off": "[%key:common::state::off%]",
|
"off": "[%key:common::state::off%]",
|
||||||
"auto": "Auto",
|
"auto": "[%key:common::state::auto%]",
|
||||||
"boost": "[%key:component::climate::entity_component::_::state_attributes::preset_mode::state::boost%]",
|
"boost": "[%key:component::climate::entity_component::_::state_attributes::preset_mode::state::boost%]",
|
||||||
"comfort": "[%key:component::climate::entity_component::_::state_attributes::preset_mode::state::comfort%]"
|
"comfort": "[%key:component::climate::entity_component::_::state_attributes::preset_mode::state::comfort%]"
|
||||||
}
|
}
|
||||||
|
@ -170,12 +170,12 @@ async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
|
|||||||
exclude_event_types=exclude_event_types,
|
exclude_event_types=exclude_event_types,
|
||||||
)
|
)
|
||||||
get_instance.cache_clear()
|
get_instance.cache_clear()
|
||||||
|
entity_registry.async_setup(hass)
|
||||||
instance.async_initialize()
|
instance.async_initialize()
|
||||||
instance.async_register()
|
instance.async_register()
|
||||||
instance.start()
|
instance.start()
|
||||||
async_register_services(hass, instance)
|
async_register_services(hass, instance)
|
||||||
websocket_api.async_setup(hass)
|
websocket_api.async_setup(hass)
|
||||||
entity_registry.async_setup(hass)
|
|
||||||
|
|
||||||
await _async_setup_integration_platform(hass, instance)
|
await _async_setup_integration_platform(hass, instance)
|
||||||
|
|
||||||
|
@ -4,8 +4,9 @@ import logging
|
|||||||
from typing import TYPE_CHECKING
|
from typing import TYPE_CHECKING
|
||||||
|
|
||||||
from homeassistant.core import Event, HomeAssistant, callback
|
from homeassistant.core import Event, HomeAssistant, callback
|
||||||
|
from homeassistant.exceptions import HomeAssistantError
|
||||||
from homeassistant.helpers import entity_registry as er
|
from homeassistant.helpers import entity_registry as er
|
||||||
from homeassistant.helpers.start import async_at_start
|
from homeassistant.helpers.event import async_has_entity_registry_updated_listeners
|
||||||
|
|
||||||
from .core import Recorder
|
from .core import Recorder
|
||||||
from .util import filter_unique_constraint_integrity_error, get_instance, session_scope
|
from .util import filter_unique_constraint_integrity_error, get_instance, session_scope
|
||||||
@ -40,16 +41,17 @@ def async_setup(hass: HomeAssistant) -> None:
|
|||||||
"""Handle entity_id changed filter."""
|
"""Handle entity_id changed filter."""
|
||||||
return event_data["action"] == "update" and "old_entity_id" in event_data
|
return event_data["action"] == "update" and "old_entity_id" in event_data
|
||||||
|
|
||||||
@callback
|
if async_has_entity_registry_updated_listeners(hass):
|
||||||
def _setup_entity_registry_event_handler(hass: HomeAssistant) -> None:
|
raise HomeAssistantError(
|
||||||
"""Subscribe to event registry events."""
|
"The recorder entity registry listener must be installed"
|
||||||
hass.bus.async_listen(
|
" before async_track_entity_registry_updated_event is called"
|
||||||
er.EVENT_ENTITY_REGISTRY_UPDATED,
|
|
||||||
_async_entity_id_changed,
|
|
||||||
event_filter=entity_registry_changed_filter,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
async_at_start(hass, _setup_entity_registry_event_handler)
|
hass.bus.async_listen(
|
||||||
|
er.EVENT_ENTITY_REGISTRY_UPDATED,
|
||||||
|
_async_entity_id_changed,
|
||||||
|
event_filter=entity_registry_changed_filter,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def update_states_metadata(
|
def update_states_metadata(
|
||||||
|
@ -380,6 +380,9 @@
|
|||||||
},
|
},
|
||||||
"scene_mode": {
|
"scene_mode": {
|
||||||
"default": "mdi:view-list"
|
"default": "mdi:view-list"
|
||||||
|
},
|
||||||
|
"packing_time": {
|
||||||
|
"default": "mdi:record-rec"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"sensor": {
|
"sensor": {
|
||||||
|
@ -19,5 +19,5 @@
|
|||||||
"iot_class": "local_push",
|
"iot_class": "local_push",
|
||||||
"loggers": ["reolink_aio"],
|
"loggers": ["reolink_aio"],
|
||||||
"quality_scale": "platinum",
|
"quality_scale": "platinum",
|
||||||
"requirements": ["reolink-aio==0.13.1"]
|
"requirements": ["reolink-aio==0.13.2"]
|
||||||
}
|
}
|
||||||
|
@ -263,6 +263,17 @@ HOST_SELECT_ENTITIES = (
|
|||||||
value=lambda api: api.baichuan.active_scene,
|
value=lambda api: api.baichuan.active_scene,
|
||||||
method=lambda api, name: api.baichuan.set_scene(scene_name=name),
|
method=lambda api, name: api.baichuan.set_scene(scene_name=name),
|
||||||
),
|
),
|
||||||
|
ReolinkHostSelectEntityDescription(
|
||||||
|
key="packing_time",
|
||||||
|
cmd_key="GetRec",
|
||||||
|
translation_key="packing_time",
|
||||||
|
entity_category=EntityCategory.CONFIG,
|
||||||
|
entity_registry_enabled_default=False,
|
||||||
|
get_options=lambda api: api.recording_packing_time_list,
|
||||||
|
supported=lambda api: api.supported(None, "pak_time"),
|
||||||
|
value=lambda api: api.recording_packing_time,
|
||||||
|
method=lambda api, value: api.set_recording_packing_time(value),
|
||||||
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
CHIME_SELECT_ENTITIES = (
|
CHIME_SELECT_ENTITIES = (
|
||||||
|
@ -652,7 +652,7 @@
|
|||||||
"name": "Floodlight mode",
|
"name": "Floodlight mode",
|
||||||
"state": {
|
"state": {
|
||||||
"off": "[%key:common::state::off%]",
|
"off": "[%key:common::state::off%]",
|
||||||
"auto": "[%key:component::reolink::entity::select::day_night_mode::state::auto%]",
|
"auto": "[%key:common::state::auto%]",
|
||||||
"onatnight": "On at night",
|
"onatnight": "On at night",
|
||||||
"schedule": "Schedule",
|
"schedule": "Schedule",
|
||||||
"adaptive": "Adaptive",
|
"adaptive": "Adaptive",
|
||||||
@ -662,7 +662,7 @@
|
|||||||
"day_night_mode": {
|
"day_night_mode": {
|
||||||
"name": "Day night mode",
|
"name": "Day night mode",
|
||||||
"state": {
|
"state": {
|
||||||
"auto": "Auto",
|
"auto": "[%key:common::state::auto%]",
|
||||||
"color": "Color",
|
"color": "Color",
|
||||||
"blackwhite": "Black & white"
|
"blackwhite": "Black & white"
|
||||||
}
|
}
|
||||||
@ -691,7 +691,7 @@
|
|||||||
"name": "Doorbell LED",
|
"name": "Doorbell LED",
|
||||||
"state": {
|
"state": {
|
||||||
"stayoff": "Stay off",
|
"stayoff": "Stay off",
|
||||||
"auto": "[%key:component::reolink::entity::select::day_night_mode::state::auto%]",
|
"auto": "[%key:common::state::auto%]",
|
||||||
"alwaysonatnight": "Auto & always on at night",
|
"alwaysonatnight": "Auto & always on at night",
|
||||||
"always": "Always on",
|
"always": "Always on",
|
||||||
"alwayson": "Always on"
|
"alwayson": "Always on"
|
||||||
@ -702,7 +702,7 @@
|
|||||||
"state": {
|
"state": {
|
||||||
"off": "[%key:common::state::off%]",
|
"off": "[%key:common::state::off%]",
|
||||||
"on": "[%key:common::state::on%]",
|
"on": "[%key:common::state::on%]",
|
||||||
"auto": "[%key:component::reolink::entity::select::day_night_mode::state::auto%]"
|
"auto": "[%key:common::state::auto%]"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"binning_mode": {
|
"binning_mode": {
|
||||||
@ -710,7 +710,7 @@
|
|||||||
"state": {
|
"state": {
|
||||||
"off": "[%key:common::state::off%]",
|
"off": "[%key:common::state::off%]",
|
||||||
"on": "[%key:common::state::on%]",
|
"on": "[%key:common::state::on%]",
|
||||||
"auto": "[%key:component::reolink::entity::select::day_night_mode::state::auto%]"
|
"auto": "[%key:common::state::auto%]"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"hub_alarm_ringtone": {
|
"hub_alarm_ringtone": {
|
||||||
@ -845,6 +845,9 @@
|
|||||||
"home": "[%key:common::state::home%]",
|
"home": "[%key:common::state::home%]",
|
||||||
"away": "[%key:common::state::not_home%]"
|
"away": "[%key:common::state::not_home%]"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"packing_time": {
|
||||||
|
"name": "Recording packing time"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"sensor": {
|
"sensor": {
|
||||||
|
@ -426,11 +426,11 @@
|
|||||||
"state_attributes": {
|
"state_attributes": {
|
||||||
"fan_speed": {
|
"fan_speed": {
|
||||||
"state": {
|
"state": {
|
||||||
"auto": "Auto",
|
"off": "[%key:common::state::off%]",
|
||||||
|
"auto": "[%key:common::state::auto%]",
|
||||||
"balanced": "Balanced",
|
"balanced": "Balanced",
|
||||||
"custom": "[%key:component::roborock::entity::select::mop_mode::state::custom%]",
|
"custom": "[%key:component::roborock::entity::select::mop_mode::state::custom%]",
|
||||||
"gentle": "Gentle",
|
"gentle": "Gentle",
|
||||||
"off": "[%key:common::state::off%]",
|
|
||||||
"max": "[%key:component::roborock::entity::select::mop_intensity::state::max%]",
|
"max": "[%key:component::roborock::entity::select::mop_intensity::state::max%]",
|
||||||
"max_plus": "Max plus",
|
"max_plus": "Max plus",
|
||||||
"medium": "[%key:common::state::medium%]",
|
"medium": "[%key:common::state::medium%]",
|
||||||
|
@ -53,7 +53,7 @@
|
|||||||
"state_attributes": {
|
"state_attributes": {
|
||||||
"preset_mode": {
|
"preset_mode": {
|
||||||
"state": {
|
"state": {
|
||||||
"auto": "Auto"
|
"auto": "[%key:common::state::auto%]"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -139,7 +139,7 @@
|
|||||||
"description": "Adds a meter reading to Tado Energy IQ.",
|
"description": "Adds a meter reading to Tado Energy IQ.",
|
||||||
"fields": {
|
"fields": {
|
||||||
"config_entry": {
|
"config_entry": {
|
||||||
"name": "Config Entry",
|
"name": "Config entry",
|
||||||
"description": "Config entry to add meter reading to."
|
"description": "Config entry to add meter reading to."
|
||||||
},
|
},
|
||||||
"reading": {
|
"reading": {
|
||||||
|
@ -163,7 +163,7 @@ class UkTransportLiveBusTimeSensor(UkTransportSensor):
|
|||||||
self._destination_re = re.compile(f"{bus_direction}", re.IGNORECASE)
|
self._destination_re = re.compile(f"{bus_direction}", re.IGNORECASE)
|
||||||
|
|
||||||
sensor_name = f"Next bus to {bus_direction}"
|
sensor_name = f"Next bus to {bus_direction}"
|
||||||
stop_url = f"bus/stop/{stop_atcocode}/live.json"
|
stop_url = f"bus/stop/{stop_atcocode}.json"
|
||||||
|
|
||||||
UkTransportSensor.__init__(self, sensor_name, api_app_id, api_app_key, stop_url)
|
UkTransportSensor.__init__(self, sensor_name, api_app_id, api_app_key, stop_url)
|
||||||
self.update = Throttle(interval)(self._update)
|
self.update = Throttle(interval)(self._update)
|
||||||
@ -226,7 +226,7 @@ class UkTransportLiveTrainTimeSensor(UkTransportSensor):
|
|||||||
self._next_trains = []
|
self._next_trains = []
|
||||||
|
|
||||||
sensor_name = f"Next train to {calling_at}"
|
sensor_name = f"Next train to {calling_at}"
|
||||||
query_url = f"train/station/{station_code}/live.json"
|
query_url = f"train/station/{station_code}.json"
|
||||||
|
|
||||||
UkTransportSensor.__init__(
|
UkTransportSensor.__init__(
|
||||||
self, sensor_name, api_app_id, api_app_key, query_url
|
self, sensor_name, api_app_id, api_app_key, query_url
|
||||||
|
@ -43,4 +43,4 @@ class UptimeRobotBinarySensor(UptimeRobotEntity, BinarySensorEntity):
|
|||||||
@property
|
@property
|
||||||
def is_on(self) -> bool:
|
def is_on(self) -> bool:
|
||||||
"""Return True if the entity is on."""
|
"""Return True if the entity is on."""
|
||||||
return self.monitor_available
|
return bool(self.monitor.status == 2)
|
||||||
|
@ -59,8 +59,3 @@ class UptimeRobotEntity(CoordinatorEntity[UptimeRobotDataUpdateCoordinator]):
|
|||||||
),
|
),
|
||||||
self._monitor,
|
self._monitor,
|
||||||
)
|
)
|
||||||
|
|
||||||
@property
|
|
||||||
def monitor_available(self) -> bool:
|
|
||||||
"""Returtn if the monitor is available."""
|
|
||||||
return bool(self.monitor.status == 2)
|
|
||||||
|
@ -86,7 +86,7 @@
|
|||||||
"state_attributes": {
|
"state_attributes": {
|
||||||
"preset_mode": {
|
"preset_mode": {
|
||||||
"state": {
|
"state": {
|
||||||
"auto": "Auto",
|
"auto": "[%key:common::state::auto%]",
|
||||||
"sleep": "Sleep",
|
"sleep": "Sleep",
|
||||||
"advanced_sleep": "Advanced sleep",
|
"advanced_sleep": "Advanced sleep",
|
||||||
"pet": "Pet",
|
"pet": "Pet",
|
||||||
|
@ -7,5 +7,5 @@
|
|||||||
"iot_class": "local_polling",
|
"iot_class": "local_polling",
|
||||||
"loggers": ["holidays"],
|
"loggers": ["holidays"],
|
||||||
"quality_scale": "internal",
|
"quality_scale": "internal",
|
||||||
"requirements": ["holidays==0.69"]
|
"requirements": ["holidays==0.70"]
|
||||||
}
|
}
|
||||||
|
@ -8,5 +8,5 @@
|
|||||||
"iot_class": "local_push",
|
"iot_class": "local_push",
|
||||||
"loggers": ["zeroconf"],
|
"loggers": ["zeroconf"],
|
||||||
"quality_scale": "internal",
|
"quality_scale": "internal",
|
||||||
"requirements": ["zeroconf==0.146.0"]
|
"requirements": ["zeroconf==0.146.5"]
|
||||||
}
|
}
|
||||||
|
@ -75,7 +75,7 @@ voluptuous-serialize==2.6.0
|
|||||||
voluptuous==0.15.2
|
voluptuous==0.15.2
|
||||||
webrtc-models==0.3.0
|
webrtc-models==0.3.0
|
||||||
yarl==1.19.0
|
yarl==1.19.0
|
||||||
zeroconf==0.146.0
|
zeroconf==0.146.5
|
||||||
|
|
||||||
# Constrain pycryptodome to avoid vulnerability
|
# Constrain pycryptodome to avoid vulnerability
|
||||||
# see https://github.com/home-assistant/core/pull/16238
|
# see https://github.com/home-assistant/core/pull/16238
|
||||||
|
@ -123,7 +123,7 @@ dependencies = [
|
|||||||
"voluptuous-openapi==0.0.6",
|
"voluptuous-openapi==0.0.6",
|
||||||
"yarl==1.19.0",
|
"yarl==1.19.0",
|
||||||
"webrtc-models==0.3.0",
|
"webrtc-models==0.3.0",
|
||||||
"zeroconf==0.146.0",
|
"zeroconf==0.146.5",
|
||||||
]
|
]
|
||||||
|
|
||||||
[project.urls]
|
[project.urls]
|
||||||
|
2
requirements.txt
generated
2
requirements.txt
generated
@ -60,4 +60,4 @@ voluptuous-serialize==2.6.0
|
|||||||
voluptuous-openapi==0.0.6
|
voluptuous-openapi==0.0.6
|
||||||
yarl==1.19.0
|
yarl==1.19.0
|
||||||
webrtc-models==0.3.0
|
webrtc-models==0.3.0
|
||||||
zeroconf==0.146.0
|
zeroconf==0.146.5
|
||||||
|
12
requirements_all.txt
generated
12
requirements_all.txt
generated
@ -781,7 +781,7 @@ devialet==1.5.7
|
|||||||
devolo-home-control-api==0.18.3
|
devolo-home-control-api==0.18.3
|
||||||
|
|
||||||
# homeassistant.components.devolo_home_network
|
# homeassistant.components.devolo_home_network
|
||||||
devolo-plc-api==1.4.1
|
devolo-plc-api==1.5.1
|
||||||
|
|
||||||
# homeassistant.components.chacon_dio
|
# homeassistant.components.chacon_dio
|
||||||
dio-chacon-wifi-api==1.2.1
|
dio-chacon-wifi-api==1.2.1
|
||||||
@ -1154,7 +1154,7 @@ hole==0.8.0
|
|||||||
|
|
||||||
# homeassistant.components.holiday
|
# homeassistant.components.holiday
|
||||||
# homeassistant.components.workday
|
# homeassistant.components.workday
|
||||||
holidays==0.69
|
holidays==0.70
|
||||||
|
|
||||||
# homeassistant.components.frontend
|
# homeassistant.components.frontend
|
||||||
home-assistant-frontend==20250411.0
|
home-assistant-frontend==20250411.0
|
||||||
@ -2113,7 +2113,7 @@ pylitterbot==2024.0.0
|
|||||||
pylutron-caseta==0.24.0
|
pylutron-caseta==0.24.0
|
||||||
|
|
||||||
# homeassistant.components.lutron
|
# homeassistant.components.lutron
|
||||||
pylutron==0.2.16
|
pylutron==0.2.18
|
||||||
|
|
||||||
# homeassistant.components.mailgun
|
# homeassistant.components.mailgun
|
||||||
pymailgunner==1.4
|
pymailgunner==1.4
|
||||||
@ -2436,7 +2436,7 @@ python-juicenet==1.1.0
|
|||||||
python-kasa[speedups]==0.10.2
|
python-kasa[speedups]==0.10.2
|
||||||
|
|
||||||
# homeassistant.components.linkplay
|
# homeassistant.components.linkplay
|
||||||
python-linkplay==0.2.2
|
python-linkplay==0.2.3
|
||||||
|
|
||||||
# homeassistant.components.lirc
|
# homeassistant.components.lirc
|
||||||
# python-lirc==1.2.3
|
# python-lirc==1.2.3
|
||||||
@ -2633,7 +2633,7 @@ renault-api==0.2.9
|
|||||||
renson-endura-delta==1.7.2
|
renson-endura-delta==1.7.2
|
||||||
|
|
||||||
# homeassistant.components.reolink
|
# homeassistant.components.reolink
|
||||||
reolink-aio==0.13.1
|
reolink-aio==0.13.2
|
||||||
|
|
||||||
# homeassistant.components.idteck_prox
|
# homeassistant.components.idteck_prox
|
||||||
rfk101py==0.0.1
|
rfk101py==0.0.1
|
||||||
@ -3152,7 +3152,7 @@ zabbix-utils==2.0.2
|
|||||||
zamg==0.3.6
|
zamg==0.3.6
|
||||||
|
|
||||||
# homeassistant.components.zeroconf
|
# homeassistant.components.zeroconf
|
||||||
zeroconf==0.146.0
|
zeroconf==0.146.5
|
||||||
|
|
||||||
# homeassistant.components.zeversolar
|
# homeassistant.components.zeversolar
|
||||||
zeversolar==0.3.2
|
zeversolar==0.3.2
|
||||||
|
12
requirements_test_all.txt
generated
12
requirements_test_all.txt
generated
@ -672,7 +672,7 @@ devialet==1.5.7
|
|||||||
devolo-home-control-api==0.18.3
|
devolo-home-control-api==0.18.3
|
||||||
|
|
||||||
# homeassistant.components.devolo_home_network
|
# homeassistant.components.devolo_home_network
|
||||||
devolo-plc-api==1.4.1
|
devolo-plc-api==1.5.1
|
||||||
|
|
||||||
# homeassistant.components.chacon_dio
|
# homeassistant.components.chacon_dio
|
||||||
dio-chacon-wifi-api==1.2.1
|
dio-chacon-wifi-api==1.2.1
|
||||||
@ -984,7 +984,7 @@ hole==0.8.0
|
|||||||
|
|
||||||
# homeassistant.components.holiday
|
# homeassistant.components.holiday
|
||||||
# homeassistant.components.workday
|
# homeassistant.components.workday
|
||||||
holidays==0.69
|
holidays==0.70
|
||||||
|
|
||||||
# homeassistant.components.frontend
|
# homeassistant.components.frontend
|
||||||
home-assistant-frontend==20250411.0
|
home-assistant-frontend==20250411.0
|
||||||
@ -1728,7 +1728,7 @@ pylitterbot==2024.0.0
|
|||||||
pylutron-caseta==0.24.0
|
pylutron-caseta==0.24.0
|
||||||
|
|
||||||
# homeassistant.components.lutron
|
# homeassistant.components.lutron
|
||||||
pylutron==0.2.16
|
pylutron==0.2.18
|
||||||
|
|
||||||
# homeassistant.components.mailgun
|
# homeassistant.components.mailgun
|
||||||
pymailgunner==1.4
|
pymailgunner==1.4
|
||||||
@ -1976,7 +1976,7 @@ python-juicenet==1.1.0
|
|||||||
python-kasa[speedups]==0.10.2
|
python-kasa[speedups]==0.10.2
|
||||||
|
|
||||||
# homeassistant.components.linkplay
|
# homeassistant.components.linkplay
|
||||||
python-linkplay==0.2.2
|
python-linkplay==0.2.3
|
||||||
|
|
||||||
# homeassistant.components.matter
|
# homeassistant.components.matter
|
||||||
python-matter-server==7.0.0
|
python-matter-server==7.0.0
|
||||||
@ -2137,7 +2137,7 @@ renault-api==0.2.9
|
|||||||
renson-endura-delta==1.7.2
|
renson-endura-delta==1.7.2
|
||||||
|
|
||||||
# homeassistant.components.reolink
|
# homeassistant.components.reolink
|
||||||
reolink-aio==0.13.1
|
reolink-aio==0.13.2
|
||||||
|
|
||||||
# homeassistant.components.rflink
|
# homeassistant.components.rflink
|
||||||
rflink==0.0.66
|
rflink==0.0.66
|
||||||
@ -2548,7 +2548,7 @@ yt-dlp[default]==2025.03.26
|
|||||||
zamg==0.3.6
|
zamg==0.3.6
|
||||||
|
|
||||||
# homeassistant.components.zeroconf
|
# homeassistant.components.zeroconf
|
||||||
zeroconf==0.146.0
|
zeroconf==0.146.5
|
||||||
|
|
||||||
# homeassistant.components.zeversolar
|
# homeassistant.components.zeversolar
|
||||||
zeversolar==0.3.2
|
zeversolar==0.3.2
|
||||||
|
@ -60,6 +60,7 @@ class FritzEntityBaseMock(Mock):
|
|||||||
"""base mock of a AVM Fritz!Box binary sensor device."""
|
"""base mock of a AVM Fritz!Box binary sensor device."""
|
||||||
|
|
||||||
ain = CONF_FAKE_AIN
|
ain = CONF_FAKE_AIN
|
||||||
|
device_and_unit_id = (CONF_FAKE_AIN, None)
|
||||||
manufacturer = CONF_FAKE_MANUFACTURER
|
manufacturer = CONF_FAKE_MANUFACTURER
|
||||||
name = CONF_FAKE_NAME
|
name = CONF_FAKE_NAME
|
||||||
productname = CONF_FAKE_PRODUCTNAME
|
productname = CONF_FAKE_PRODUCTNAME
|
||||||
|
@ -110,6 +110,7 @@ async def test_discover_new_device(hass: HomeAssistant, fritz: Mock) -> None:
|
|||||||
|
|
||||||
new_device = FritzDeviceBinarySensorMock()
|
new_device = FritzDeviceBinarySensorMock()
|
||||||
new_device.ain = "7890 1234"
|
new_device.ain = "7890 1234"
|
||||||
|
new_device.device_and_unit_id = ("7890 1234", None)
|
||||||
new_device.name = "new_device"
|
new_device.name = "new_device"
|
||||||
set_devices(fritz, devices=[device, new_device])
|
set_devices(fritz, devices=[device, new_device])
|
||||||
|
|
||||||
|
@ -85,8 +85,16 @@ async def test_coordinator_automatic_registry_cleanup(
|
|||||||
) -> None:
|
) -> None:
|
||||||
"""Test automatic registry cleanup."""
|
"""Test automatic registry cleanup."""
|
||||||
fritz().get_devices.return_value = [
|
fritz().get_devices.return_value = [
|
||||||
FritzDeviceSwitchMock(ain="fake ain switch", name="fake_switch"),
|
FritzDeviceSwitchMock(
|
||||||
FritzDeviceCoverMock(ain="fake ain cover", name="fake_cover"),
|
ain="fake ain switch",
|
||||||
|
device_and_unit_id=("fake ain switch", None),
|
||||||
|
name="fake_switch",
|
||||||
|
),
|
||||||
|
FritzDeviceCoverMock(
|
||||||
|
ain="fake ain cover",
|
||||||
|
device_and_unit_id=("fake ain cover", None),
|
||||||
|
name="fake_cover",
|
||||||
|
),
|
||||||
]
|
]
|
||||||
entry = MockConfigEntry(
|
entry = MockConfigEntry(
|
||||||
domain=FB_DOMAIN,
|
domain=FB_DOMAIN,
|
||||||
@ -101,7 +109,11 @@ async def test_coordinator_automatic_registry_cleanup(
|
|||||||
assert len(dr.async_entries_for_config_entry(device_registry, entry.entry_id)) == 2
|
assert len(dr.async_entries_for_config_entry(device_registry, entry.entry_id)) == 2
|
||||||
|
|
||||||
fritz().get_devices.return_value = [
|
fritz().get_devices.return_value = [
|
||||||
FritzDeviceSwitchMock(ain="fake ain switch", name="fake_switch")
|
FritzDeviceSwitchMock(
|
||||||
|
ain="fake ain switch",
|
||||||
|
device_and_unit_id=("fake ain switch", None),
|
||||||
|
name="fake_switch",
|
||||||
|
)
|
||||||
]
|
]
|
||||||
|
|
||||||
async_fire_time_changed(hass, utcnow() + timedelta(seconds=35))
|
async_fire_time_changed(hass, utcnow() + timedelta(seconds=35))
|
||||||
|
@ -108,6 +108,7 @@ async def test_discover_new_device(hass: HomeAssistant, fritz: Mock) -> None:
|
|||||||
|
|
||||||
new_device = FritzDeviceSensorMock()
|
new_device = FritzDeviceSensorMock()
|
||||||
new_device.ain = "7890 1234"
|
new_device.ain = "7890 1234"
|
||||||
|
new_device.device_and_unit_id = ("7890 1234", None)
|
||||||
new_device.name = "new_device"
|
new_device.name = "new_device"
|
||||||
set_devices(fritz, devices=[device, new_device])
|
set_devices(fritz, devices=[device, new_device])
|
||||||
|
|
||||||
|
@ -365,6 +365,7 @@ async def test_invalid_schemas() -> None:
|
|||||||
{"platform": "time_pattern", "minutes": "/"},
|
{"platform": "time_pattern", "minutes": "/"},
|
||||||
{"platform": "time_pattern", "minutes": "*/5"},
|
{"platform": "time_pattern", "minutes": "*/5"},
|
||||||
{"platform": "time_pattern", "minutes": "/90"},
|
{"platform": "time_pattern", "minutes": "/90"},
|
||||||
|
{"platform": "time_pattern", "hours": "/0", "minutes": 10},
|
||||||
{"platform": "time_pattern", "hours": 12, "minutes": 0, "seconds": 100},
|
{"platform": "time_pattern", "hours": 12, "minutes": 0, "seconds": 100},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -129,10 +129,6 @@ async def test_hap_reset_unloads_entry_if_setup(
|
|||||||
assert hass.data[HMIPC_DOMAIN] == {}
|
assert hass.data[HMIPC_DOMAIN] == {}
|
||||||
|
|
||||||
|
|
||||||
@patch(
|
|
||||||
"homeassistant.components.homematicip_cloud.hap.ConnectionContextBuilder.build_context_async",
|
|
||||||
return_value=ConnectionContext(),
|
|
||||||
)
|
|
||||||
async def test_hap_create(
|
async def test_hap_create(
|
||||||
hass: HomeAssistant, hmip_config_entry: MockConfigEntry, simple_mock_home
|
hass: HomeAssistant, hmip_config_entry: MockConfigEntry, simple_mock_home
|
||||||
) -> None:
|
) -> None:
|
||||||
@ -140,15 +136,17 @@ async def test_hap_create(
|
|||||||
hass.config.components.add(HMIPC_DOMAIN)
|
hass.config.components.add(HMIPC_DOMAIN)
|
||||||
hap = HomematicipHAP(hass, hmip_config_entry)
|
hap = HomematicipHAP(hass, hmip_config_entry)
|
||||||
assert hap
|
assert hap
|
||||||
with patch.object(hap, "async_connect"):
|
with (
|
||||||
|
patch(
|
||||||
|
"homeassistant.components.homematicip_cloud.hap.ConnectionContextBuilder.build_context_async",
|
||||||
|
return_value=ConnectionContext(),
|
||||||
|
),
|
||||||
|
patch.object(hap, "async_connect"),
|
||||||
|
):
|
||||||
async with hmip_config_entry.setup_lock:
|
async with hmip_config_entry.setup_lock:
|
||||||
assert await hap.async_setup()
|
assert await hap.async_setup()
|
||||||
|
|
||||||
|
|
||||||
@patch(
|
|
||||||
"homeassistant.components.homematicip_cloud.hap.ConnectionContextBuilder.build_context_async",
|
|
||||||
return_value=ConnectionContext(),
|
|
||||||
)
|
|
||||||
async def test_hap_create_exception(
|
async def test_hap_create_exception(
|
||||||
hass: HomeAssistant, hmip_config_entry: MockConfigEntry, mock_connection_init
|
hass: HomeAssistant, hmip_config_entry: MockConfigEntry, mock_connection_init
|
||||||
) -> None:
|
) -> None:
|
||||||
@ -158,13 +156,23 @@ async def test_hap_create_exception(
|
|||||||
hap = HomematicipHAP(hass, hmip_config_entry)
|
hap = HomematicipHAP(hass, hmip_config_entry)
|
||||||
assert hap
|
assert hap
|
||||||
|
|
||||||
with patch(
|
with (
|
||||||
"homeassistant.components.homematicip_cloud.hap.AsyncHome.get_current_state_async",
|
patch(
|
||||||
side_effect=Exception,
|
"homeassistant.components.homematicip_cloud.hap.ConnectionContextBuilder.build_context_async",
|
||||||
|
return_value=ConnectionContext(),
|
||||||
|
),
|
||||||
|
patch(
|
||||||
|
"homeassistant.components.homematicip_cloud.hap.AsyncHome.get_current_state_async",
|
||||||
|
side_effect=Exception,
|
||||||
|
),
|
||||||
):
|
):
|
||||||
assert not await hap.async_setup()
|
assert not await hap.async_setup()
|
||||||
|
|
||||||
with (
|
with (
|
||||||
|
patch(
|
||||||
|
"homeassistant.components.homematicip_cloud.hap.ConnectionContextBuilder.build_context_async",
|
||||||
|
return_value=ConnectionContext(),
|
||||||
|
),
|
||||||
patch(
|
patch(
|
||||||
"homeassistant.components.homematicip_cloud.hap.AsyncHome.get_current_state_async",
|
"homeassistant.components.homematicip_cloud.hap.AsyncHome.get_current_state_async",
|
||||||
side_effect=HmipConnectionError,
|
side_effect=HmipConnectionError,
|
||||||
|
@ -77,6 +77,7 @@ from homeassistant.helpers import (
|
|||||||
issue_registry as ir,
|
issue_registry as ir,
|
||||||
recorder as recorder_helper,
|
recorder as recorder_helper,
|
||||||
)
|
)
|
||||||
|
from homeassistant.helpers.event import async_track_entity_registry_updated_event
|
||||||
from homeassistant.helpers.typing import ConfigType
|
from homeassistant.helpers.typing import ConfigType
|
||||||
from homeassistant.setup import async_setup_component
|
from homeassistant.setup import async_setup_component
|
||||||
from homeassistant.util import dt as dt_util
|
from homeassistant.util import dt as dt_util
|
||||||
@ -2798,3 +2799,22 @@ async def test_empty_entity_id(
|
|||||||
hass.bus.async_fire("hello", {"entity_id": ""})
|
hass.bus.async_fire("hello", {"entity_id": ""})
|
||||||
await async_wait_recording_done(hass)
|
await async_wait_recording_done(hass)
|
||||||
assert "Invalid entity ID" not in caplog.text
|
assert "Invalid entity ID" not in caplog.text
|
||||||
|
|
||||||
|
|
||||||
|
async def test_setting_up_recorder_fails_entity_registry_listener(
|
||||||
|
hass: HomeAssistant, caplog: pytest.LogCaptureFixture
|
||||||
|
) -> None:
|
||||||
|
"""Test recorder setup fails if an entity registry listener is in place."""
|
||||||
|
async_track_entity_registry_updated_event(hass, "test.test", lambda x: x)
|
||||||
|
recorder_helper.async_initialize_recorder(hass)
|
||||||
|
with patch("homeassistant.components.recorder.ALLOW_IN_MEMORY_DB", True):
|
||||||
|
assert not await async_setup_component(
|
||||||
|
hass,
|
||||||
|
recorder.DOMAIN,
|
||||||
|
{recorder.DOMAIN: {recorder.CONF_DB_URL: "sqlite://"}},
|
||||||
|
)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
assert (
|
||||||
|
"The recorder entity registry listener must be installed before "
|
||||||
|
"async_track_entity_registry_updated_event is called" in caplog.text
|
||||||
|
)
|
||||||
|
@ -138,6 +138,8 @@ def reolink_connect_class() -> Generator[MagicMock]:
|
|||||||
host_mock.daynight_state.return_value = "Black&White"
|
host_mock.daynight_state.return_value = "Black&White"
|
||||||
host_mock.hub_alarm_tone_id.return_value = 1
|
host_mock.hub_alarm_tone_id.return_value = 1
|
||||||
host_mock.hub_visitor_tone_id.return_value = 1
|
host_mock.hub_visitor_tone_id.return_value = 1
|
||||||
|
host_mock.recording_packing_time_list = ["30 Minutes", "60 Minutes"]
|
||||||
|
host_mock.recording_packing_time = "60 Minutes"
|
||||||
|
|
||||||
# Baichuan
|
# Baichuan
|
||||||
host_mock.baichuan = create_autospec(Baichuan)
|
host_mock.baichuan = create_autospec(Baichuan)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user