"""Models for aiorussound.""" from dataclasses import dataclass, field from enum import StrEnum from typing import Optional, Dict from mashumaro import field_options from mashumaro.mixins.orjson import DataClassORJSONMixin from mashumaro.types import SerializationStrategy from datetime import datetime, UTC class RussoundBool(SerializationStrategy): def deserialize(self, value: str) -> bool: if value and (value == "ON" or value == "TRUE"): return True return False class RussoundInt(SerializationStrategy): def deserialize(self, value: str) -> int: return int(value) class PartyMode(StrEnum): """Party mode.""" OFF = "OFF" ON = "ON" MASTER = "MASTER" @dataclass class Zone(DataClassORJSONMixin): """Data class representing Russound state.""" name: str = field(default=None) volume: int = field( metadata=field_options(serialization_strategy=RussoundInt()), default=0 ) bass: int = field( metadata=field_options(serialization_strategy=RussoundInt()), default=0 ) treble: int = field( metadata=field_options(serialization_strategy=RussoundInt()), default=0 ) balance: int = field( metadata=field_options(serialization_strategy=RussoundInt()), default=0 ) loudness: bool = field( metadata=field_options(serialization_strategy=RussoundBool()), default=False ) turn_on_volume: int = field( metadata=field_options( alias="turnOnVolume", serialization_strategy=RussoundInt() ), default=20, ) do_not_disturb: bool = field( metadata=field_options( alias="doNotDisturb", serialization_strategy=RussoundBool() ), default=False, ) party_mode: PartyMode = field( metadata=field_options(alias="partyMode"), default=PartyMode.OFF, ) status: bool = field( metadata=field_options(serialization_strategy=RussoundBool()), default=False ) is_mute: bool = field( metadata=field_options(alias="mute", serialization_strategy=RussoundBool()), default=False, ) shared_source: bool = field( metadata=field_options( alias="sharedSource", serialization_strategy=RussoundBool() ), default=False, ) last_error: Optional[str] = field( metadata=field_options(alias="lastError"), default=None ) page: Optional[str] = field(metadata=field_options(alias="page"), default=None) sleep_time_default: Optional[int] = field( metadata=field_options( alias="sleepTimeDefault", serialization_strategy=RussoundInt() ), default=None, ) sleep_time_remaining: Optional[int] = field( metadata=field_options( alias="sleepTimeRemaining", serialization_strategy=RussoundInt() ), default=None, ) enabled: bool = field( metadata=field_options(serialization_strategy=RussoundBool()), default=False ) current_source: int = field( metadata=field_options( alias="currentSource", serialization_strategy=RussoundInt() ), default=1, ) enabled_sources: list[int] = field( metadata=field_options(alias="enabled_sources"), default_factory=list ) class SourceType(StrEnum): """Russound source types.""" AMPLIFIER = "Amplifier" TELEVISION = "Television" CABLE = "Cable" VIDEO_ACCESSORY = "Video Accessory" SATELLITE = "Satellite" VCR = "VCR" BLURAY_DVD = "Blu-ray / DVD" RECEIVER = "Receiver" MISC_AUDIO = "Misc Audio" CD = "CD" HOME_CONTROL = "Home Control" RUSSOUND_MEDIA_STREAMER = "Russound Media Streamer" RUSSOUND_DMS_3_1_AM_FM_TUNER = "Russound DMS 3.1 AM/FM Tuner" RUSSOUND_ST_1_AM_FM_TUNER = "Russound ST.1 AM/FM Tuner" RUSSOUND_BLUETOOTH_MODULE = "Russound Bluetooth Module" class SourceMode(StrEnum): """Russound source modes.""" UNKNOWN = "Unknown" AIRPLAY = "AirPlay" SPOTIFY = "Spotify" PANDORA = "Pandora" SIRIUS_XM = "SiriusXM" TUNE_IN = "TuneIn" INTERNET_RADIO = "Internet Radio" MEDIA_SERVER = "Media Server" USB = "USB" AIRABLE_RADIO = "Airable Radio" DEEZER = "Deezer" TIDAL = "Tidal" NAPSTER = "Napster" CHROMECAST = "Chromecast" BLUETOOTH = "Bluetooth" class RepeatMode(StrEnum): """Repeat mode.""" OFF = "OFF" ALL = "ALL" SINGLE = "SINGLE" class PlayStatus(StrEnum): """Play status""" PLAYING = "playing" PAUSED = "paused" STOPPED = "stopped" TRANSITIONING = "transitioning" LOADING = "loading" @dataclass class Source(DataClassORJSONMixin): """Data class representing Russound source.""" name: str = field(default=None) type: SourceType = field( metadata={"deserialize": lambda v: SourceType.MISC_AUDIO if not v else v}, default=SourceType.MISC_AUDIO, ) channel: Optional[str] = field(default=None) cover_art_url: Optional[str] = field( metadata=field_options(alias="coverArtURL"), default=None ) channel_name: Optional[str] = field( metadata=field_options(alias="channelName"), default=None ) genre: Optional[str] = field(default=None) artist_name: Optional[str] = field( metadata=field_options(alias="artistName"), default=None ) album_name: Optional[str] = field( metadata=field_options(alias="albumName"), default=None ) playlist_name: Optional[str] = field( metadata=field_options(alias="playlistName"), default=None ) song_name: Optional[str] = field( metadata=field_options(alias="songName"), default=None ) program_service_name: Optional[str] = field( metadata=field_options(alias="programServiceName"), default=None ) radio_text: Optional[str] = field( metadata=field_options(alias="radioText"), default=None ) shuffle_mode: bool = field( metadata=field_options( alias="shuffleMode", serialization_strategy=RussoundBool() ), default=False, ) repeat_mode: Optional[RepeatMode] = field( metadata=field_options(alias="repeatMode"), default=None ) mode: SourceMode = field( metadata={"deserialize": lambda v: SourceMode.UNKNOWN if not v else v}, default=SourceMode.UNKNOWN, ) play_status: Optional[PlayStatus] = field( metadata=field_options(alias="playStatus"), default=None ) sample_rate: Optional[int] = field( metadata=field_options( alias="sampleRate", serialization_strategy=RussoundInt() ), default=None, ) bit_rate: Optional[int] = field( metadata=field_options(alias="bitRate", serialization_strategy=RussoundInt()), default=None, ) bit_depth: Optional[int] = field( metadata=field_options(alias="bitDepth", serialization_strategy=RussoundInt()), default=None, ) play_time: Optional[int] = field( metadata=field_options(alias="playTime", serialization_strategy=RussoundInt()), default=None, ) track_time: Optional[int] = field( metadata=field_options(alias="trackTime", serialization_strategy=RussoundInt()), default=None, ) presets: Optional[Dict[int, str]] = field( metadata=field_options(alias="presets"), default_factory=dict, ) position_last_updated: datetime = datetime.now(UTC) class CallbackType(StrEnum): """Callback type.""" STATE = "state" CONNECTION = "connection" class MessageType(StrEnum): """Message type.""" STATE = "S" NOTIFICATION = "N" ERROR = "E" @dataclass class RussoundMessage: """Incoming russound message.""" type: str branch: Optional[str] = None leaf: Optional[str] = None value: Optional[str] = None