207 lines
6.6 KiB
Python
207 lines
6.6 KiB
Python
"""Base class for Netatmo entities."""
|
|
|
|
from __future__ import annotations
|
|
|
|
from abc import abstractmethod
|
|
from typing import Any, cast
|
|
|
|
from pyatmo import DeviceType, Home, Module, Room
|
|
from pyatmo.modules.base_class import NetatmoBase, Place
|
|
from pyatmo.modules.device_types import DEVICE_DESCRIPTION_MAP
|
|
|
|
from homeassistant.const import ATTR_LATITUDE, ATTR_LONGITUDE
|
|
from homeassistant.core import callback
|
|
from homeassistant.helpers import device_registry as dr
|
|
from homeassistant.helpers.device_registry import DeviceInfo
|
|
from homeassistant.helpers.entity import Entity
|
|
|
|
from .const import (
|
|
CONF_URL_ENERGY,
|
|
CONF_URL_WEATHER,
|
|
DATA_DEVICE_IDS,
|
|
DEFAULT_ATTRIBUTION,
|
|
DOMAIN,
|
|
SIGNAL_NAME,
|
|
)
|
|
from .data_handler import PUBLIC, NetatmoDataHandler, NetatmoDevice, NetatmoRoom
|
|
|
|
|
|
class NetatmoBaseEntity(Entity):
|
|
"""Netatmo entity base class."""
|
|
|
|
_attr_attribution = DEFAULT_ATTRIBUTION
|
|
_attr_has_entity_name = True
|
|
|
|
def __init__(self, data_handler: NetatmoDataHandler) -> None:
|
|
"""Set up Netatmo entity base."""
|
|
self.data_handler = data_handler
|
|
self._publishers: list[dict[str, Any]] = []
|
|
self._attr_extra_state_attributes = {}
|
|
|
|
async def async_added_to_hass(self) -> None:
|
|
"""Entity created."""
|
|
for publisher in self._publishers:
|
|
signal_name = publisher[SIGNAL_NAME]
|
|
|
|
if "home_id" in publisher:
|
|
await self.data_handler.subscribe(
|
|
publisher["name"],
|
|
signal_name,
|
|
self.async_update_callback,
|
|
home_id=publisher["home_id"],
|
|
)
|
|
|
|
elif publisher["name"] == PUBLIC:
|
|
await self.data_handler.subscribe(
|
|
publisher["name"],
|
|
signal_name,
|
|
self.async_update_callback,
|
|
lat_ne=publisher["lat_ne"],
|
|
lon_ne=publisher["lon_ne"],
|
|
lat_sw=publisher["lat_sw"],
|
|
lon_sw=publisher["lon_sw"],
|
|
)
|
|
|
|
else:
|
|
await self.data_handler.subscribe(
|
|
publisher["name"], signal_name, self.async_update_callback
|
|
)
|
|
|
|
if any(
|
|
sub is None
|
|
for sub in self.data_handler.publisher[signal_name].subscriptions
|
|
):
|
|
await self.data_handler.unsubscribe(signal_name, None)
|
|
|
|
self.async_update_callback()
|
|
|
|
async def async_will_remove_from_hass(self) -> None:
|
|
"""Run when entity will be removed from hass."""
|
|
await super().async_will_remove_from_hass()
|
|
|
|
for publisher in self._publishers:
|
|
await self.data_handler.unsubscribe(
|
|
publisher[SIGNAL_NAME], self.async_update_callback
|
|
)
|
|
|
|
@callback
|
|
def async_update_callback(self) -> None:
|
|
"""Update the entity's state."""
|
|
raise NotImplementedError
|
|
|
|
|
|
class NetatmoDeviceEntity(NetatmoBaseEntity):
|
|
"""Netatmo entity base class."""
|
|
|
|
def __init__(self, data_handler: NetatmoDataHandler, device: NetatmoBase) -> None:
|
|
"""Set up Netatmo entity base."""
|
|
super().__init__(data_handler)
|
|
self.device = device
|
|
|
|
@property
|
|
@abstractmethod
|
|
def device_type(self) -> DeviceType:
|
|
"""Return the device type."""
|
|
|
|
@property
|
|
def device_description(self) -> tuple[str, str]:
|
|
"""Return the model of this device."""
|
|
return DEVICE_DESCRIPTION_MAP[self.device_type]
|
|
|
|
@property
|
|
def home(self) -> Home:
|
|
"""Return the home this room belongs to."""
|
|
return self.device.home
|
|
|
|
|
|
class NetatmoRoomEntity(NetatmoDeviceEntity):
|
|
"""Netatmo room entity base class."""
|
|
|
|
device: Room
|
|
|
|
def __init__(self, room: NetatmoRoom) -> None:
|
|
"""Set up a Netatmo room entity."""
|
|
super().__init__(room.data_handler, room.room)
|
|
self._attr_device_info = DeviceInfo(
|
|
identifiers={(DOMAIN, room.room.entity_id)},
|
|
name=room.room.name,
|
|
manufacturer=self.device_description[0],
|
|
model=self.device_description[1],
|
|
configuration_url=CONF_URL_ENERGY,
|
|
suggested_area=room.room.name,
|
|
)
|
|
|
|
async def async_added_to_hass(self) -> None:
|
|
"""Entity created."""
|
|
await super().async_added_to_hass()
|
|
registry = dr.async_get(self.hass)
|
|
if device := registry.async_get_device(
|
|
identifiers={(DOMAIN, self.device.entity_id)}
|
|
):
|
|
self.hass.data[DOMAIN][DATA_DEVICE_IDS][self.device.entity_id] = device.id
|
|
|
|
@property
|
|
def device_type(self) -> DeviceType:
|
|
"""Return the device type."""
|
|
assert self.device.climate_type
|
|
return self.device.climate_type
|
|
|
|
|
|
class NetatmoModuleEntity(NetatmoDeviceEntity):
|
|
"""Netatmo module entity base class."""
|
|
|
|
device: Module
|
|
_attr_configuration_url: str
|
|
|
|
def __init__(self, device: NetatmoDevice) -> None:
|
|
"""Set up a Netatmo module entity."""
|
|
super().__init__(device.data_handler, device.device)
|
|
self._attr_device_info = DeviceInfo(
|
|
identifiers={(DOMAIN, device.device.entity_id)},
|
|
name=device.device.name,
|
|
manufacturer=self.device_description[0],
|
|
model=self.device_description[1],
|
|
configuration_url=self._attr_configuration_url,
|
|
)
|
|
|
|
@property
|
|
def device_type(self) -> DeviceType:
|
|
"""Return the device type."""
|
|
return self.device.device_type
|
|
|
|
|
|
class NetatmoWeatherModuleEntity(NetatmoModuleEntity):
|
|
"""Netatmo weather module entity base class."""
|
|
|
|
_attr_configuration_url = CONF_URL_WEATHER
|
|
|
|
def __init__(self, device: NetatmoDevice) -> None:
|
|
"""Set up a Netatmo weather module entity."""
|
|
super().__init__(device)
|
|
category = getattr(self.device.device_category, "name")
|
|
self._publishers.extend(
|
|
[
|
|
{
|
|
"name": category,
|
|
SIGNAL_NAME: category,
|
|
},
|
|
]
|
|
)
|
|
|
|
if hasattr(self.device, "place"):
|
|
place = cast(Place, getattr(self.device, "place"))
|
|
if hasattr(place, "location") and place.location is not None:
|
|
self._attr_extra_state_attributes.update(
|
|
{
|
|
ATTR_LATITUDE: place.location.latitude,
|
|
ATTR_LONGITUDE: place.location.longitude,
|
|
}
|
|
)
|
|
|
|
@property
|
|
def device_type(self) -> DeviceType:
|
|
"""Return the Netatmo device type."""
|
|
if "." not in self.device.device_type:
|
|
return super().device_type
|
|
return DeviceType(self.device.device_type.partition(".")[2])
|