diff --git a/CODEOWNERS b/CODEOWNERS index 05cb45ee70f0..e797ca160c04 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -1764,7 +1764,6 @@ CLAUDE.md @home-assistant/core /tests/components/sofar/ @darkrain-nl /homeassistant/components/solaredge/ @frenck @bdraco @tronikos /tests/components/solaredge/ @frenck @bdraco @tronikos -/homeassistant/components/solaredge_local/ @drobtravels @scheric /homeassistant/components/solaredge_modbus/ @frenck /tests/components/solaredge_modbus/ @frenck /homeassistant/components/solarlog/ @Ernst79 @dontinelli diff --git a/homeassistant/brands/solaredge.json b/homeassistant/brands/solaredge.json index 1138992f1fb5..556c86252bc9 100644 --- a/homeassistant/brands/solaredge.json +++ b/homeassistant/brands/solaredge.json @@ -1,5 +1,5 @@ { "domain": "solaredge", "name": "SolarEdge", - "integrations": ["solaredge", "solaredge_local", "solaredge_modbus"] + "integrations": ["solaredge", "solaredge_modbus"] } diff --git a/homeassistant/components/solaredge_local/__init__.py b/homeassistant/components/solaredge_local/__init__.py deleted file mode 100644 index bf9d724dd545..000000000000 --- a/homeassistant/components/solaredge_local/__init__.py +++ /dev/null @@ -1 +0,0 @@ -"""The SolarEdge Local Integration.""" diff --git a/homeassistant/components/solaredge_local/manifest.json b/homeassistant/components/solaredge_local/manifest.json deleted file mode 100644 index 61c08b3b152a..000000000000 --- a/homeassistant/components/solaredge_local/manifest.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "domain": "solaredge_local", - "name": "SolarEdge Local", - "codeowners": ["@drobtravels", "@scheric"], - "documentation": "https://www.home-assistant.io/integrations/solaredge_local", - "iot_class": "local_polling", - "loggers": ["solaredge_local"], - "quality_scale": "legacy", - "requirements": ["solaredge-local==0.2.3"] -} diff --git a/homeassistant/components/solaredge_local/sensor.py b/homeassistant/components/solaredge_local/sensor.py deleted file mode 100644 index 1e4e5563d74f..000000000000 --- a/homeassistant/components/solaredge_local/sensor.py +++ /dev/null @@ -1,390 +0,0 @@ -"""Support for SolarEdge-local Monitoring API.""" - -from contextlib import suppress -import dataclasses -from datetime import timedelta -import logging -import statistics -from typing import Any, override - -import probatio -from requests.exceptions import ConnectTimeout, HTTPError -from solaredge_local import SolarEdge - -from homeassistant.components.sensor import ( - PLATFORM_SCHEMA as SENSOR_PLATFORM_SCHEMA, - SensorDeviceClass, - SensorEntity, - SensorEntityDescription, -) -from homeassistant.const import ( - CONF_IP_ADDRESS, - CONF_NAME, - UnitOfElectricCurrent, - UnitOfElectricPotential, - UnitOfEnergy, - UnitOfFrequency, - UnitOfPower, - UnitOfTemperature, -) -from homeassistant.core import HomeAssistant -from homeassistant.helpers import config_validation as cv -from homeassistant.helpers.entity_platform import AddEntitiesCallback -from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType -from homeassistant.util import Throttle - -DOMAIN = "solaredge_local" -UPDATE_DELAY = timedelta(seconds=10) - -INVERTER_MODES = ( - "SHUTTING_DOWN", - "ERROR", - "STANDBY", - "PAIRING", - "POWER_PRODUCTION", - "AC_CHARGING", - "NOT_PAIRED", - "NIGHT_MODE", - "GRID_MONITORING", - "IDLE", -) - - -@dataclasses.dataclass(frozen=True) -class SolarEdgeLocalSensorEntityDescription(SensorEntityDescription): - """Describes SolarEdge-local sensor entity.""" - - extra_attribute: str | None = None - - -SENSOR_TYPES: tuple[SolarEdgeLocalSensorEntityDescription, ...] = ( - SolarEdgeLocalSensorEntityDescription( - key="gridvoltage", - name="Grid Voltage", - native_unit_of_measurement=UnitOfElectricPotential.VOLT, - device_class=SensorDeviceClass.VOLTAGE, - icon="mdi:current-ac", - ), - SolarEdgeLocalSensorEntityDescription( - key="dcvoltage", - name="DC Voltage", - native_unit_of_measurement=UnitOfElectricPotential.VOLT, - device_class=SensorDeviceClass.VOLTAGE, - icon="mdi:current-dc", - ), - SolarEdgeLocalSensorEntityDescription( - key="gridfrequency", - name="Grid Frequency", - native_unit_of_measurement=UnitOfFrequency.HERTZ, - device_class=SensorDeviceClass.FREQUENCY, - ), - SolarEdgeLocalSensorEntityDescription( - key="currentPower", - name="Current Power", - native_unit_of_measurement=UnitOfPower.WATT, - device_class=SensorDeviceClass.POWER, - icon="mdi:solar-power", - ), - SolarEdgeLocalSensorEntityDescription( - key="energyThisMonth", - name="Energy This Month", - native_unit_of_measurement=UnitOfEnergy.WATT_HOUR, - device_class=SensorDeviceClass.ENERGY, - icon="mdi:solar-power", - ), - SolarEdgeLocalSensorEntityDescription( - key="energyThisYear", - name="Energy This Year", - native_unit_of_measurement=UnitOfEnergy.WATT_HOUR, - device_class=SensorDeviceClass.ENERGY, - icon="mdi:solar-power", - ), - SolarEdgeLocalSensorEntityDescription( - key="energyToday", - name="Energy Today", - native_unit_of_measurement=UnitOfEnergy.WATT_HOUR, - device_class=SensorDeviceClass.ENERGY, - icon="mdi:solar-power", - ), - SolarEdgeLocalSensorEntityDescription( - key="energyTotal", - name="Lifetime Energy", - native_unit_of_measurement=UnitOfEnergy.WATT_HOUR, - device_class=SensorDeviceClass.ENERGY, - icon="mdi:solar-power", - ), - SolarEdgeLocalSensorEntityDescription( - key="optimizers", - name="Optimizers Online", - native_unit_of_measurement="optimizers", - icon="mdi:solar-panel", - extra_attribute="optimizers_connected", - ), - SolarEdgeLocalSensorEntityDescription( - key="optimizercurrent", - name="Average Optimizer Current", - native_unit_of_measurement=UnitOfElectricCurrent.AMPERE, - device_class=SensorDeviceClass.CURRENT, - icon="mdi:solar-panel", - ), - SolarEdgeLocalSensorEntityDescription( - key="optimizerpower", - name="Average Optimizer Power", - native_unit_of_measurement=UnitOfPower.WATT, - device_class=SensorDeviceClass.POWER, - icon="mdi:solar-panel", - ), - SolarEdgeLocalSensorEntityDescription( - key="optimizertemperature", - name="Average Optimizer Temperature", - native_unit_of_measurement=UnitOfTemperature.CELSIUS, - icon="mdi:solar-panel", - device_class=SensorDeviceClass.TEMPERATURE, - ), - SolarEdgeLocalSensorEntityDescription( - key="optimizervoltage", - name="Average Optimizer Voltage", - native_unit_of_measurement=UnitOfElectricPotential.VOLT, - device_class=SensorDeviceClass.VOLTAGE, - icon="mdi:solar-panel", - ), -) - -SENSOR_TYPE_INVERTER_TEMPERATURE = SolarEdgeLocalSensorEntityDescription( - key="invertertemperature", - name="Inverter Temperature", - native_unit_of_measurement=UnitOfTemperature.CELSIUS, - extra_attribute="operating_mode", - device_class=SensorDeviceClass.TEMPERATURE, -) - -SENSOR_TYPES_ENERGY_IMPORT: tuple[SolarEdgeLocalSensorEntityDescription, ...] = ( - SolarEdgeLocalSensorEntityDescription( - key="currentPowerimport", - name="current import Power", - native_unit_of_measurement=UnitOfPower.WATT, - device_class=SensorDeviceClass.POWER, - icon="mdi:arrow-collapse-down", - ), - SolarEdgeLocalSensorEntityDescription( - key="totalEnergyimport", - name="total import Energy", - native_unit_of_measurement=UnitOfEnergy.WATT_HOUR, - device_class=SensorDeviceClass.ENERGY, - icon="mdi:counter", - ), -) - -SENSOR_TYPES_ENERGY_EXPORT: tuple[SolarEdgeLocalSensorEntityDescription, ...] = ( - SolarEdgeLocalSensorEntityDescription( - key="currentPowerexport", - name="current export Power", - native_unit_of_measurement=UnitOfPower.WATT, - device_class=SensorDeviceClass.POWER, - icon="mdi:arrow-expand-up", - ), - SolarEdgeLocalSensorEntityDescription( - key="totalEnergyexport", - name="total export Energy", - native_unit_of_measurement=UnitOfEnergy.WATT_HOUR, - device_class=SensorDeviceClass.ENERGY, - icon="mdi:counter", - ), -) - -PLATFORM_SCHEMA = SENSOR_PLATFORM_SCHEMA.extend( - { - probatio.Required(CONF_IP_ADDRESS): cv.string, - probatio.Optional(CONF_NAME, default="SolarEdge"): cv.string, - } -) - -_LOGGER = logging.getLogger(__name__) - - -def setup_platform( - hass: HomeAssistant, - config: ConfigType, - add_entities: AddEntitiesCallback, - discovery_info: DiscoveryInfoType | None = None, -) -> None: - """Create the SolarEdge Monitoring API sensor.""" - ip_address = config[CONF_IP_ADDRESS] - platform_name = config[CONF_NAME] - - # Create new SolarEdge object to retrieve data. - api = SolarEdge(f"http://{ip_address}/") - - # Check if api can be reached and site is active. - try: - status = api.get_status() - _LOGGER.debug("Credentials correct and site is active") - except AttributeError: - _LOGGER.error("Missing details data in solaredge status") - return - except ConnectTimeout, HTTPError: - _LOGGER.error("Could not retrieve details from SolarEdge API") - return - - # Create solaredge data service which will retrieve and update the data. - data = SolarEdgeData(hass, api) - - # Changing inverter temperature unit. - inverter_temp_description = SENSOR_TYPE_INVERTER_TEMPERATURE - if ( - status.inverters.primary.temperature.units.farenheit # codespell:ignore farenheit - ): - inverter_temp_description = dataclasses.replace( - inverter_temp_description, - native_unit_of_measurement=UnitOfTemperature.FAHRENHEIT, - ) - - # Create entities - entities = [ - SolarEdgeSensor(platform_name, data, description) - for description in (*SENSOR_TYPES, inverter_temp_description) - ] - - try: - if status.metersList[0]: - entities.extend( - [ - SolarEdgeSensor(platform_name, data, description) - for description in SENSOR_TYPES_ENERGY_IMPORT - ] - ) - except IndexError: - _LOGGER.debug("Import meter sensors are not created") - - try: - if status.metersList[1]: - entities.extend( - [ - SolarEdgeSensor(platform_name, data, description) - for description in SENSOR_TYPES_ENERGY_EXPORT - ] - ) - except IndexError: - _LOGGER.debug("Export meter sensors are not created") - - add_entities(entities, True) - - -class SolarEdgeSensor(SensorEntity): - """Representation of an SolarEdge Monitoring API sensor.""" - - entity_description: SolarEdgeLocalSensorEntityDescription - - def __init__( - self, - platform_name, - data, - description: SolarEdgeLocalSensorEntityDescription, - ) -> None: - """Initialize the sensor.""" - self.entity_description = description - self._platform_name = platform_name - self._data = data - self._attr_name = f"{platform_name} ({description.name})" - - @property - @override - def extra_state_attributes(self) -> dict[str, Any] | None: - """Return the state attributes.""" - if extra_attr := self.entity_description.extra_attribute: - try: - return {extra_attr: self._data.info.get(self.entity_description.key)} - except KeyError: - pass - return None - - def update(self) -> None: - """Get the latest data from the sensor and update the state.""" - self._data.update() - self._attr_native_value = self._data.data.get(self.entity_description.key) - - -class SolarEdgeData: - """Get and update the latest data.""" - - def __init__(self, hass, api): - """Initialize the data object.""" - self.hass = hass - self.api = api - self.data = {} - self.info = {} - - @Throttle(UPDATE_DELAY) - def update(self): - """Update the data from the SolarEdge Monitoring API.""" - try: - status = self.api.get_status() - _LOGGER.debug("Status from SolarEdge: %s", status) - except ConnectTimeout: - _LOGGER.error("Connection timeout, skipping update") - return - except HTTPError: - _LOGGER.error("Could not retrieve status, skipping update") - return - - try: - maintenance = self.api.get_maintenance() - _LOGGER.debug("Maintenance from SolarEdge: %s", maintenance) - except ConnectTimeout: - _LOGGER.error("Connection timeout, skipping update") - return - except HTTPError: - _LOGGER.error("Could not retrieve maintenance, skipping update") - return - - temperature = [] - voltage = [] - current = [] - power = 0 - - for optimizer in maintenance.diagnostics.inverters.primary.optimizer: - if not optimizer.online: - continue - temperature.append(optimizer.temperature.value) - voltage.append(optimizer.inputV) - current.append(optimizer.inputC) - - if not voltage: - temperature.append(0) - voltage.append(0) - current.append(0) - else: - power = statistics.mean(voltage) * statistics.mean(current) - - if status.sn: - self.data["energyTotal"] = round(status.energy.total, 2) - self.data["energyThisYear"] = round(status.energy.thisYear, 2) - self.data["energyThisMonth"] = round(status.energy.thisMonth, 2) - self.data["energyToday"] = round(status.energy.today, 2) - self.data["currentPower"] = round(status.powerWatt, 2) - self.data["invertertemperature"] = round( - status.inverters.primary.temperature.value, 2 - ) - self.data["dcvoltage"] = round(status.inverters.primary.voltage, 2) - self.data["gridfrequency"] = round(status.frequencyHz, 2) - self.data["gridvoltage"] = round(status.voltage, 2) - self.data["optimizers"] = status.optimizersStatus.online - - self.info["optimizers"] = status.optimizersStatus.total - self.info["invertertemperature"] = INVERTER_MODES[status.status] - - with suppress(IndexError): - if status.metersList[1]: - self.data["currentPowerimport"] = status.metersList[1].currentPower - self.data["totalEnergyimport"] = status.metersList[1].totalEnergy - - with suppress(IndexError): - if status.metersList[0]: - self.data["currentPowerexport"] = status.metersList[0].currentPower - self.data["totalEnergyexport"] = status.metersList[0].totalEnergy - - if maintenance.system.name: - self.data["optimizertemperature"] = round(statistics.mean(temperature), 2) - self.data["optimizervoltage"] = round(statistics.mean(voltage), 2) - self.data["optimizercurrent"] = round(statistics.mean(current), 2) - self.data["optimizerpower"] = round(power, 2) diff --git a/homeassistant/generated/integrations.json b/homeassistant/generated/integrations.json index 3d4f871b0019..574757ff4d50 100644 --- a/homeassistant/generated/integrations.json +++ b/homeassistant/generated/integrations.json @@ -6887,12 +6887,6 @@ "iot_class": "cloud_polling", "name": "SolarEdge" }, - "solaredge_local": { - "integration_type": "hub", - "config_flow": false, - "iot_class": "local_polling", - "name": "SolarEdge Local" - }, "solaredge_modbus": { "integration_type": "device", "config_flow": true, diff --git a/requirements_all.txt b/requirements_all.txt index 3b1477e82a8b..1a0baf9f7acb 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -3131,9 +3131,6 @@ soco==0.31.2 # homeassistant.components.sofar sofar-modbus==0.17.0 -# homeassistant.components.solaredge_local -solaredge-local==0.2.3 - # homeassistant.components.solaredge solaredge-web==0.4.0 diff --git a/script/hassfest/quality_scale.py b/script/hassfest/quality_scale.py index b6af338c3b2a..4e1054838c16 100644 --- a/script/hassfest/quality_scale.py +++ b/script/hassfest/quality_scale.py @@ -827,7 +827,6 @@ INTEGRATIONS_WITHOUT_QUALITY_SCALE_FILE = [ "snmp", "snooz", "solaredge", - "solaredge_local", "solax", "soma", "somfy_mylink", @@ -1773,7 +1772,6 @@ INTEGRATIONS_WITHOUT_SCALE = [ "snmp", "snooz", "solaredge", - "solaredge_local", "solax", "soma", "somfy_mylink",