1
mirror of https://github.com/home-assistant/core synced 2024-08-28 03:36:46 +02:00
ha-core/homeassistant/components/solax/sensor.py
Erik Montnemery 045c327928
Move DeviceInfo from entity to device registry (#98149)
* Move DeviceInfo from entity to device registry

* Update integrations
2023-08-10 22:04:26 -04:00

193 lines
6.0 KiB
Python

"""Support for Solax inverter via local API."""
from __future__ import annotations
import asyncio
from datetime import timedelta
from solax import RealTimeAPI
from solax.discovery import InverterError
from solax.units import Units
from homeassistant.components.sensor import (
SensorDeviceClass,
SensorEntity,
SensorEntityDescription,
SensorStateClass,
)
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import (
PERCENTAGE,
UnitOfElectricCurrent,
UnitOfElectricPotential,
UnitOfEnergy,
UnitOfFrequency,
UnitOfPower,
UnitOfTemperature,
)
from homeassistant.core import HomeAssistant
from homeassistant.exceptions import PlatformNotReady
from homeassistant.helpers.device_registry import DeviceInfo
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from homeassistant.helpers.event import async_track_time_interval
from .const import DOMAIN, MANUFACTURER
DEFAULT_PORT = 80
SCAN_INTERVAL = timedelta(seconds=30)
SENSOR_DESCRIPTIONS: dict[tuple[Units, bool], SensorEntityDescription] = {
(Units.C, False): SensorEntityDescription(
key=f"{Units.C}_{False}",
device_class=SensorDeviceClass.TEMPERATURE,
native_unit_of_measurement=UnitOfTemperature.CELSIUS,
state_class=SensorStateClass.MEASUREMENT,
),
(Units.KWH, False): SensorEntityDescription(
key=f"{Units.KWH}_{False}",
device_class=SensorDeviceClass.ENERGY,
native_unit_of_measurement=UnitOfEnergy.KILO_WATT_HOUR,
state_class=SensorStateClass.MEASUREMENT,
),
(Units.KWH, True): SensorEntityDescription(
key=f"{Units.KWH}_{True}",
device_class=SensorDeviceClass.ENERGY,
native_unit_of_measurement=UnitOfEnergy.KILO_WATT_HOUR,
state_class=SensorStateClass.TOTAL_INCREASING,
),
(Units.V, False): SensorEntityDescription(
key=f"{Units.V}_{False}",
device_class=SensorDeviceClass.VOLTAGE,
native_unit_of_measurement=UnitOfElectricPotential.VOLT,
state_class=SensorStateClass.MEASUREMENT,
),
(Units.A, False): SensorEntityDescription(
key=f"{Units.A}_{False}",
device_class=SensorDeviceClass.CURRENT,
native_unit_of_measurement=UnitOfElectricCurrent.AMPERE,
state_class=SensorStateClass.MEASUREMENT,
),
(Units.W, False): SensorEntityDescription(
key=f"{Units.W}_{False}",
device_class=SensorDeviceClass.POWER,
native_unit_of_measurement=UnitOfPower.WATT,
state_class=SensorStateClass.MEASUREMENT,
),
(Units.PERCENT, False): SensorEntityDescription(
key=f"{Units.PERCENT}_{False}",
device_class=SensorDeviceClass.BATTERY,
native_unit_of_measurement=PERCENTAGE,
state_class=SensorStateClass.MEASUREMENT,
),
(Units.HZ, False): SensorEntityDescription(
key=f"{Units.HZ}_{False}",
device_class=SensorDeviceClass.FREQUENCY,
native_unit_of_measurement=UnitOfFrequency.HERTZ,
state_class=SensorStateClass.MEASUREMENT,
),
(Units.NONE, False): SensorEntityDescription(
key=f"{Units.NONE}_{False}",
),
}
async def async_setup_entry(
hass: HomeAssistant,
entry: ConfigEntry,
async_add_entities: AddEntitiesCallback,
) -> None:
"""Entry setup."""
api: RealTimeAPI = hass.data[DOMAIN][entry.entry_id]
resp = await api.get_data()
serial = resp.serial_number
version = resp.version
endpoint = RealTimeDataEndpoint(hass, api)
hass.async_add_job(endpoint.async_refresh)
async_track_time_interval(hass, endpoint.async_refresh, SCAN_INTERVAL)
devices = []
for sensor, (idx, measurement) in api.inverter.sensor_map().items():
description = SENSOR_DESCRIPTIONS[(measurement.unit, measurement.is_monotonic)]
uid = f"{serial}-{idx}"
devices.append(
Inverter(
api.inverter.manufacturer,
uid,
serial,
version,
sensor,
description.native_unit_of_measurement,
description.state_class,
description.device_class,
)
)
endpoint.sensors = devices
async_add_entities(devices)
class RealTimeDataEndpoint:
"""Representation of a Sensor."""
def __init__(self, hass: HomeAssistant, api: RealTimeAPI) -> None:
"""Initialize the sensor."""
self.hass = hass
self.api = api
self.ready = asyncio.Event()
self.sensors: list[Inverter] = []
async def async_refresh(self, now=None):
"""Fetch new state data for the sensor.
This is the only method that should fetch new data for Home Assistant.
"""
try:
api_response = await self.api.get_data()
self.ready.set()
except InverterError as err:
if now is not None:
self.ready.clear()
return
raise PlatformNotReady from err
data = api_response.data
for sensor in self.sensors:
if sensor.key in data:
sensor.value = data[sensor.key]
sensor.async_schedule_update_ha_state()
class Inverter(SensorEntity):
"""Class for a sensor."""
_attr_should_poll = False
def __init__(
self,
manufacturer,
uid,
serial,
version,
key,
unit,
state_class=None,
device_class=None,
):
"""Initialize an inverter sensor."""
self._attr_unique_id = uid
self._attr_name = f"{manufacturer} {serial} {key}"
self._attr_native_unit_of_measurement = unit
self._attr_state_class = state_class
self._attr_device_class = device_class
self._attr_device_info = DeviceInfo(
identifiers={(DOMAIN, serial)},
manufacturer=MANUFACTURER,
name=f"{manufacturer} {serial}",
sw_version=version,
)
self.key = key
self.value = None
@property
def native_value(self):
"""State of this inverter attribute."""
return self.value