"""Models for Husqvarna Automower data.""" from __future__ import annotations import logging from dataclasses import dataclass, field from typing import TYPE_CHECKING, Any from mashumaro import DataClassDictMixin, field_options from .model_battery import Battery # noqa: TC001 from .model_calendar import Tasks # noqa: TC001 from .model_capabilities import Capabilities # noqa: TC001 from .model_metadata import Metadata # noqa: TC001 from .model_mower import Mower # noqa: TC001 from .model_planner import Planner # noqa: TC001 from .model_positions import Positions # noqa: TC001 from .model_settings import Settings # noqa: TC001 from .model_statistics import Statistics # noqa: TC001 from .model_stay_out_zones import StayOutZones # noqa: TC001 from .model_system import System # noqa: TC001 from .model_work_areas import WorkArea if TYPE_CHECKING: from collections.abc import Mapping _LOGGER = logging.getLogger(__name__) def generate_work_area_names_list(workarea_list: Mapping[Any, Any]) -> list[str]: """Return a list of names extracted from each work area dictionary.""" wa_names = [WorkArea.from_dict(area).name for area in workarea_list] wa_names.append("no_work_area_active") return wa_names def generate_work_area_dict( workarea_list: Mapping[Any, Any] | None, ) -> dict[int, str] | None: """Return a dict of names extracted from each work area dictionary.""" if workarea_list is None: return None return { area["workAreaId"]: get_work_area_name(area["name"]) for area in workarea_list } def get_work_area_name(name: str) -> str: """Return the work area name. Replacing empty strings with a default name 'my_lawn'. """ return "my_lawn" if name == "" else name @dataclass class MowerAttributes(DataClassDictMixin): """DataClass for MowerAttributes.""" system: System battery: Battery capabilities: Capabilities mower: Mower calendar: Tasks planner: Planner metadata: Metadata positions: list[Positions] settings: Settings statistics: Statistics stay_out_zones: StayOutZones | None = field( metadata=field_options(alias="stayOutZones"), default=None ) work_areas: dict[int, WorkArea] | None = field( metadata=field_options( deserialize=lambda workarea_list: { area["workAreaId"]: WorkArea.from_dict(area) for area in workarea_list }, alias="workAreas", ), default=None, ) work_area_names: list[str] | None = field( metadata=field_options( deserialize=generate_work_area_names_list, alias="workAreas", ), default=None, ) work_area_dict: dict[int, str] | None = field( metadata=field_options( deserialize=generate_work_area_dict, alias="workAreas", ), default=None, ) def __post_init__(self) -> None: """Set the name after init.""" if self.capabilities.work_areas: if self.mower.work_area_id is None: self.mower.work_area_name = "no_work_area_active" if self.work_areas and self.mower.work_area_id is not None: work_area = self.work_areas.get(self.mower.work_area_id) if work_area: self.mower.work_area_name = work_area.name @dataclass class MowerData(DataClassDictMixin): """DataClass for MowerData values.""" type: str id: str attributes: MowerAttributes @dataclass class MowerList(DataClassDictMixin): """DataClass for a list of all mowers.""" data: list[MowerData] MowerDictionary = dict[str, MowerAttributes]