updated apps

This commit is contained in:
2026-07-14 23:57:03 -04:00
parent 6cc7212cef
commit 010e828e9c
797 changed files with 45153 additions and 4246 deletions
+84 -85
View File
@@ -1,119 +1,118 @@
import logging
from awesomeversion import AwesomeVersion
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import (
CONF_DEVICE,
__version__ as HA_VERSION, # noqa: N812
)
from homeassistant.core import HomeAssistant
from homeassistant.const import CONF_DEVICE
from homeassistant.core import HomeAssistant, callback
from homeassistant.helpers import device_registry
from homeassistant.helpers.device_registry import DeviceEntry, DeviceInfo
from homeassistant.helpers.device import async_entity_id_to_device
from homeassistant.helpers.device_registry import DeviceEntry
from homeassistant.helpers.entity import Entity
import homeassistant.helpers.entity_registry as er
from homeassistant.helpers.entity_registry import RegistryEntry
from homeassistant.helpers.typing import ConfigType
from custom_components.powercalc.common import SourceEntity
from custom_components.powercalc.const import CONF_SENSOR_TYPE, SensorType
from custom_components.powercalc.sensors.abstract import BaseEntity
from custom_components.powercalc.const import CONF_AREA
_LOGGER = logging.getLogger(__name__)
async def attach_entities_to_source_device(
async def attach_entities_to_resolved_device(
config_entry: ConfigEntry | None,
entities_to_add: list[Entity],
hass: HomeAssistant,
source_entity: SourceEntity | None,
sensor_config: ConfigType | None = None,
) -> None:
"""Set the entity to same device as the source entity, if any available."""
device_entry = source_entity.device_entry if source_entity else None
if not device_entry and config_entry:
device_id = config_entry.data.get(CONF_DEVICE)
if device_id:
device_entry = device_registry.async_get(hass).async_get(device_id)
"""Set entities to the configured or source device, if any available."""
device_entry = get_device_entry(hass, sensor_config, source_entity, config_entry)
if not device_entry:
if config_entry:
sensor_type = SensorType(config_entry.data.get(CONF_SENSOR_TYPE, SensorType.VIRTUAL_POWER))
if sensor_type == SensorType.GROUP:
remove_stale_devices(hass, config_entry, None)
return
if config_entry:
bind_config_entry_to_device(hass, config_entry, device_entry)
for entity in (entity for entity in entities_to_add if isinstance(entity, BaseEntity)):
for entity in entities_to_add:
try:
if AwesomeVersion(HA_VERSION) >= AwesomeVersion("2025.8.0") and config_entry:
entity.device_entry = device_entry
else:
entity.source_device_id = device_entry.id # type: ignore
entity.device_entry = device_entry
except AttributeError: # pragma: no cover
_LOGGER.error("%s: Cannot set device id on entity", entity.entity_id)
def bind_config_entry_to_device(hass: HomeAssistant, config_entry: ConfigEntry, device_entry: DeviceEntry) -> None:
"""
When the user selected a specific device in the config flow, bind the config entry to that device
This will let HA bind all the powercalc entities for that config entry to the concerning device
"""
if config_entry.entry_id not in device_entry.config_entries:
device_reg = device_registry.async_get(hass)
device_reg.async_update_device(
device_entry.id,
add_config_entry_id=config_entry.entry_id,
)
remove_stale_devices(hass, config_entry, device_entry.id)
def remove_stale_devices(
def get_device_entry(
hass: HomeAssistant,
config_entry: ConfigEntry,
device_id: str | None,
) -> None:
"""Remove powercalc config entries from old devices."""
device_reg = device_registry.async_get(hass)
device_entries = device_registry.async_entries_for_config_entry(
device_reg,
config_entry.entry_id,
)
stale_devices = [device_entry for device_entry in device_entries if device_entry.id != device_id]
for device_entry in stale_devices:
device_reg.async_update_device(
device_entry.id,
remove_config_entry_id=config_entry.entry_id,
)
def get_device_info(
hass: HomeAssistant,
sensor_config: ConfigType,
source_entity: SourceEntity | None,
) -> DeviceInfo | None:
sensor_config: ConfigType | None = None,
source_entity: SourceEntity | None = None,
config_entry: ConfigEntry | None = None,
) -> DeviceEntry | None:
"""
Get device info for a given powercalc entity configuration.
Get device entry for a given powercalc entity configuration.
Prefer user configured device, when it is not set fallback to the same device as the source entity
"""
device_id = sensor_config.get(CONF_DEVICE)
device = None
device_id = None
if sensor_config is not None:
device_id = sensor_config.get(CONF_DEVICE)
if device_id is None and config_entry is not None:
device_id = config_entry.data.get(CONF_DEVICE)
if device_id is not None:
device_reg = device_registry.async_get(hass)
device = device_reg.async_get(device_id)
elif source_entity:
device = source_entity.device_entry
return device_registry.async_get(hass).async_get(device_id)
if device is None:
return None
if source_entity:
return source_entity.device_entry or async_entity_id_to_device(hass, source_entity.entity_id)
if not device.identifiers and not device.connections:
return None
return None
return DeviceInfo(
identifiers=device.identifiers,
connections=device.connections,
)
@callback
def bind_entity_to_registry_metadata(
hass: HomeAssistant,
entity_id: str | None,
device_entry: DeviceEntry | None,
sensor_config: ConfigType | None,
) -> None:
"""Bind a Powercalc entity to configured registry metadata."""
if entity_id is None:
return
entity_reg = er.async_get(hass)
entity_entry = entity_reg.async_get(entity_id)
if entity_entry is None:
return
bind_entity_to_device(entity_reg, entity_entry, device_entry)
bind_entity_to_area(entity_reg, entity_entry, sensor_config.get(CONF_AREA) if sensor_config else None)
@callback
def bind_entity_to_device(
entity_reg: er.EntityRegistry,
entity_entry: RegistryEntry,
device_entry: DeviceEntry | None,
) -> None:
"""Bind a Powercalc entity to the resolved device."""
# Home Assistant only consumes entity.device_entry while creating registry
# entries for config-entry platforms. YAML/platform entities need this
# registry update after they have been added.
if device_entry is None:
return
if entity_entry.config_entry_id is not None or entity_entry.device_id == device_entry.id:
return
_LOGGER.debug("Binding %s to device %s", entity_entry.entity_id, device_entry.id)
entity_reg.async_update_entity(entity_entry.entity_id, device_id=device_entry.id)
@callback
def bind_entity_to_area(
entity_reg: er.EntityRegistry,
entity_entry: RegistryEntry,
area_id: str | None,
) -> None:
"""Bind a Powercalc entity to the configured area."""
if not area_id:
return
if entity_entry.area_id == area_id:
return
_LOGGER.debug("Binding %s to area %s", entity_entry.entity_id, area_id)
entity_reg.async_update_entity(entity_entry.entity_id, area_id=area_id)