1
0
mirror of https://github.com/home-assistant/core.git synced 2026-04-30 21:51:29 +01:00
Files
core/homeassistant/components/kostal_plenticore/switch.py
Maximilian Arzberger bf88fcd5bf Add Manual Charge Switch for Installers for Kostal Plenticore (#146932)
* Add Manual Charge Switch for Installers

* Update stale docstring

* Installer config fixture

* fix ruff
2025-06-26 19:50:27 +02:00

192 lines
6.4 KiB
Python

"""Platform for Kostal Plenticore switches."""
from __future__ import annotations
from dataclasses import dataclass
from datetime import timedelta
import logging
from typing import Any
from homeassistant.components.switch import SwitchEntity, SwitchEntityDescription
from homeassistant.const import EntityCategory
from homeassistant.core import HomeAssistant
from homeassistant.helpers.device_registry import DeviceInfo
from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback
from homeassistant.helpers.update_coordinator import CoordinatorEntity
from .const import CONF_SERVICE_CODE
from .coordinator import PlenticoreConfigEntry, SettingDataUpdateCoordinator
_LOGGER = logging.getLogger(__name__)
@dataclass(frozen=True, kw_only=True)
class PlenticoreSwitchEntityDescription(SwitchEntityDescription):
"""A class that describes plenticore switch entities."""
module_id: str
is_on: str
on_value: str
on_label: str
off_value: str
off_label: str
installer_required: bool = False
SWITCH_SETTINGS_DATA = [
PlenticoreSwitchEntityDescription(
module_id="devices:local",
key="Battery:Strategy",
name="Battery Strategy",
is_on="1",
on_value="1",
on_label="Automatic",
off_value="2",
off_label="Automatic economical",
),
PlenticoreSwitchEntityDescription(
module_id="devices:local",
key="Battery:ManualCharge",
name="Battery Manual Charge",
is_on="1",
on_value="1",
on_label="On",
off_value="0",
off_label="Off",
installer_required=True,
),
]
async def async_setup_entry(
hass: HomeAssistant,
entry: PlenticoreConfigEntry,
async_add_entities: AddConfigEntryEntitiesCallback,
) -> None:
"""Add kostal plenticore Switch."""
plenticore = entry.runtime_data
entities = []
available_settings_data = await plenticore.client.get_settings()
settings_data_update_coordinator = SettingDataUpdateCoordinator(
hass, entry, _LOGGER, "Settings Data", timedelta(seconds=30), plenticore
)
for description in SWITCH_SETTINGS_DATA:
if (
description.module_id not in available_settings_data
or description.key
not in (
setting.id for setting in available_settings_data[description.module_id]
)
):
_LOGGER.debug(
"Skipping non existing setting data %s/%s",
description.module_id,
description.key,
)
continue
if entry.data.get(CONF_SERVICE_CODE) is None and description.installer_required:
_LOGGER.debug(
"Skipping installer required setting data %s/%s",
description.module_id,
description.key,
)
continue
entities.append(
PlenticoreDataSwitch(
settings_data_update_coordinator,
description,
entry.entry_id,
entry.title,
plenticore.device_info,
)
)
async_add_entities(entities)
class PlenticoreDataSwitch(
CoordinatorEntity[SettingDataUpdateCoordinator], SwitchEntity
):
"""Representation of a Plenticore Switch."""
_attr_entity_category = EntityCategory.CONFIG
entity_description: PlenticoreSwitchEntityDescription
def __init__(
self,
coordinator: SettingDataUpdateCoordinator,
description: PlenticoreSwitchEntityDescription,
entry_id: str,
platform_name: str,
device_info: DeviceInfo,
) -> None:
"""Create a new Switch Entity for Plenticore process data."""
super().__init__(coordinator)
self.entity_description = description
self.platform_name = platform_name
self.module_id = description.module_id
self.data_id = description.key
self._name = description.name
self._is_on = description.is_on
self._attr_name = f"{platform_name} {description.name}"
self.on_value = description.on_value
self.on_label = description.on_label
self.off_value = description.off_value
self.off_label = description.off_label
self._attr_unique_id = f"{entry_id}_{description.module_id}_{description.key}"
self._attr_device_info = device_info
@property
def available(self) -> bool:
"""Return if entity is available."""
return (
super().available
and self.coordinator.data is not None
and self.module_id in self.coordinator.data
and self.data_id in self.coordinator.data[self.module_id]
)
async def async_added_to_hass(self) -> None:
"""Register this entity on the Update Coordinator."""
await super().async_added_to_hass()
self.async_on_remove(
self.coordinator.start_fetch_data(self.module_id, self.data_id)
)
async def async_will_remove_from_hass(self) -> None:
"""Unregister this entity from the Update Coordinator."""
self.coordinator.stop_fetch_data(self.module_id, self.data_id)
await super().async_will_remove_from_hass()
async def async_turn_on(self, **kwargs: Any) -> None:
"""Turn device on."""
if await self.coordinator.async_write_data(
self.module_id, {self.data_id: self.on_value}
):
self.coordinator.name = f"{self.platform_name} {self._name} {self.on_label}"
await self.coordinator.async_request_refresh()
async def async_turn_off(self, **kwargs: Any) -> None:
"""Turn device off."""
if await self.coordinator.async_write_data(
self.module_id, {self.data_id: self.off_value}
):
self.coordinator.name = (
f"{self.platform_name} {self._name} {self.off_label}"
)
await self.coordinator.async_request_refresh()
@property
def is_on(self) -> bool:
"""Return true if device is on."""
if self.coordinator.data[self.module_id][self.data_id] == self._is_on:
self.coordinator.name = f"{self.platform_name} {self._name} {self.on_label}"
else:
self.coordinator.name = (
f"{self.platform_name} {self._name} {self.off_label}"
)
return bool(self.coordinator.data[self.module_id][self.data_id] == self._is_on)