mirror of
				https://github.com/home-assistant/core.git
				synced 2025-11-04 00:19:31 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			1563 lines
		
	
	
		
			55 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			1563 lines
		
	
	
		
			55 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
"""Support for Enphase Envoy solar energy monitor."""
 | 
						|
 | 
						|
from __future__ import annotations
 | 
						|
 | 
						|
from collections.abc import Callable
 | 
						|
from dataclasses import dataclass, replace
 | 
						|
import datetime
 | 
						|
import logging
 | 
						|
from operator import attrgetter
 | 
						|
from typing import TYPE_CHECKING
 | 
						|
 | 
						|
from pyenphase import (
 | 
						|
    EnvoyACBPower,
 | 
						|
    EnvoyBatteryAggregate,
 | 
						|
    EnvoyC6CC,
 | 
						|
    EnvoyCollar,
 | 
						|
    EnvoyEncharge,
 | 
						|
    EnvoyEnchargeAggregate,
 | 
						|
    EnvoyEnchargePower,
 | 
						|
    EnvoyEnpower,
 | 
						|
    EnvoyInverter,
 | 
						|
    EnvoySystemConsumption,
 | 
						|
    EnvoySystemProduction,
 | 
						|
)
 | 
						|
from pyenphase.const import PHASENAMES
 | 
						|
from pyenphase.models.meters import (
 | 
						|
    CtMeterStatus,
 | 
						|
    CtState,
 | 
						|
    CtStatusFlags,
 | 
						|
    CtType,
 | 
						|
    EnvoyMeterData,
 | 
						|
)
 | 
						|
 | 
						|
from homeassistant.components.sensor import (
 | 
						|
    SensorDeviceClass,
 | 
						|
    SensorEntity,
 | 
						|
    SensorEntityDescription,
 | 
						|
    SensorStateClass,
 | 
						|
)
 | 
						|
from homeassistant.const import (
 | 
						|
    PERCENTAGE,
 | 
						|
    EntityCategory,
 | 
						|
    UnitOfApparentPower,
 | 
						|
    UnitOfElectricCurrent,
 | 
						|
    UnitOfElectricPotential,
 | 
						|
    UnitOfEnergy,
 | 
						|
    UnitOfFrequency,
 | 
						|
    UnitOfPower,
 | 
						|
    UnitOfTemperature,
 | 
						|
    UnitOfTime,
 | 
						|
)
 | 
						|
from homeassistant.core import HomeAssistant
 | 
						|
from homeassistant.helpers.device_registry import DeviceInfo
 | 
						|
from homeassistant.helpers.entity import Entity
 | 
						|
from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback
 | 
						|
from homeassistant.util import dt as dt_util
 | 
						|
 | 
						|
from .const import DOMAIN
 | 
						|
from .coordinator import EnphaseConfigEntry, EnphaseUpdateCoordinator
 | 
						|
from .entity import EnvoyBaseEntity
 | 
						|
 | 
						|
_LOGGER = logging.getLogger(__name__)
 | 
						|
 | 
						|
INVERTERS_KEY = "inverters"
 | 
						|
LAST_REPORTED_KEY = "last_reported"
 | 
						|
 | 
						|
PARALLEL_UPDATES = 0
 | 
						|
 | 
						|
 | 
						|
@dataclass(frozen=True, kw_only=True)
 | 
						|
class EnvoyInverterSensorEntityDescription(SensorEntityDescription):
 | 
						|
    """Describes an Envoy inverter sensor entity."""
 | 
						|
 | 
						|
    value_fn: Callable[[EnvoyInverter], datetime.datetime | float]
 | 
						|
 | 
						|
 | 
						|
INVERTER_SENSORS = (
 | 
						|
    EnvoyInverterSensorEntityDescription(
 | 
						|
        key=INVERTERS_KEY,
 | 
						|
        name=None,
 | 
						|
        native_unit_of_measurement=UnitOfPower.WATT,
 | 
						|
        state_class=SensorStateClass.MEASUREMENT,
 | 
						|
        device_class=SensorDeviceClass.POWER,
 | 
						|
        value_fn=attrgetter("last_report_watts"),
 | 
						|
    ),
 | 
						|
    EnvoyInverterSensorEntityDescription(
 | 
						|
        key="dc_voltage",
 | 
						|
        translation_key="dc_voltage",
 | 
						|
        native_unit_of_measurement=UnitOfElectricPotential.VOLT,
 | 
						|
        state_class=SensorStateClass.MEASUREMENT,
 | 
						|
        device_class=SensorDeviceClass.VOLTAGE,
 | 
						|
        suggested_display_precision=3,
 | 
						|
        entity_registry_enabled_default=False,
 | 
						|
        value_fn=attrgetter("dc_voltage"),
 | 
						|
    ),
 | 
						|
    EnvoyInverterSensorEntityDescription(
 | 
						|
        key="dc_current",
 | 
						|
        translation_key="dc_current",
 | 
						|
        native_unit_of_measurement=UnitOfElectricCurrent.AMPERE,
 | 
						|
        state_class=SensorStateClass.MEASUREMENT,
 | 
						|
        device_class=SensorDeviceClass.CURRENT,
 | 
						|
        suggested_display_precision=3,
 | 
						|
        entity_registry_enabled_default=False,
 | 
						|
        value_fn=attrgetter("dc_current"),
 | 
						|
    ),
 | 
						|
    EnvoyInverterSensorEntityDescription(
 | 
						|
        key="ac_voltage",
 | 
						|
        translation_key="ac_voltage",
 | 
						|
        native_unit_of_measurement=UnitOfElectricPotential.VOLT,
 | 
						|
        state_class=SensorStateClass.MEASUREMENT,
 | 
						|
        device_class=SensorDeviceClass.VOLTAGE,
 | 
						|
        suggested_display_precision=3,
 | 
						|
        entity_registry_enabled_default=False,
 | 
						|
        value_fn=attrgetter("ac_voltage"),
 | 
						|
    ),
 | 
						|
    EnvoyInverterSensorEntityDescription(
 | 
						|
        key="ac_current",
 | 
						|
        translation_key="ac_current",
 | 
						|
        native_unit_of_measurement=UnitOfElectricCurrent.AMPERE,
 | 
						|
        state_class=SensorStateClass.MEASUREMENT,
 | 
						|
        device_class=SensorDeviceClass.CURRENT,
 | 
						|
        suggested_display_precision=3,
 | 
						|
        entity_registry_enabled_default=False,
 | 
						|
        value_fn=attrgetter("ac_current"),
 | 
						|
    ),
 | 
						|
    EnvoyInverterSensorEntityDescription(
 | 
						|
        key="ac_frequency",
 | 
						|
        native_unit_of_measurement=UnitOfFrequency.HERTZ,
 | 
						|
        state_class=SensorStateClass.MEASUREMENT,
 | 
						|
        device_class=SensorDeviceClass.FREQUENCY,
 | 
						|
        suggested_display_precision=3,
 | 
						|
        entity_registry_enabled_default=False,
 | 
						|
        value_fn=attrgetter("ac_frequency"),
 | 
						|
    ),
 | 
						|
    EnvoyInverterSensorEntityDescription(
 | 
						|
        key="temperature",
 | 
						|
        native_unit_of_measurement=UnitOfTemperature.CELSIUS,
 | 
						|
        state_class=SensorStateClass.MEASUREMENT,
 | 
						|
        device_class=SensorDeviceClass.TEMPERATURE,
 | 
						|
        suggested_display_precision=3,
 | 
						|
        entity_registry_enabled_default=False,
 | 
						|
        entity_category=EntityCategory.DIAGNOSTIC,
 | 
						|
        value_fn=attrgetter("temperature"),
 | 
						|
    ),
 | 
						|
    EnvoyInverterSensorEntityDescription(
 | 
						|
        key="lifetime_energy",
 | 
						|
        translation_key="lifetime_energy",
 | 
						|
        native_unit_of_measurement=UnitOfEnergy.WATT_HOUR,
 | 
						|
        suggested_unit_of_measurement=UnitOfEnergy.KILO_WATT_HOUR,
 | 
						|
        state_class=SensorStateClass.TOTAL_INCREASING,
 | 
						|
        device_class=SensorDeviceClass.ENERGY,
 | 
						|
        entity_registry_enabled_default=False,
 | 
						|
        value_fn=attrgetter("lifetime_energy"),
 | 
						|
    ),
 | 
						|
    EnvoyInverterSensorEntityDescription(
 | 
						|
        key="energy_today",
 | 
						|
        translation_key="energy_today",
 | 
						|
        native_unit_of_measurement=UnitOfEnergy.WATT_HOUR,
 | 
						|
        state_class=SensorStateClass.TOTAL_INCREASING,
 | 
						|
        device_class=SensorDeviceClass.ENERGY,
 | 
						|
        entity_registry_enabled_default=False,
 | 
						|
        value_fn=attrgetter("energy_today"),
 | 
						|
    ),
 | 
						|
    EnvoyInverterSensorEntityDescription(
 | 
						|
        key="last_report_duration",
 | 
						|
        translation_key="last_report_duration",
 | 
						|
        native_unit_of_measurement=UnitOfTime.SECONDS,
 | 
						|
        state_class=SensorStateClass.MEASUREMENT,
 | 
						|
        device_class=SensorDeviceClass.DURATION,
 | 
						|
        entity_registry_enabled_default=False,
 | 
						|
        entity_category=EntityCategory.DIAGNOSTIC,
 | 
						|
        value_fn=attrgetter("last_report_duration"),
 | 
						|
    ),
 | 
						|
    EnvoyInverterSensorEntityDescription(
 | 
						|
        key="energy_produced",
 | 
						|
        translation_key="energy_produced",
 | 
						|
        native_unit_of_measurement=UnitOfEnergy.MILLIWATT_HOUR,
 | 
						|
        state_class=SensorStateClass.TOTAL,
 | 
						|
        device_class=SensorDeviceClass.ENERGY,
 | 
						|
        suggested_display_precision=3,
 | 
						|
        entity_registry_enabled_default=False,
 | 
						|
        value_fn=attrgetter("energy_produced"),
 | 
						|
    ),
 | 
						|
    EnvoyInverterSensorEntityDescription(
 | 
						|
        key="max_reported",
 | 
						|
        translation_key="max_reported",
 | 
						|
        native_unit_of_measurement=UnitOfPower.WATT,
 | 
						|
        state_class=SensorStateClass.MEASUREMENT,
 | 
						|
        device_class=SensorDeviceClass.POWER,
 | 
						|
        entity_registry_enabled_default=False,
 | 
						|
        entity_category=EntityCategory.DIAGNOSTIC,
 | 
						|
        value_fn=attrgetter("max_report_watts"),
 | 
						|
    ),
 | 
						|
    EnvoyInverterSensorEntityDescription(
 | 
						|
        key=LAST_REPORTED_KEY,
 | 
						|
        translation_key=LAST_REPORTED_KEY,
 | 
						|
        device_class=SensorDeviceClass.TIMESTAMP,
 | 
						|
        entity_registry_enabled_default=False,
 | 
						|
        value_fn=lambda inverter: dt_util.utc_from_timestamp(inverter.last_report_date),
 | 
						|
    ),
 | 
						|
)
 | 
						|
 | 
						|
 | 
						|
@dataclass(frozen=True, kw_only=True)
 | 
						|
class EnvoyProductionSensorEntityDescription(SensorEntityDescription):
 | 
						|
    """Describes an Envoy production sensor entity."""
 | 
						|
 | 
						|
    value_fn: Callable[[EnvoySystemProduction], int]
 | 
						|
    on_phase: str | None
 | 
						|
 | 
						|
 | 
						|
PRODUCTION_SENSORS = (
 | 
						|
    EnvoyProductionSensorEntityDescription(
 | 
						|
        key="production",
 | 
						|
        translation_key="current_power_production",
 | 
						|
        native_unit_of_measurement=UnitOfPower.WATT,
 | 
						|
        state_class=SensorStateClass.MEASUREMENT,
 | 
						|
        device_class=SensorDeviceClass.POWER,
 | 
						|
        suggested_unit_of_measurement=UnitOfPower.KILO_WATT,
 | 
						|
        suggested_display_precision=3,
 | 
						|
        value_fn=attrgetter("watts_now"),
 | 
						|
        on_phase=None,
 | 
						|
    ),
 | 
						|
    EnvoyProductionSensorEntityDescription(
 | 
						|
        key="daily_production",
 | 
						|
        translation_key="daily_production",
 | 
						|
        native_unit_of_measurement=UnitOfEnergy.WATT_HOUR,
 | 
						|
        state_class=SensorStateClass.TOTAL_INCREASING,
 | 
						|
        device_class=SensorDeviceClass.ENERGY,
 | 
						|
        suggested_unit_of_measurement=UnitOfEnergy.KILO_WATT_HOUR,
 | 
						|
        suggested_display_precision=2,
 | 
						|
        value_fn=attrgetter("watt_hours_today"),
 | 
						|
        on_phase=None,
 | 
						|
    ),
 | 
						|
    EnvoyProductionSensorEntityDescription(
 | 
						|
        key="seven_days_production",
 | 
						|
        translation_key="seven_days_production",
 | 
						|
        native_unit_of_measurement=UnitOfEnergy.WATT_HOUR,
 | 
						|
        device_class=SensorDeviceClass.ENERGY,
 | 
						|
        suggested_unit_of_measurement=UnitOfEnergy.KILO_WATT_HOUR,
 | 
						|
        suggested_display_precision=1,
 | 
						|
        value_fn=attrgetter("watt_hours_last_7_days"),
 | 
						|
        on_phase=None,
 | 
						|
    ),
 | 
						|
    EnvoyProductionSensorEntityDescription(
 | 
						|
        key="lifetime_production",
 | 
						|
        translation_key="lifetime_production",
 | 
						|
        native_unit_of_measurement=UnitOfEnergy.WATT_HOUR,
 | 
						|
        state_class=SensorStateClass.TOTAL_INCREASING,
 | 
						|
        device_class=SensorDeviceClass.ENERGY,
 | 
						|
        suggested_unit_of_measurement=UnitOfEnergy.MEGA_WATT_HOUR,
 | 
						|
        suggested_display_precision=3,
 | 
						|
        value_fn=attrgetter("watt_hours_lifetime"),
 | 
						|
        on_phase=None,
 | 
						|
    ),
 | 
						|
)
 | 
						|
 | 
						|
 | 
						|
PRODUCTION_PHASE_SENSORS = {
 | 
						|
    (on_phase := PHASENAMES[phase]): [
 | 
						|
        replace(
 | 
						|
            sensor,
 | 
						|
            key=f"{sensor.key}_l{phase + 1}",
 | 
						|
            translation_key=f"{sensor.translation_key}_phase",
 | 
						|
            entity_registry_enabled_default=False,
 | 
						|
            on_phase=on_phase,
 | 
						|
            translation_placeholders={"phase_name": f"l{phase + 1}"},
 | 
						|
        )
 | 
						|
        for sensor in list(PRODUCTION_SENSORS)
 | 
						|
    ]
 | 
						|
    for phase in range(3)
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
@dataclass(frozen=True, kw_only=True)
 | 
						|
class EnvoyConsumptionSensorEntityDescription(SensorEntityDescription):
 | 
						|
    """Describes an Envoy consumption sensor entity."""
 | 
						|
 | 
						|
    value_fn: Callable[[EnvoySystemConsumption], int]
 | 
						|
    on_phase: str | None
 | 
						|
 | 
						|
 | 
						|
CONSUMPTION_SENSORS = (
 | 
						|
    EnvoyConsumptionSensorEntityDescription(
 | 
						|
        key="consumption",
 | 
						|
        translation_key="current_power_consumption",
 | 
						|
        native_unit_of_measurement=UnitOfPower.WATT,
 | 
						|
        state_class=SensorStateClass.MEASUREMENT,
 | 
						|
        device_class=SensorDeviceClass.POWER,
 | 
						|
        suggested_unit_of_measurement=UnitOfPower.KILO_WATT,
 | 
						|
        suggested_display_precision=3,
 | 
						|
        value_fn=attrgetter("watts_now"),
 | 
						|
        on_phase=None,
 | 
						|
    ),
 | 
						|
    EnvoyConsumptionSensorEntityDescription(
 | 
						|
        key="daily_consumption",
 | 
						|
        translation_key="daily_consumption",
 | 
						|
        native_unit_of_measurement=UnitOfEnergy.WATT_HOUR,
 | 
						|
        state_class=SensorStateClass.TOTAL_INCREASING,
 | 
						|
        device_class=SensorDeviceClass.ENERGY,
 | 
						|
        suggested_unit_of_measurement=UnitOfEnergy.KILO_WATT_HOUR,
 | 
						|
        suggested_display_precision=2,
 | 
						|
        value_fn=attrgetter("watt_hours_today"),
 | 
						|
        on_phase=None,
 | 
						|
    ),
 | 
						|
    EnvoyConsumptionSensorEntityDescription(
 | 
						|
        key="seven_days_consumption",
 | 
						|
        translation_key="seven_days_consumption",
 | 
						|
        native_unit_of_measurement=UnitOfEnergy.WATT_HOUR,
 | 
						|
        device_class=SensorDeviceClass.ENERGY,
 | 
						|
        suggested_unit_of_measurement=UnitOfEnergy.KILO_WATT_HOUR,
 | 
						|
        suggested_display_precision=1,
 | 
						|
        value_fn=attrgetter("watt_hours_last_7_days"),
 | 
						|
        on_phase=None,
 | 
						|
    ),
 | 
						|
    EnvoyConsumptionSensorEntityDescription(
 | 
						|
        key="lifetime_consumption",
 | 
						|
        translation_key="lifetime_consumption",
 | 
						|
        native_unit_of_measurement=UnitOfEnergy.WATT_HOUR,
 | 
						|
        state_class=SensorStateClass.TOTAL_INCREASING,
 | 
						|
        device_class=SensorDeviceClass.ENERGY,
 | 
						|
        suggested_unit_of_measurement=UnitOfEnergy.MEGA_WATT_HOUR,
 | 
						|
        suggested_display_precision=3,
 | 
						|
        value_fn=attrgetter("watt_hours_lifetime"),
 | 
						|
        on_phase=None,
 | 
						|
    ),
 | 
						|
)
 | 
						|
 | 
						|
 | 
						|
CONSUMPTION_PHASE_SENSORS = {
 | 
						|
    (on_phase := PHASENAMES[phase]): [
 | 
						|
        replace(
 | 
						|
            sensor,
 | 
						|
            key=f"{sensor.key}_l{phase + 1}",
 | 
						|
            translation_key=f"{sensor.translation_key}_phase",
 | 
						|
            entity_registry_enabled_default=False,
 | 
						|
            on_phase=on_phase,
 | 
						|
            translation_placeholders={"phase_name": f"l{phase + 1}"},
 | 
						|
        )
 | 
						|
        for sensor in list(CONSUMPTION_SENSORS)
 | 
						|
    ]
 | 
						|
    for phase in range(3)
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
NET_CONSUMPTION_SENSORS = (
 | 
						|
    EnvoyConsumptionSensorEntityDescription(
 | 
						|
        key="balanced_net_consumption",
 | 
						|
        translation_key="balanced_net_consumption",
 | 
						|
        entity_registry_enabled_default=False,
 | 
						|
        native_unit_of_measurement=UnitOfPower.WATT,
 | 
						|
        state_class=SensorStateClass.MEASUREMENT,
 | 
						|
        device_class=SensorDeviceClass.POWER,
 | 
						|
        suggested_unit_of_measurement=UnitOfPower.KILO_WATT,
 | 
						|
        suggested_display_precision=3,
 | 
						|
        value_fn=attrgetter("watts_now"),
 | 
						|
        on_phase=None,
 | 
						|
    ),
 | 
						|
    EnvoyConsumptionSensorEntityDescription(
 | 
						|
        key="lifetime_balanced_net_consumption",
 | 
						|
        translation_key="lifetime_balanced_net_consumption",
 | 
						|
        entity_registry_enabled_default=False,
 | 
						|
        native_unit_of_measurement=UnitOfEnergy.WATT_HOUR,
 | 
						|
        state_class=SensorStateClass.TOTAL,
 | 
						|
        device_class=SensorDeviceClass.ENERGY,
 | 
						|
        suggested_unit_of_measurement=UnitOfEnergy.KILO_WATT_HOUR,
 | 
						|
        suggested_display_precision=3,
 | 
						|
        value_fn=attrgetter("watt_hours_lifetime"),
 | 
						|
        on_phase=None,
 | 
						|
    ),
 | 
						|
)
 | 
						|
 | 
						|
 | 
						|
NET_CONSUMPTION_PHASE_SENSORS = {
 | 
						|
    (on_phase := PHASENAMES[phase]): [
 | 
						|
        replace(
 | 
						|
            sensor,
 | 
						|
            key=f"{sensor.key}_l{phase + 1}",
 | 
						|
            translation_key=f"{sensor.translation_key}_phase",
 | 
						|
            entity_registry_enabled_default=False,
 | 
						|
            on_phase=on_phase,
 | 
						|
            translation_placeholders={"phase_name": f"l{phase + 1}"},
 | 
						|
        )
 | 
						|
        for sensor in list(NET_CONSUMPTION_SENSORS)
 | 
						|
    ]
 | 
						|
    for phase in range(3)
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
@dataclass(frozen=True, kw_only=True)
 | 
						|
class EnvoyCTSensorEntityDescription(SensorEntityDescription):
 | 
						|
    """Describes an Envoy CT sensor entity."""
 | 
						|
 | 
						|
    value_fn: Callable[
 | 
						|
        [EnvoyMeterData],
 | 
						|
        int | float | str | CtType | CtMeterStatus | CtStatusFlags | CtState | None,
 | 
						|
    ]
 | 
						|
    on_phase: str | None
 | 
						|
    cttype: str | None = None
 | 
						|
 | 
						|
 | 
						|
CT_NET_CONSUMPTION_SENSORS = (
 | 
						|
    EnvoyCTSensorEntityDescription(
 | 
						|
        key="lifetime_net_consumption",
 | 
						|
        translation_key="lifetime_net_consumption",
 | 
						|
        native_unit_of_measurement=UnitOfEnergy.WATT_HOUR,
 | 
						|
        state_class=SensorStateClass.TOTAL_INCREASING,
 | 
						|
        device_class=SensorDeviceClass.ENERGY,
 | 
						|
        suggested_unit_of_measurement=UnitOfEnergy.MEGA_WATT_HOUR,
 | 
						|
        suggested_display_precision=3,
 | 
						|
        value_fn=attrgetter("energy_delivered"),
 | 
						|
        on_phase=None,
 | 
						|
        cttype=CtType.NET_CONSUMPTION,
 | 
						|
    ),
 | 
						|
    EnvoyCTSensorEntityDescription(
 | 
						|
        key="lifetime_net_production",
 | 
						|
        translation_key="lifetime_net_production",
 | 
						|
        native_unit_of_measurement=UnitOfEnergy.WATT_HOUR,
 | 
						|
        state_class=SensorStateClass.TOTAL_INCREASING,
 | 
						|
        device_class=SensorDeviceClass.ENERGY,
 | 
						|
        suggested_unit_of_measurement=UnitOfEnergy.MEGA_WATT_HOUR,
 | 
						|
        suggested_display_precision=3,
 | 
						|
        value_fn=attrgetter("energy_received"),
 | 
						|
        on_phase=None,
 | 
						|
        cttype=CtType.NET_CONSUMPTION,
 | 
						|
    ),
 | 
						|
    EnvoyCTSensorEntityDescription(
 | 
						|
        key="net_consumption",
 | 
						|
        translation_key="net_consumption",
 | 
						|
        native_unit_of_measurement=UnitOfPower.WATT,
 | 
						|
        state_class=SensorStateClass.MEASUREMENT,
 | 
						|
        device_class=SensorDeviceClass.POWER,
 | 
						|
        suggested_unit_of_measurement=UnitOfPower.KILO_WATT,
 | 
						|
        suggested_display_precision=3,
 | 
						|
        value_fn=attrgetter("active_power"),
 | 
						|
        on_phase=None,
 | 
						|
        cttype=CtType.NET_CONSUMPTION,
 | 
						|
    ),
 | 
						|
    EnvoyCTSensorEntityDescription(
 | 
						|
        key="frequency",
 | 
						|
        translation_key="net_ct_frequency",
 | 
						|
        native_unit_of_measurement=UnitOfFrequency.HERTZ,
 | 
						|
        state_class=SensorStateClass.MEASUREMENT,
 | 
						|
        device_class=SensorDeviceClass.FREQUENCY,
 | 
						|
        suggested_display_precision=1,
 | 
						|
        entity_registry_enabled_default=False,
 | 
						|
        value_fn=attrgetter("frequency"),
 | 
						|
        on_phase=None,
 | 
						|
        cttype=CtType.NET_CONSUMPTION,
 | 
						|
    ),
 | 
						|
    EnvoyCTSensorEntityDescription(
 | 
						|
        key="voltage",
 | 
						|
        translation_key="net_ct_voltage",
 | 
						|
        native_unit_of_measurement=UnitOfElectricPotential.VOLT,
 | 
						|
        state_class=SensorStateClass.MEASUREMENT,
 | 
						|
        device_class=SensorDeviceClass.VOLTAGE,
 | 
						|
        suggested_unit_of_measurement=UnitOfElectricPotential.VOLT,
 | 
						|
        suggested_display_precision=1,
 | 
						|
        entity_registry_enabled_default=False,
 | 
						|
        value_fn=attrgetter("voltage"),
 | 
						|
        on_phase=None,
 | 
						|
        cttype=CtType.NET_CONSUMPTION,
 | 
						|
    ),
 | 
						|
    EnvoyCTSensorEntityDescription(
 | 
						|
        key="net_ct_current",
 | 
						|
        translation_key="net_ct_current",
 | 
						|
        native_unit_of_measurement=UnitOfElectricCurrent.AMPERE,
 | 
						|
        state_class=SensorStateClass.MEASUREMENT,
 | 
						|
        device_class=SensorDeviceClass.CURRENT,
 | 
						|
        suggested_unit_of_measurement=UnitOfElectricCurrent.AMPERE,
 | 
						|
        suggested_display_precision=3,
 | 
						|
        entity_registry_enabled_default=False,
 | 
						|
        value_fn=attrgetter("current"),
 | 
						|
        on_phase=None,
 | 
						|
        cttype=CtType.NET_CONSUMPTION,
 | 
						|
    ),
 | 
						|
    EnvoyCTSensorEntityDescription(
 | 
						|
        key="net_ct_powerfactor",
 | 
						|
        translation_key="net_ct_powerfactor",
 | 
						|
        device_class=SensorDeviceClass.POWER_FACTOR,
 | 
						|
        state_class=SensorStateClass.MEASUREMENT,
 | 
						|
        suggested_display_precision=2,
 | 
						|
        entity_registry_enabled_default=False,
 | 
						|
        value_fn=attrgetter("power_factor"),
 | 
						|
        on_phase=None,
 | 
						|
        cttype=CtType.NET_CONSUMPTION,
 | 
						|
    ),
 | 
						|
    EnvoyCTSensorEntityDescription(
 | 
						|
        key="net_consumption_ct_metering_status",
 | 
						|
        translation_key="net_ct_metering_status",
 | 
						|
        device_class=SensorDeviceClass.ENUM,
 | 
						|
        entity_category=EntityCategory.DIAGNOSTIC,
 | 
						|
        options=list(CtMeterStatus),
 | 
						|
        entity_registry_enabled_default=False,
 | 
						|
        value_fn=attrgetter("metering_status"),
 | 
						|
        on_phase=None,
 | 
						|
        cttype=CtType.NET_CONSUMPTION,
 | 
						|
    ),
 | 
						|
    EnvoyCTSensorEntityDescription(
 | 
						|
        key="net_consumption_ct_status_flags",
 | 
						|
        translation_key="net_ct_status_flags",
 | 
						|
        state_class=None,
 | 
						|
        entity_category=EntityCategory.DIAGNOSTIC,
 | 
						|
        entity_registry_enabled_default=False,
 | 
						|
        value_fn=lambda ct: 0 if ct.status_flags is None else len(ct.status_flags),
 | 
						|
        on_phase=None,
 | 
						|
        cttype=CtType.NET_CONSUMPTION,
 | 
						|
    ),
 | 
						|
)
 | 
						|
 | 
						|
 | 
						|
CT_NET_CONSUMPTION_PHASE_SENSORS = {
 | 
						|
    (on_phase := PHASENAMES[phase]): [
 | 
						|
        replace(
 | 
						|
            sensor,
 | 
						|
            key=f"{sensor.key}_l{phase + 1}",
 | 
						|
            translation_key=f"{sensor.translation_key}_phase",
 | 
						|
            entity_registry_enabled_default=False,
 | 
						|
            on_phase=on_phase,
 | 
						|
            translation_placeholders={"phase_name": f"l{phase + 1}"},
 | 
						|
        )
 | 
						|
        for sensor in list(CT_NET_CONSUMPTION_SENSORS)
 | 
						|
    ]
 | 
						|
    for phase in range(3)
 | 
						|
}
 | 
						|
 | 
						|
CT_PRODUCTION_SENSORS = (
 | 
						|
    EnvoyCTSensorEntityDescription(
 | 
						|
        key="production_ct_frequency",
 | 
						|
        translation_key="production_ct_frequency",
 | 
						|
        native_unit_of_measurement=UnitOfFrequency.HERTZ,
 | 
						|
        state_class=SensorStateClass.MEASUREMENT,
 | 
						|
        device_class=SensorDeviceClass.FREQUENCY,
 | 
						|
        suggested_display_precision=1,
 | 
						|
        entity_registry_enabled_default=False,
 | 
						|
        value_fn=attrgetter("frequency"),
 | 
						|
        on_phase=None,
 | 
						|
        cttype=CtType.PRODUCTION,
 | 
						|
    ),
 | 
						|
    EnvoyCTSensorEntityDescription(
 | 
						|
        key="production_ct_voltage",
 | 
						|
        translation_key="production_ct_voltage",
 | 
						|
        native_unit_of_measurement=UnitOfElectricPotential.VOLT,
 | 
						|
        state_class=SensorStateClass.MEASUREMENT,
 | 
						|
        device_class=SensorDeviceClass.VOLTAGE,
 | 
						|
        suggested_unit_of_measurement=UnitOfElectricPotential.VOLT,
 | 
						|
        suggested_display_precision=1,
 | 
						|
        entity_registry_enabled_default=False,
 | 
						|
        value_fn=attrgetter("voltage"),
 | 
						|
        on_phase=None,
 | 
						|
        cttype=CtType.PRODUCTION,
 | 
						|
    ),
 | 
						|
    EnvoyCTSensorEntityDescription(
 | 
						|
        key="production_ct_current",
 | 
						|
        translation_key="production_ct_current",
 | 
						|
        native_unit_of_measurement=UnitOfElectricCurrent.AMPERE,
 | 
						|
        state_class=SensorStateClass.MEASUREMENT,
 | 
						|
        device_class=SensorDeviceClass.CURRENT,
 | 
						|
        suggested_unit_of_measurement=UnitOfElectricCurrent.AMPERE,
 | 
						|
        suggested_display_precision=3,
 | 
						|
        entity_registry_enabled_default=False,
 | 
						|
        value_fn=attrgetter("current"),
 | 
						|
        on_phase=None,
 | 
						|
        cttype=CtType.PRODUCTION,
 | 
						|
    ),
 | 
						|
    EnvoyCTSensorEntityDescription(
 | 
						|
        key="production_ct_powerfactor",
 | 
						|
        translation_key="production_ct_powerfactor",
 | 
						|
        device_class=SensorDeviceClass.POWER_FACTOR,
 | 
						|
        state_class=SensorStateClass.MEASUREMENT,
 | 
						|
        suggested_display_precision=2,
 | 
						|
        entity_registry_enabled_default=False,
 | 
						|
        value_fn=attrgetter("power_factor"),
 | 
						|
        on_phase=None,
 | 
						|
        cttype=CtType.PRODUCTION,
 | 
						|
    ),
 | 
						|
    EnvoyCTSensorEntityDescription(
 | 
						|
        key="production_ct_metering_status",
 | 
						|
        translation_key="production_ct_metering_status",
 | 
						|
        device_class=SensorDeviceClass.ENUM,
 | 
						|
        options=list(CtMeterStatus),
 | 
						|
        entity_category=EntityCategory.DIAGNOSTIC,
 | 
						|
        entity_registry_enabled_default=False,
 | 
						|
        value_fn=attrgetter("metering_status"),
 | 
						|
        on_phase=None,
 | 
						|
        cttype=CtType.PRODUCTION,
 | 
						|
    ),
 | 
						|
    EnvoyCTSensorEntityDescription(
 | 
						|
        key="production_ct_status_flags",
 | 
						|
        translation_key="production_ct_status_flags",
 | 
						|
        state_class=None,
 | 
						|
        entity_category=EntityCategory.DIAGNOSTIC,
 | 
						|
        entity_registry_enabled_default=False,
 | 
						|
        value_fn=lambda ct: 0 if ct.status_flags is None else len(ct.status_flags),
 | 
						|
        on_phase=None,
 | 
						|
        cttype=CtType.PRODUCTION,
 | 
						|
    ),
 | 
						|
)
 | 
						|
 | 
						|
CT_PRODUCTION_PHASE_SENSORS = {
 | 
						|
    (on_phase := PHASENAMES[phase]): [
 | 
						|
        replace(
 | 
						|
            sensor,
 | 
						|
            key=f"{sensor.key}_l{phase + 1}",
 | 
						|
            translation_key=f"{sensor.translation_key}_phase",
 | 
						|
            entity_registry_enabled_default=False,
 | 
						|
            on_phase=on_phase,
 | 
						|
            translation_placeholders={"phase_name": f"l{phase + 1}"},
 | 
						|
        )
 | 
						|
        for sensor in list(CT_PRODUCTION_SENSORS)
 | 
						|
    ]
 | 
						|
    for phase in range(3)
 | 
						|
}
 | 
						|
 | 
						|
CT_STORAGE_SENSORS = (
 | 
						|
    EnvoyCTSensorEntityDescription(
 | 
						|
        key="lifetime_battery_discharged",
 | 
						|
        translation_key="lifetime_battery_discharged",
 | 
						|
        native_unit_of_measurement=UnitOfEnergy.WATT_HOUR,
 | 
						|
        state_class=SensorStateClass.TOTAL_INCREASING,
 | 
						|
        device_class=SensorDeviceClass.ENERGY,
 | 
						|
        suggested_unit_of_measurement=UnitOfEnergy.MEGA_WATT_HOUR,
 | 
						|
        suggested_display_precision=3,
 | 
						|
        value_fn=attrgetter("energy_delivered"),
 | 
						|
        on_phase=None,
 | 
						|
        cttype=CtType.STORAGE,
 | 
						|
    ),
 | 
						|
    EnvoyCTSensorEntityDescription(
 | 
						|
        key="lifetime_battery_charged",
 | 
						|
        translation_key="lifetime_battery_charged",
 | 
						|
        native_unit_of_measurement=UnitOfEnergy.WATT_HOUR,
 | 
						|
        state_class=SensorStateClass.TOTAL_INCREASING,
 | 
						|
        device_class=SensorDeviceClass.ENERGY,
 | 
						|
        suggested_unit_of_measurement=UnitOfEnergy.MEGA_WATT_HOUR,
 | 
						|
        suggested_display_precision=3,
 | 
						|
        value_fn=attrgetter("energy_received"),
 | 
						|
        on_phase=None,
 | 
						|
        cttype=CtType.STORAGE,
 | 
						|
    ),
 | 
						|
    EnvoyCTSensorEntityDescription(
 | 
						|
        key="battery_discharge",
 | 
						|
        translation_key="battery_discharge",
 | 
						|
        native_unit_of_measurement=UnitOfPower.WATT,
 | 
						|
        state_class=SensorStateClass.MEASUREMENT,
 | 
						|
        device_class=SensorDeviceClass.POWER,
 | 
						|
        suggested_unit_of_measurement=UnitOfPower.KILO_WATT,
 | 
						|
        suggested_display_precision=3,
 | 
						|
        value_fn=attrgetter("active_power"),
 | 
						|
        on_phase=None,
 | 
						|
        cttype=CtType.STORAGE,
 | 
						|
    ),
 | 
						|
    EnvoyCTSensorEntityDescription(
 | 
						|
        key="storage_ct_frequency",
 | 
						|
        translation_key="storage_ct_frequency",
 | 
						|
        native_unit_of_measurement=UnitOfFrequency.HERTZ,
 | 
						|
        state_class=SensorStateClass.MEASUREMENT,
 | 
						|
        device_class=SensorDeviceClass.FREQUENCY,
 | 
						|
        suggested_display_precision=1,
 | 
						|
        entity_registry_enabled_default=False,
 | 
						|
        value_fn=attrgetter("frequency"),
 | 
						|
        on_phase=None,
 | 
						|
        cttype=CtType.STORAGE,
 | 
						|
    ),
 | 
						|
    EnvoyCTSensorEntityDescription(
 | 
						|
        key="storage_voltage",
 | 
						|
        translation_key="storage_ct_voltage",
 | 
						|
        native_unit_of_measurement=UnitOfElectricPotential.VOLT,
 | 
						|
        state_class=SensorStateClass.MEASUREMENT,
 | 
						|
        device_class=SensorDeviceClass.VOLTAGE,
 | 
						|
        suggested_unit_of_measurement=UnitOfElectricPotential.VOLT,
 | 
						|
        suggested_display_precision=1,
 | 
						|
        entity_registry_enabled_default=False,
 | 
						|
        value_fn=attrgetter("voltage"),
 | 
						|
        on_phase=None,
 | 
						|
        cttype=CtType.STORAGE,
 | 
						|
    ),
 | 
						|
    EnvoyCTSensorEntityDescription(
 | 
						|
        key="storage_ct_current",
 | 
						|
        translation_key="storage_ct_current",
 | 
						|
        native_unit_of_measurement=UnitOfElectricCurrent.AMPERE,
 | 
						|
        state_class=SensorStateClass.MEASUREMENT,
 | 
						|
        device_class=SensorDeviceClass.CURRENT,
 | 
						|
        suggested_unit_of_measurement=UnitOfElectricCurrent.AMPERE,
 | 
						|
        suggested_display_precision=3,
 | 
						|
        entity_registry_enabled_default=False,
 | 
						|
        value_fn=attrgetter("current"),
 | 
						|
        on_phase=None,
 | 
						|
        cttype=CtType.STORAGE,
 | 
						|
    ),
 | 
						|
    EnvoyCTSensorEntityDescription(
 | 
						|
        key="storage_ct_powerfactor",
 | 
						|
        translation_key="storage_ct_powerfactor",
 | 
						|
        device_class=SensorDeviceClass.POWER_FACTOR,
 | 
						|
        state_class=SensorStateClass.MEASUREMENT,
 | 
						|
        suggested_display_precision=2,
 | 
						|
        entity_registry_enabled_default=False,
 | 
						|
        value_fn=attrgetter("power_factor"),
 | 
						|
        on_phase=None,
 | 
						|
        cttype=CtType.STORAGE,
 | 
						|
    ),
 | 
						|
    EnvoyCTSensorEntityDescription(
 | 
						|
        key="storage_ct_metering_status",
 | 
						|
        translation_key="storage_ct_metering_status",
 | 
						|
        device_class=SensorDeviceClass.ENUM,
 | 
						|
        options=list(CtMeterStatus),
 | 
						|
        entity_category=EntityCategory.DIAGNOSTIC,
 | 
						|
        entity_registry_enabled_default=False,
 | 
						|
        value_fn=attrgetter("metering_status"),
 | 
						|
        on_phase=None,
 | 
						|
        cttype=CtType.STORAGE,
 | 
						|
    ),
 | 
						|
    EnvoyCTSensorEntityDescription(
 | 
						|
        key="storage_ct_status_flags",
 | 
						|
        translation_key="storage_ct_status_flags",
 | 
						|
        state_class=None,
 | 
						|
        entity_category=EntityCategory.DIAGNOSTIC,
 | 
						|
        entity_registry_enabled_default=False,
 | 
						|
        value_fn=lambda ct: 0 if ct.status_flags is None else len(ct.status_flags),
 | 
						|
        on_phase=None,
 | 
						|
        cttype=CtType.STORAGE,
 | 
						|
    ),
 | 
						|
)
 | 
						|
 | 
						|
 | 
						|
CT_STORAGE_PHASE_SENSORS = {
 | 
						|
    (on_phase := PHASENAMES[phase]): [
 | 
						|
        replace(
 | 
						|
            sensor,
 | 
						|
            key=f"{sensor.key}_l{phase + 1}",
 | 
						|
            translation_key=f"{sensor.translation_key}_phase",
 | 
						|
            entity_registry_enabled_default=False,
 | 
						|
            on_phase=on_phase,
 | 
						|
            translation_placeholders={"phase_name": f"l{phase + 1}"},
 | 
						|
        )
 | 
						|
        for sensor in list(CT_STORAGE_SENSORS)
 | 
						|
    ]
 | 
						|
    for phase in range(3)
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
@dataclass(frozen=True, kw_only=True)
 | 
						|
class EnvoyEnchargeSensorEntityDescription(SensorEntityDescription):
 | 
						|
    """Describes an Envoy Encharge sensor entity."""
 | 
						|
 | 
						|
    value_fn: Callable[[EnvoyEncharge], datetime.datetime | int | float]
 | 
						|
 | 
						|
 | 
						|
@dataclass(frozen=True)
 | 
						|
class EnvoyEnchargePowerRequiredKeysMixin:
 | 
						|
    """Mixin for required keys."""
 | 
						|
 | 
						|
 | 
						|
@dataclass(frozen=True, kw_only=True)
 | 
						|
class EnvoyEnchargePowerSensorEntityDescription(SensorEntityDescription):
 | 
						|
    """Describes an Envoy Encharge sensor entity."""
 | 
						|
 | 
						|
    value_fn: Callable[[EnvoyEnchargePower], int | float]
 | 
						|
 | 
						|
 | 
						|
ENCHARGE_INVENTORY_SENSORS = (
 | 
						|
    EnvoyEnchargeSensorEntityDescription(
 | 
						|
        key="temperature",
 | 
						|
        native_unit_of_measurement=UnitOfTemperature.CELSIUS,
 | 
						|
        device_class=SensorDeviceClass.TEMPERATURE,
 | 
						|
        value_fn=attrgetter("temperature"),
 | 
						|
    ),
 | 
						|
    EnvoyEnchargeSensorEntityDescription(
 | 
						|
        key=LAST_REPORTED_KEY,
 | 
						|
        translation_key=LAST_REPORTED_KEY,
 | 
						|
        native_unit_of_measurement=None,
 | 
						|
        device_class=SensorDeviceClass.TIMESTAMP,
 | 
						|
        value_fn=lambda encharge: dt_util.utc_from_timestamp(encharge.last_report_date),
 | 
						|
    ),
 | 
						|
)
 | 
						|
ENCHARGE_POWER_SENSORS = (
 | 
						|
    EnvoyEnchargePowerSensorEntityDescription(
 | 
						|
        key="soc",
 | 
						|
        native_unit_of_measurement=PERCENTAGE,
 | 
						|
        device_class=SensorDeviceClass.BATTERY,
 | 
						|
        value_fn=attrgetter("soc"),
 | 
						|
    ),
 | 
						|
    EnvoyEnchargePowerSensorEntityDescription(
 | 
						|
        key="apparent_power_mva",
 | 
						|
        native_unit_of_measurement=UnitOfApparentPower.VOLT_AMPERE,
 | 
						|
        device_class=SensorDeviceClass.APPARENT_POWER,
 | 
						|
        value_fn=lambda encharge: encharge.apparent_power_mva * 0.001,
 | 
						|
    ),
 | 
						|
    EnvoyEnchargePowerSensorEntityDescription(
 | 
						|
        key="real_power_mw",
 | 
						|
        native_unit_of_measurement=UnitOfPower.WATT,
 | 
						|
        device_class=SensorDeviceClass.POWER,
 | 
						|
        value_fn=lambda encharge: encharge.real_power_mw * 0.001,
 | 
						|
    ),
 | 
						|
)
 | 
						|
 | 
						|
 | 
						|
@dataclass(frozen=True, kw_only=True)
 | 
						|
class EnvoyEnpowerSensorEntityDescription(SensorEntityDescription):
 | 
						|
    """Describes an Envoy Encharge sensor entity."""
 | 
						|
 | 
						|
    value_fn: Callable[[EnvoyEnpower], datetime.datetime | int | float]
 | 
						|
 | 
						|
 | 
						|
ENPOWER_SENSORS = (
 | 
						|
    EnvoyEnpowerSensorEntityDescription(
 | 
						|
        key="temperature",
 | 
						|
        native_unit_of_measurement=UnitOfTemperature.FAHRENHEIT,
 | 
						|
        device_class=SensorDeviceClass.TEMPERATURE,
 | 
						|
        value_fn=attrgetter("temperature"),
 | 
						|
    ),
 | 
						|
    EnvoyEnpowerSensorEntityDescription(
 | 
						|
        key=LAST_REPORTED_KEY,
 | 
						|
        translation_key=LAST_REPORTED_KEY,
 | 
						|
        device_class=SensorDeviceClass.TIMESTAMP,
 | 
						|
        value_fn=lambda enpower: dt_util.utc_from_timestamp(enpower.last_report_date),
 | 
						|
    ),
 | 
						|
)
 | 
						|
 | 
						|
 | 
						|
@dataclass(frozen=True, kw_only=True)
 | 
						|
class EnvoyCollarSensorEntityDescription(SensorEntityDescription):
 | 
						|
    """Describes an Envoy Collar sensor entity."""
 | 
						|
 | 
						|
    value_fn: Callable[[EnvoyCollar], datetime.datetime | int | float | str]
 | 
						|
 | 
						|
 | 
						|
COLLAR_SENSORS = (
 | 
						|
    EnvoyCollarSensorEntityDescription(
 | 
						|
        key="temperature",
 | 
						|
        native_unit_of_measurement=UnitOfTemperature.CELSIUS,
 | 
						|
        device_class=SensorDeviceClass.TEMPERATURE,
 | 
						|
        value_fn=attrgetter("temperature"),
 | 
						|
    ),
 | 
						|
    EnvoyCollarSensorEntityDescription(
 | 
						|
        key=LAST_REPORTED_KEY,
 | 
						|
        translation_key=LAST_REPORTED_KEY,
 | 
						|
        native_unit_of_measurement=None,
 | 
						|
        device_class=SensorDeviceClass.TIMESTAMP,
 | 
						|
        value_fn=lambda collar: dt_util.utc_from_timestamp(collar.last_report_date),
 | 
						|
    ),
 | 
						|
    EnvoyCollarSensorEntityDescription(
 | 
						|
        key="grid_state",
 | 
						|
        translation_key="grid_status",
 | 
						|
        value_fn=lambda collar: collar.grid_state,
 | 
						|
    ),
 | 
						|
    EnvoyCollarSensorEntityDescription(
 | 
						|
        key="mid_state",
 | 
						|
        translation_key="mid_state",
 | 
						|
        value_fn=lambda collar: collar.mid_state,
 | 
						|
    ),
 | 
						|
)
 | 
						|
 | 
						|
 | 
						|
@dataclass(frozen=True, kw_only=True)
 | 
						|
class EnvoyC6CCSensorEntityDescription(SensorEntityDescription):
 | 
						|
    """Describes an Envoy C6 Combiner controller sensor entity."""
 | 
						|
 | 
						|
    value_fn: Callable[[EnvoyC6CC], datetime.datetime]
 | 
						|
 | 
						|
 | 
						|
C6CC_SENSORS = (
 | 
						|
    EnvoyC6CCSensorEntityDescription(
 | 
						|
        key=LAST_REPORTED_KEY,
 | 
						|
        translation_key=LAST_REPORTED_KEY,
 | 
						|
        native_unit_of_measurement=None,
 | 
						|
        device_class=SensorDeviceClass.TIMESTAMP,
 | 
						|
        value_fn=lambda c6cc: dt_util.utc_from_timestamp(c6cc.last_report_date),
 | 
						|
    ),
 | 
						|
)
 | 
						|
 | 
						|
 | 
						|
@dataclass(frozen=True)
 | 
						|
class EnvoyEnchargeAggregateRequiredKeysMixin:
 | 
						|
    """Mixin for required keys."""
 | 
						|
 | 
						|
 | 
						|
@dataclass(frozen=True, kw_only=True)
 | 
						|
class EnvoyEnchargeAggregateSensorEntityDescription(SensorEntityDescription):
 | 
						|
    """Describes an Envoy Encharge sensor entity."""
 | 
						|
 | 
						|
    value_fn: Callable[[EnvoyEnchargeAggregate], int]
 | 
						|
 | 
						|
 | 
						|
ENCHARGE_AGGREGATE_SENSORS = (
 | 
						|
    EnvoyEnchargeAggregateSensorEntityDescription(
 | 
						|
        key="battery_level",
 | 
						|
        native_unit_of_measurement=PERCENTAGE,
 | 
						|
        device_class=SensorDeviceClass.BATTERY,
 | 
						|
        value_fn=attrgetter("state_of_charge"),
 | 
						|
    ),
 | 
						|
    EnvoyEnchargeAggregateSensorEntityDescription(
 | 
						|
        key="reserve_soc",
 | 
						|
        translation_key="reserve_soc",
 | 
						|
        native_unit_of_measurement=PERCENTAGE,
 | 
						|
        device_class=SensorDeviceClass.BATTERY,
 | 
						|
        value_fn=attrgetter("reserve_state_of_charge"),
 | 
						|
    ),
 | 
						|
    EnvoyEnchargeAggregateSensorEntityDescription(
 | 
						|
        key="available_energy",
 | 
						|
        translation_key="available_energy",
 | 
						|
        native_unit_of_measurement=UnitOfEnergy.WATT_HOUR,
 | 
						|
        device_class=SensorDeviceClass.ENERGY,
 | 
						|
        value_fn=attrgetter("available_energy"),
 | 
						|
    ),
 | 
						|
    EnvoyEnchargeAggregateSensorEntityDescription(
 | 
						|
        key="reserve_energy",
 | 
						|
        translation_key="reserve_energy",
 | 
						|
        native_unit_of_measurement=UnitOfEnergy.WATT_HOUR,
 | 
						|
        device_class=SensorDeviceClass.ENERGY,
 | 
						|
        value_fn=attrgetter("backup_reserve"),
 | 
						|
    ),
 | 
						|
    EnvoyEnchargeAggregateSensorEntityDescription(
 | 
						|
        key="max_capacity",
 | 
						|
        translation_key="max_capacity",
 | 
						|
        native_unit_of_measurement=UnitOfEnergy.WATT_HOUR,
 | 
						|
        device_class=SensorDeviceClass.ENERGY,
 | 
						|
        value_fn=attrgetter("max_available_capacity"),
 | 
						|
    ),
 | 
						|
)
 | 
						|
 | 
						|
 | 
						|
@dataclass(frozen=True, kw_only=True)
 | 
						|
class EnvoyAcbBatterySensorEntityDescription(SensorEntityDescription):
 | 
						|
    """Describes an Envoy ACB Battery sensor entity."""
 | 
						|
 | 
						|
    value_fn: Callable[[EnvoyACBPower], int | str]
 | 
						|
 | 
						|
 | 
						|
ACB_BATTERY_POWER_SENSORS = (
 | 
						|
    EnvoyAcbBatterySensorEntityDescription(
 | 
						|
        key="acb_power",
 | 
						|
        native_unit_of_measurement=UnitOfPower.WATT,
 | 
						|
        device_class=SensorDeviceClass.POWER,
 | 
						|
        value_fn=attrgetter("power"),
 | 
						|
    ),
 | 
						|
    EnvoyAcbBatterySensorEntityDescription(
 | 
						|
        key="acb_soc",
 | 
						|
        native_unit_of_measurement=PERCENTAGE,
 | 
						|
        device_class=SensorDeviceClass.BATTERY,
 | 
						|
        value_fn=attrgetter("state_of_charge"),
 | 
						|
    ),
 | 
						|
    EnvoyAcbBatterySensorEntityDescription(
 | 
						|
        key="acb_battery_state",
 | 
						|
        translation_key="acb_battery_state",
 | 
						|
        device_class=SensorDeviceClass.ENUM,
 | 
						|
        options=["discharging", "idle", "charging", "full"],
 | 
						|
        value_fn=attrgetter("state"),
 | 
						|
    ),
 | 
						|
)
 | 
						|
 | 
						|
ACB_BATTERY_ENERGY_SENSORS = (
 | 
						|
    EnvoyAcbBatterySensorEntityDescription(
 | 
						|
        key="acb_available_energy",
 | 
						|
        translation_key="acb_available_energy",
 | 
						|
        native_unit_of_measurement=UnitOfEnergy.WATT_HOUR,
 | 
						|
        device_class=SensorDeviceClass.ENERGY_STORAGE,
 | 
						|
        value_fn=attrgetter("charge_wh"),
 | 
						|
    ),
 | 
						|
)
 | 
						|
 | 
						|
 | 
						|
@dataclass(frozen=True, kw_only=True)
 | 
						|
class EnvoyAggregateBatterySensorEntityDescription(SensorEntityDescription):
 | 
						|
    """Describes an Envoy aggregate Ensemble and ACB Battery sensor entity."""
 | 
						|
 | 
						|
    value_fn: Callable[[EnvoyBatteryAggregate], int]
 | 
						|
 | 
						|
 | 
						|
AGGREGATE_BATTERY_SENSORS = (
 | 
						|
    EnvoyAggregateBatterySensorEntityDescription(
 | 
						|
        key="aggregated_soc",
 | 
						|
        translation_key="aggregated_soc",
 | 
						|
        native_unit_of_measurement=PERCENTAGE,
 | 
						|
        device_class=SensorDeviceClass.BATTERY,
 | 
						|
        value_fn=attrgetter("state_of_charge"),
 | 
						|
    ),
 | 
						|
    EnvoyAggregateBatterySensorEntityDescription(
 | 
						|
        key="aggregated_available_energy",
 | 
						|
        translation_key="aggregated_available_energy",
 | 
						|
        native_unit_of_measurement=UnitOfEnergy.WATT_HOUR,
 | 
						|
        device_class=SensorDeviceClass.ENERGY_STORAGE,
 | 
						|
        value_fn=attrgetter("available_energy"),
 | 
						|
    ),
 | 
						|
    EnvoyAggregateBatterySensorEntityDescription(
 | 
						|
        key="aggregated_max_battery_capacity",
 | 
						|
        translation_key="aggregated_max_capacity",
 | 
						|
        native_unit_of_measurement=UnitOfEnergy.WATT_HOUR,
 | 
						|
        device_class=SensorDeviceClass.ENERGY_STORAGE,
 | 
						|
        value_fn=attrgetter("max_available_capacity"),
 | 
						|
    ),
 | 
						|
)
 | 
						|
 | 
						|
 | 
						|
async def async_setup_entry(
 | 
						|
    hass: HomeAssistant,
 | 
						|
    config_entry: EnphaseConfigEntry,
 | 
						|
    async_add_entities: AddConfigEntryEntitiesCallback,
 | 
						|
) -> None:
 | 
						|
    """Set up envoy sensor platform."""
 | 
						|
    coordinator = config_entry.runtime_data
 | 
						|
    envoy_data = coordinator.envoy.data
 | 
						|
    assert envoy_data is not None
 | 
						|
    _LOGGER.debug("Envoy data: %s", envoy_data)
 | 
						|
 | 
						|
    entities: list[Entity] = [
 | 
						|
        EnvoyProductionEntity(coordinator, description)
 | 
						|
        for description in PRODUCTION_SENSORS
 | 
						|
    ]
 | 
						|
    if envoy_data.system_consumption:
 | 
						|
        entities.extend(
 | 
						|
            EnvoyConsumptionEntity(coordinator, description)
 | 
						|
            for description in CONSUMPTION_SENSORS
 | 
						|
        )
 | 
						|
    if envoy_data.system_net_consumption:
 | 
						|
        entities.extend(
 | 
						|
            EnvoyNetConsumptionEntity(coordinator, description)
 | 
						|
            for description in NET_CONSUMPTION_SENSORS
 | 
						|
        )
 | 
						|
    # For each production phase reported add production entities
 | 
						|
    if envoy_data.system_production_phases:
 | 
						|
        entities.extend(
 | 
						|
            EnvoyProductionPhaseEntity(coordinator, description)
 | 
						|
            for use_phase, phase in envoy_data.system_production_phases.items()
 | 
						|
            for description in PRODUCTION_PHASE_SENSORS[use_phase]
 | 
						|
            if phase is not None
 | 
						|
        )
 | 
						|
    # For each consumption phase reported add consumption entities
 | 
						|
    if envoy_data.system_consumption_phases:
 | 
						|
        entities.extend(
 | 
						|
            EnvoyConsumptionPhaseEntity(coordinator, description)
 | 
						|
            for use_phase, phase in envoy_data.system_consumption_phases.items()
 | 
						|
            for description in CONSUMPTION_PHASE_SENSORS[use_phase]
 | 
						|
            if phase is not None
 | 
						|
        )
 | 
						|
    # For each net_consumption phase reported add consumption entities
 | 
						|
    if envoy_data.system_net_consumption_phases:
 | 
						|
        entities.extend(
 | 
						|
            EnvoyNetConsumptionPhaseEntity(coordinator, description)
 | 
						|
            for use_phase, phase in envoy_data.system_net_consumption_phases.items()
 | 
						|
            for description in NET_CONSUMPTION_PHASE_SENSORS[use_phase]
 | 
						|
            if phase is not None
 | 
						|
        )
 | 
						|
    # Add Current Transformer entities
 | 
						|
    if envoy_data.ctmeters:
 | 
						|
        entities.extend(
 | 
						|
            EnvoyCTEntity(coordinator, description)
 | 
						|
            for sensors in (
 | 
						|
                CT_NET_CONSUMPTION_SENSORS,
 | 
						|
                CT_PRODUCTION_SENSORS,
 | 
						|
                CT_STORAGE_SENSORS,
 | 
						|
            )
 | 
						|
            for description in sensors
 | 
						|
            if description.cttype in envoy_data.ctmeters
 | 
						|
        )
 | 
						|
    # Add Current Transformer phase entities
 | 
						|
    if ctmeters_phases := envoy_data.ctmeters_phases:
 | 
						|
        entities.extend(
 | 
						|
            EnvoyCTPhaseEntity(coordinator, description)
 | 
						|
            for sensors in (
 | 
						|
                CT_NET_CONSUMPTION_PHASE_SENSORS,
 | 
						|
                CT_PRODUCTION_PHASE_SENSORS,
 | 
						|
                CT_STORAGE_PHASE_SENSORS,
 | 
						|
            )
 | 
						|
            for phase, descriptions in sensors.items()
 | 
						|
            for description in descriptions
 | 
						|
            if (cttype := description.cttype) in ctmeters_phases
 | 
						|
            and phase in ctmeters_phases[cttype]
 | 
						|
        )
 | 
						|
 | 
						|
    if envoy_data.inverters:
 | 
						|
        entities.extend(
 | 
						|
            EnvoyInverterEntity(coordinator, description, inverter)
 | 
						|
            for description in INVERTER_SENSORS
 | 
						|
            for inverter in envoy_data.inverters
 | 
						|
        )
 | 
						|
 | 
						|
    if envoy_data.encharge_inventory:
 | 
						|
        entities.extend(
 | 
						|
            EnvoyEnchargeInventoryEntity(coordinator, description, encharge)
 | 
						|
            for description in ENCHARGE_INVENTORY_SENSORS
 | 
						|
            for encharge in envoy_data.encharge_inventory
 | 
						|
        )
 | 
						|
    if envoy_data.encharge_power:
 | 
						|
        entities.extend(
 | 
						|
            EnvoyEnchargePowerEntity(coordinator, description, encharge)
 | 
						|
            for description in ENCHARGE_POWER_SENSORS
 | 
						|
            for encharge in envoy_data.encharge_power
 | 
						|
        )
 | 
						|
    if envoy_data.encharge_aggregate:
 | 
						|
        entities.extend(
 | 
						|
            EnvoyEnchargeAggregateEntity(coordinator, description)
 | 
						|
            for description in ENCHARGE_AGGREGATE_SENSORS
 | 
						|
        )
 | 
						|
    if envoy_data.enpower:
 | 
						|
        entities.extend(
 | 
						|
            EnvoyEnpowerEntity(coordinator, description)
 | 
						|
            for description in ENPOWER_SENSORS
 | 
						|
        )
 | 
						|
    if envoy_data.acb_power:
 | 
						|
        entities.extend(
 | 
						|
            EnvoyAcbBatteryPowerEntity(coordinator, description)
 | 
						|
            for description in ACB_BATTERY_POWER_SENSORS
 | 
						|
        )
 | 
						|
        entities.extend(
 | 
						|
            EnvoyAcbBatteryEnergyEntity(coordinator, description)
 | 
						|
            for description in ACB_BATTERY_ENERGY_SENSORS
 | 
						|
        )
 | 
						|
    if envoy_data.battery_aggregate:
 | 
						|
        entities.extend(
 | 
						|
            AggregateBatteryEntity(coordinator, description)
 | 
						|
            for description in AGGREGATE_BATTERY_SENSORS
 | 
						|
        )
 | 
						|
    if envoy_data.collar:
 | 
						|
        entities.extend(
 | 
						|
            EnvoyCollarEntity(coordinator, description)
 | 
						|
            for description in COLLAR_SENSORS
 | 
						|
        )
 | 
						|
    if envoy_data.c6cc:
 | 
						|
        entities.extend(
 | 
						|
            EnvoyC6CCEntity(coordinator, description) for description in C6CC_SENSORS
 | 
						|
        )
 | 
						|
 | 
						|
    async_add_entities(entities)
 | 
						|
 | 
						|
 | 
						|
class EnvoySensorBaseEntity(EnvoyBaseEntity, SensorEntity):
 | 
						|
    """Defines a base envoy entity."""
 | 
						|
 | 
						|
 | 
						|
class EnvoySystemSensorEntity(EnvoySensorBaseEntity):
 | 
						|
    """Envoy system base entity."""
 | 
						|
 | 
						|
    def __init__(
 | 
						|
        self,
 | 
						|
        coordinator: EnphaseUpdateCoordinator,
 | 
						|
        description: SensorEntityDescription,
 | 
						|
    ) -> None:
 | 
						|
        """Initialize Envoy entity."""
 | 
						|
        super().__init__(coordinator, description)
 | 
						|
        self._attr_unique_id = f"{self.envoy_serial_num}_{description.key}"
 | 
						|
        self._attr_device_info = DeviceInfo(
 | 
						|
            identifiers={(DOMAIN, self.envoy_serial_num)},
 | 
						|
            manufacturer="Enphase",
 | 
						|
            model=coordinator.envoy.envoy_model,
 | 
						|
            name=coordinator.name,
 | 
						|
            sw_version=str(coordinator.envoy.firmware),
 | 
						|
            hw_version=coordinator.envoy.part_number,
 | 
						|
            serial_number=self.envoy_serial_num,
 | 
						|
        )
 | 
						|
 | 
						|
 | 
						|
class EnvoyProductionEntity(EnvoySystemSensorEntity):
 | 
						|
    """Envoy production entity."""
 | 
						|
 | 
						|
    entity_description: EnvoyProductionSensorEntityDescription
 | 
						|
 | 
						|
    @property
 | 
						|
    def native_value(self) -> int | None:
 | 
						|
        """Return the state of the sensor."""
 | 
						|
        system_production = self.data.system_production
 | 
						|
        assert system_production is not None
 | 
						|
        return self.entity_description.value_fn(system_production)
 | 
						|
 | 
						|
 | 
						|
class EnvoyConsumptionEntity(EnvoySystemSensorEntity):
 | 
						|
    """Envoy consumption entity."""
 | 
						|
 | 
						|
    entity_description: EnvoyConsumptionSensorEntityDescription
 | 
						|
 | 
						|
    @property
 | 
						|
    def native_value(self) -> int | None:
 | 
						|
        """Return the state of the sensor."""
 | 
						|
        system_consumption = self.data.system_consumption
 | 
						|
        assert system_consumption is not None
 | 
						|
        return self.entity_description.value_fn(system_consumption)
 | 
						|
 | 
						|
 | 
						|
class EnvoyNetConsumptionEntity(EnvoySystemSensorEntity):
 | 
						|
    """Envoy consumption entity."""
 | 
						|
 | 
						|
    entity_description: EnvoyConsumptionSensorEntityDescription
 | 
						|
 | 
						|
    @property
 | 
						|
    def native_value(self) -> int | None:
 | 
						|
        """Return the state of the sensor."""
 | 
						|
        system_net_consumption = self.data.system_net_consumption
 | 
						|
        assert system_net_consumption is not None
 | 
						|
        return self.entity_description.value_fn(system_net_consumption)
 | 
						|
 | 
						|
 | 
						|
class EnvoyProductionPhaseEntity(EnvoySystemSensorEntity):
 | 
						|
    """Envoy phase production entity."""
 | 
						|
 | 
						|
    entity_description: EnvoyProductionSensorEntityDescription
 | 
						|
 | 
						|
    @property
 | 
						|
    def native_value(self) -> int | None:
 | 
						|
        """Return the state of the sensor."""
 | 
						|
        if TYPE_CHECKING:
 | 
						|
            assert self.entity_description.on_phase
 | 
						|
            assert self.data.system_production_phases
 | 
						|
 | 
						|
        if (
 | 
						|
            system_production := self.data.system_production_phases[
 | 
						|
                self.entity_description.on_phase
 | 
						|
            ]
 | 
						|
        ) is None:
 | 
						|
            return None
 | 
						|
        return self.entity_description.value_fn(system_production)
 | 
						|
 | 
						|
 | 
						|
class EnvoyConsumptionPhaseEntity(EnvoySystemSensorEntity):
 | 
						|
    """Envoy phase consumption entity."""
 | 
						|
 | 
						|
    entity_description: EnvoyConsumptionSensorEntityDescription
 | 
						|
 | 
						|
    @property
 | 
						|
    def native_value(self) -> int | None:
 | 
						|
        """Return the state of the sensor."""
 | 
						|
        if TYPE_CHECKING:
 | 
						|
            assert self.entity_description.on_phase
 | 
						|
            assert self.data.system_consumption_phases
 | 
						|
 | 
						|
        if (
 | 
						|
            system_consumption := self.data.system_consumption_phases[
 | 
						|
                self.entity_description.on_phase
 | 
						|
            ]
 | 
						|
        ) is None:
 | 
						|
            return None
 | 
						|
        return self.entity_description.value_fn(system_consumption)
 | 
						|
 | 
						|
 | 
						|
class EnvoyNetConsumptionPhaseEntity(EnvoySystemSensorEntity):
 | 
						|
    """Envoy phase consumption entity."""
 | 
						|
 | 
						|
    entity_description: EnvoyConsumptionSensorEntityDescription
 | 
						|
 | 
						|
    @property
 | 
						|
    def native_value(self) -> int | None:
 | 
						|
        """Return the state of the sensor."""
 | 
						|
        if TYPE_CHECKING:
 | 
						|
            assert self.entity_description.on_phase
 | 
						|
            assert self.data.system_net_consumption_phases
 | 
						|
 | 
						|
        if (
 | 
						|
            system_net_consumption := self.data.system_net_consumption_phases[
 | 
						|
                self.entity_description.on_phase
 | 
						|
            ]
 | 
						|
        ) is None:
 | 
						|
            return None
 | 
						|
        return self.entity_description.value_fn(system_net_consumption)
 | 
						|
 | 
						|
 | 
						|
class EnvoyCTEntity(EnvoySystemSensorEntity):
 | 
						|
    """Envoy CT entity."""
 | 
						|
 | 
						|
    entity_description: EnvoyCTSensorEntityDescription
 | 
						|
 | 
						|
    @property
 | 
						|
    def native_value(
 | 
						|
        self,
 | 
						|
    ) -> int | float | str | CtType | CtMeterStatus | CtStatusFlags | None:
 | 
						|
        """Return the state of the CT sensor."""
 | 
						|
        if (cttype := self.entity_description.cttype) not in self.data.ctmeters:
 | 
						|
            return None
 | 
						|
        return self.entity_description.value_fn(self.data.ctmeters[cttype])
 | 
						|
 | 
						|
 | 
						|
class EnvoyCTPhaseEntity(EnvoySystemSensorEntity):
 | 
						|
    """Envoy CT phase entity."""
 | 
						|
 | 
						|
    entity_description: EnvoyCTSensorEntityDescription
 | 
						|
 | 
						|
    @property
 | 
						|
    def native_value(
 | 
						|
        self,
 | 
						|
    ) -> int | float | str | CtType | CtMeterStatus | CtStatusFlags | None:
 | 
						|
        """Return the state of the CT phase sensor."""
 | 
						|
        if TYPE_CHECKING:
 | 
						|
            assert self.entity_description.on_phase
 | 
						|
        if (cttype := self.entity_description.cttype) not in self.data.ctmeters_phases:
 | 
						|
            return None
 | 
						|
        if (phase := self.entity_description.on_phase) not in self.data.ctmeters_phases[
 | 
						|
            cttype
 | 
						|
        ]:
 | 
						|
            return None
 | 
						|
        return self.entity_description.value_fn(
 | 
						|
            self.data.ctmeters_phases[cttype][phase]
 | 
						|
        )
 | 
						|
 | 
						|
 | 
						|
class EnvoyInverterEntity(EnvoySensorBaseEntity):
 | 
						|
    """Envoy inverter entity."""
 | 
						|
 | 
						|
    entity_description: EnvoyInverterSensorEntityDescription
 | 
						|
 | 
						|
    def __init__(
 | 
						|
        self,
 | 
						|
        coordinator: EnphaseUpdateCoordinator,
 | 
						|
        description: EnvoyInverterSensorEntityDescription,
 | 
						|
        serial_number: str,
 | 
						|
    ) -> None:
 | 
						|
        """Initialize Envoy inverter entity."""
 | 
						|
        super().__init__(coordinator, description)
 | 
						|
        self._serial_number = serial_number
 | 
						|
        key = description.key
 | 
						|
        if key == INVERTERS_KEY:
 | 
						|
            # Originally there was only one inverter sensor, so we don't want to
 | 
						|
            # break existing installations by changing the unique_id.
 | 
						|
            self._attr_unique_id = serial_number
 | 
						|
        else:
 | 
						|
            # Additional sensors have a unique_id that includes the
 | 
						|
            # sensor key.
 | 
						|
            self._attr_unique_id = f"{serial_number}_{key}"
 | 
						|
        self._attr_device_info = DeviceInfo(
 | 
						|
            identifiers={(DOMAIN, serial_number)},
 | 
						|
            name=f"Inverter {serial_number}",
 | 
						|
            manufacturer="Enphase",
 | 
						|
            model="Inverter",
 | 
						|
            via_device=(DOMAIN, self.envoy_serial_num),
 | 
						|
            serial_number=serial_number,
 | 
						|
        )
 | 
						|
 | 
						|
    @property
 | 
						|
    def native_value(self) -> datetime.datetime | float | None:
 | 
						|
        """Return the state of the sensor."""
 | 
						|
        inverters = self.data.inverters
 | 
						|
        assert inverters is not None
 | 
						|
        # Some envoy fw versions return an empty inverter array every 4 hours when
 | 
						|
        # no production is taking place. Prevent collection failure due to this
 | 
						|
        # as other data seems fine. Inverters will show unknown during this cycle.
 | 
						|
        if self._serial_number not in inverters:
 | 
						|
            _LOGGER.debug(
 | 
						|
                "Inverter %s not in returned inverters array (size: %s)",
 | 
						|
                self._serial_number,
 | 
						|
                len(inverters),
 | 
						|
            )
 | 
						|
            return None
 | 
						|
        return self.entity_description.value_fn(inverters[self._serial_number])
 | 
						|
 | 
						|
 | 
						|
class EnvoyEnchargeEntity(EnvoySensorBaseEntity):
 | 
						|
    """Envoy Encharge sensor entity."""
 | 
						|
 | 
						|
    def __init__(
 | 
						|
        self,
 | 
						|
        coordinator: EnphaseUpdateCoordinator,
 | 
						|
        description: EnvoyEnchargeSensorEntityDescription
 | 
						|
        | EnvoyEnchargePowerSensorEntityDescription,
 | 
						|
        serial_number: str,
 | 
						|
    ) -> None:
 | 
						|
        """Initialize Encharge entity."""
 | 
						|
        super().__init__(coordinator, description)
 | 
						|
        self._serial_number = serial_number
 | 
						|
        self._attr_unique_id = f"{serial_number}_{description.key}"
 | 
						|
        encharge_inventory = self.data.encharge_inventory
 | 
						|
        assert encharge_inventory is not None
 | 
						|
        self._attr_device_info = DeviceInfo(
 | 
						|
            identifiers={(DOMAIN, serial_number)},
 | 
						|
            manufacturer="Enphase",
 | 
						|
            model="Encharge",
 | 
						|
            name=f"Encharge {serial_number}",
 | 
						|
            sw_version=str(encharge_inventory[self._serial_number].firmware_version),
 | 
						|
            via_device=(DOMAIN, self.envoy_serial_num),
 | 
						|
            serial_number=serial_number,
 | 
						|
        )
 | 
						|
 | 
						|
 | 
						|
class EnvoyEnchargeInventoryEntity(EnvoyEnchargeEntity):
 | 
						|
    """Envoy Encharge inventory entity."""
 | 
						|
 | 
						|
    entity_description: EnvoyEnchargeSensorEntityDescription
 | 
						|
 | 
						|
    @property
 | 
						|
    def native_value(self) -> int | float | datetime.datetime | None:
 | 
						|
        """Return the state of the inventory sensors."""
 | 
						|
        encharge_inventory = self.data.encharge_inventory
 | 
						|
        assert encharge_inventory is not None
 | 
						|
        return self.entity_description.value_fn(encharge_inventory[self._serial_number])
 | 
						|
 | 
						|
 | 
						|
class EnvoyEnchargePowerEntity(EnvoyEnchargeEntity):
 | 
						|
    """Envoy Encharge power entity."""
 | 
						|
 | 
						|
    entity_description: EnvoyEnchargePowerSensorEntityDescription
 | 
						|
 | 
						|
    @property
 | 
						|
    def native_value(self) -> int | float | None:
 | 
						|
        """Return the state of the power sensors."""
 | 
						|
        encharge_power = self.data.encharge_power
 | 
						|
        assert encharge_power is not None
 | 
						|
        return self.entity_description.value_fn(encharge_power[self._serial_number])
 | 
						|
 | 
						|
 | 
						|
class EnvoyEnchargeAggregateEntity(EnvoySystemSensorEntity):
 | 
						|
    """Envoy Encharge Aggregate sensor entity."""
 | 
						|
 | 
						|
    entity_description: EnvoyEnchargeAggregateSensorEntityDescription
 | 
						|
 | 
						|
    @property
 | 
						|
    def native_value(self) -> int:
 | 
						|
        """Return the state of the aggregate sensors."""
 | 
						|
        encharge_aggregate = self.data.encharge_aggregate
 | 
						|
        assert encharge_aggregate is not None
 | 
						|
        return self.entity_description.value_fn(encharge_aggregate)
 | 
						|
 | 
						|
 | 
						|
class EnvoyEnpowerEntity(EnvoySensorBaseEntity):
 | 
						|
    """Envoy Enpower sensor entity."""
 | 
						|
 | 
						|
    entity_description: EnvoyEnpowerSensorEntityDescription
 | 
						|
 | 
						|
    def __init__(
 | 
						|
        self,
 | 
						|
        coordinator: EnphaseUpdateCoordinator,
 | 
						|
        description: EnvoyEnpowerSensorEntityDescription,
 | 
						|
    ) -> None:
 | 
						|
        """Initialize Enpower entity."""
 | 
						|
        super().__init__(coordinator, description)
 | 
						|
        enpower_data = self.data.enpower
 | 
						|
        assert enpower_data is not None
 | 
						|
        self._attr_unique_id = f"{enpower_data.serial_number}_{description.key}"
 | 
						|
        self._attr_device_info = DeviceInfo(
 | 
						|
            identifiers={(DOMAIN, enpower_data.serial_number)},
 | 
						|
            manufacturer="Enphase",
 | 
						|
            model="Enpower",
 | 
						|
            name=f"Enpower {enpower_data.serial_number}",
 | 
						|
            sw_version=str(enpower_data.firmware_version),
 | 
						|
            via_device=(DOMAIN, self.envoy_serial_num),
 | 
						|
            serial_number=enpower_data.serial_number,
 | 
						|
        )
 | 
						|
 | 
						|
    @property
 | 
						|
    def native_value(self) -> datetime.datetime | int | float | None:
 | 
						|
        """Return the state of the power sensors."""
 | 
						|
        enpower = self.data.enpower
 | 
						|
        assert enpower is not None
 | 
						|
        return self.entity_description.value_fn(enpower)
 | 
						|
 | 
						|
 | 
						|
class EnvoyAcbBatteryPowerEntity(EnvoySensorBaseEntity):
 | 
						|
    """Envoy ACB Battery power sensor entity."""
 | 
						|
 | 
						|
    entity_description: EnvoyAcbBatterySensorEntityDescription
 | 
						|
 | 
						|
    def __init__(
 | 
						|
        self,
 | 
						|
        coordinator: EnphaseUpdateCoordinator,
 | 
						|
        description: EnvoyAcbBatterySensorEntityDescription,
 | 
						|
    ) -> None:
 | 
						|
        """Initialize ACB Battery entity."""
 | 
						|
        super().__init__(coordinator, description)
 | 
						|
        acb_data = self.data.acb_power
 | 
						|
        assert acb_data is not None
 | 
						|
        self._attr_unique_id = f"{self.envoy_serial_num}_{description.key}"
 | 
						|
        self._attr_device_info = DeviceInfo(
 | 
						|
            identifiers={(DOMAIN, f"{self.envoy_serial_num}_acb")},
 | 
						|
            manufacturer="Enphase",
 | 
						|
            model="ACB",
 | 
						|
            name=f"ACB {self.envoy_serial_num}",
 | 
						|
            via_device=(DOMAIN, self.envoy_serial_num),
 | 
						|
        )
 | 
						|
 | 
						|
    @property
 | 
						|
    def native_value(self) -> int | str | None:
 | 
						|
        """Return the state of the ACB Battery power sensors."""
 | 
						|
        acb = self.data.acb_power
 | 
						|
        assert acb is not None
 | 
						|
        return self.entity_description.value_fn(acb)
 | 
						|
 | 
						|
 | 
						|
class EnvoyAcbBatteryEnergyEntity(EnvoySystemSensorEntity):
 | 
						|
    """Envoy combined ACB and Ensemble Battery Aggregate energy sensor entity."""
 | 
						|
 | 
						|
    entity_description: EnvoyAcbBatterySensorEntityDescription
 | 
						|
 | 
						|
    @property
 | 
						|
    def native_value(self) -> int | str:
 | 
						|
        """Return the state of the aggregate energy sensors."""
 | 
						|
        acb = self.data.acb_power
 | 
						|
        assert acb is not None
 | 
						|
        return self.entity_description.value_fn(acb)
 | 
						|
 | 
						|
 | 
						|
class AggregateBatteryEntity(EnvoySystemSensorEntity):
 | 
						|
    """Envoy combined ACB and Ensemble Battery Aggregate sensor entity."""
 | 
						|
 | 
						|
    entity_description: EnvoyAggregateBatterySensorEntityDescription
 | 
						|
 | 
						|
    @property
 | 
						|
    def native_value(self) -> int:
 | 
						|
        """Return the state of the aggregate sensors."""
 | 
						|
        battery_aggregate = self.data.battery_aggregate
 | 
						|
        assert battery_aggregate is not None
 | 
						|
        return self.entity_description.value_fn(battery_aggregate)
 | 
						|
 | 
						|
 | 
						|
class EnvoyCollarEntity(EnvoySensorBaseEntity):
 | 
						|
    """Envoy Collar sensor entity."""
 | 
						|
 | 
						|
    entity_description: EnvoyCollarSensorEntityDescription
 | 
						|
 | 
						|
    def __init__(
 | 
						|
        self,
 | 
						|
        coordinator: EnphaseUpdateCoordinator,
 | 
						|
        description: EnvoyCollarSensorEntityDescription,
 | 
						|
    ) -> None:
 | 
						|
        """Initialize Collar entity."""
 | 
						|
        super().__init__(coordinator, description)
 | 
						|
        collar_data = self.data.collar
 | 
						|
        assert collar_data is not None
 | 
						|
        self._serial_number = collar_data.serial_number
 | 
						|
        self._attr_unique_id = f"{collar_data.serial_number}_{description.key}"
 | 
						|
        self._attr_device_info = DeviceInfo(
 | 
						|
            identifiers={(DOMAIN, collar_data.serial_number)},
 | 
						|
            manufacturer="Enphase",
 | 
						|
            model="IQ Meter Collar",
 | 
						|
            name=f"Collar {collar_data.serial_number}",
 | 
						|
            sw_version=str(collar_data.firmware_version),
 | 
						|
            via_device=(DOMAIN, self.envoy_serial_num),
 | 
						|
            serial_number=collar_data.serial_number,
 | 
						|
        )
 | 
						|
 | 
						|
    @property
 | 
						|
    def native_value(self) -> datetime.datetime | int | float | str:
 | 
						|
        """Return the state of the collar sensors."""
 | 
						|
        collar_data = self.data.collar
 | 
						|
        assert collar_data is not None
 | 
						|
        return self.entity_description.value_fn(collar_data)
 | 
						|
 | 
						|
 | 
						|
class EnvoyC6CCEntity(EnvoySensorBaseEntity):
 | 
						|
    """Envoy C6CC sensor entity."""
 | 
						|
 | 
						|
    entity_description: EnvoyC6CCSensorEntityDescription
 | 
						|
 | 
						|
    def __init__(
 | 
						|
        self,
 | 
						|
        coordinator: EnphaseUpdateCoordinator,
 | 
						|
        description: EnvoyC6CCSensorEntityDescription,
 | 
						|
    ) -> None:
 | 
						|
        """Initialize Encharge entity."""
 | 
						|
        super().__init__(coordinator, description)
 | 
						|
        c6cc_data = self.data.c6cc
 | 
						|
        assert c6cc_data is not None
 | 
						|
        self._attr_unique_id = f"{c6cc_data.serial_number}_{description.key}"
 | 
						|
        self._attr_device_info = DeviceInfo(
 | 
						|
            identifiers={(DOMAIN, c6cc_data.serial_number)},
 | 
						|
            manufacturer="Enphase",
 | 
						|
            model="C6 COMBINER CONTROLLER",
 | 
						|
            name=f"C6 Combiner {c6cc_data.serial_number}",
 | 
						|
            sw_version=str(c6cc_data.firmware_version),
 | 
						|
            via_device=(DOMAIN, self.envoy_serial_num),
 | 
						|
            serial_number=c6cc_data.serial_number,
 | 
						|
        )
 | 
						|
 | 
						|
    @property
 | 
						|
    def native_value(self) -> datetime.datetime:
 | 
						|
        """Return the state of the c6cc inventory sensors."""
 | 
						|
        c6cc_data = self.data.c6cc
 | 
						|
        assert c6cc_data is not None
 | 
						|
        return self.entity_description.value_fn(c6cc_data)
 |