1
mirror of https://github.com/home-assistant/core synced 2024-09-03 08:14:07 +02:00
ha-core/homeassistant/components/mazda/button.py
2022-03-09 04:16:07 +01:00

157 lines
4.6 KiB
Python

"""Platform for Mazda button integration."""
from __future__ import annotations
from collections.abc import Awaitable, Callable
from dataclasses import dataclass
from typing import Any
from pymazda import (
Client as MazdaAPIClient,
MazdaAccountLockedException,
MazdaAPIEncryptionException,
MazdaAuthenticationException,
MazdaException,
MazdaLoginFailedException,
MazdaTokenExpiredException,
)
from homeassistant.components.button import ButtonEntity, ButtonEntityDescription
from homeassistant.config_entries import ConfigEntry
from homeassistant.core import HomeAssistant
from homeassistant.exceptions import HomeAssistantError
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator
from . import MazdaEntity
from .const import DATA_CLIENT, DATA_COORDINATOR, DOMAIN
async def handle_button_press(
client: MazdaAPIClient,
key: str,
vehicle_id: int,
coordinator: DataUpdateCoordinator,
) -> None:
"""Handle a press for a Mazda button entity."""
api_method = getattr(client, key)
try:
await api_method(vehicle_id)
except (
MazdaException,
MazdaAuthenticationException,
MazdaAccountLockedException,
MazdaTokenExpiredException,
MazdaAPIEncryptionException,
MazdaLoginFailedException,
) as ex:
raise HomeAssistantError(ex) from ex
async def handle_refresh_vehicle_status(
client: MazdaAPIClient,
key: str,
vehicle_id: int,
coordinator: DataUpdateCoordinator,
) -> None:
"""Handle a request to refresh the vehicle status."""
await handle_button_press(client, key, vehicle_id, coordinator)
await coordinator.async_request_refresh()
@dataclass
class MazdaButtonRequiredKeysMixin:
"""Mixin for required keys."""
# Suffix to be appended to the vehicle name to obtain the button name
name_suffix: str
@dataclass
class MazdaButtonEntityDescription(
ButtonEntityDescription, MazdaButtonRequiredKeysMixin
):
"""Describes a Mazda button entity."""
# Function to determine whether the vehicle supports this button, given the coordinator data
is_supported: Callable[[dict[str, Any]], bool] = lambda data: True
async_press: Callable[
[MazdaAPIClient, str, int, DataUpdateCoordinator], Awaitable
] = handle_button_press
BUTTON_ENTITIES = [
MazdaButtonEntityDescription(
key="start_engine",
name_suffix="Start Engine",
icon="mdi:engine",
),
MazdaButtonEntityDescription(
key="stop_engine",
name_suffix="Stop Engine",
icon="mdi:engine-off",
),
MazdaButtonEntityDescription(
key="turn_on_hazard_lights",
name_suffix="Turn On Hazard Lights",
icon="mdi:hazard-lights",
),
MazdaButtonEntityDescription(
key="turn_off_hazard_lights",
name_suffix="Turn Off Hazard Lights",
icon="mdi:hazard-lights",
),
MazdaButtonEntityDescription(
key="refresh_vehicle_status",
name_suffix="Refresh Status",
icon="mdi:refresh",
async_press=handle_refresh_vehicle_status,
is_supported=lambda data: data["isElectric"],
),
]
async def async_setup_entry(
hass: HomeAssistant,
config_entry: ConfigEntry,
async_add_entities: AddEntitiesCallback,
) -> None:
"""Set up the button platform."""
client = hass.data[DOMAIN][config_entry.entry_id][DATA_CLIENT]
coordinator = hass.data[DOMAIN][config_entry.entry_id][DATA_COORDINATOR]
async_add_entities(
MazdaButtonEntity(client, coordinator, index, description)
for index, data in enumerate(coordinator.data)
for description in BUTTON_ENTITIES
if description.is_supported(data)
)
class MazdaButtonEntity(MazdaEntity, ButtonEntity):
"""Representation of a Mazda button."""
entity_description: MazdaButtonEntityDescription
def __init__(
self,
client: MazdaAPIClient,
coordinator: DataUpdateCoordinator,
index: int,
description: MazdaButtonEntityDescription,
) -> None:
"""Initialize Mazda button."""
super().__init__(client, coordinator, index)
self.entity_description = description
self._attr_name = f"{self.vehicle_name} {description.name_suffix}"
self._attr_unique_id = f"{self.vin}_{description.key}"
async def async_press(self) -> None:
"""Press the button."""
await self.entity_description.async_press(
self.client, self.entity_description.key, self.vehicle_id, self.coordinator
)