1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166
|
import enum
import logging
import click
from .click_common import command, format_output
from .device import Device, DeviceStatus
_LOGGER = logging.getLogger(__name__)
class PlayState(enum.Enum):
Playing = "PLAYING"
Stopped = "STOPPED"
Paused = "PAUSED_PLAYBACK"
NoMedia = "NO_MEDIA_PRESENT"
Transitioning = "TRANSITIONING"
class TransportChannel(enum.Enum):
Playlist = "PLAYLIST"
OneTime = "ONETIME"
Auxiliary = "AUX"
Bluetooth = "BT"
Radio = "RADIO"
Air = "AIR"
Qplay = "QPLAY"
class WifiSpeakerStatus(DeviceStatus):
"""Container of a speaker state.
This contains information such as the name of the device, and what is currently
being played by it.
"""
def __init__(self, data):
"""Example response of a xiaomi.wifispeaker.v2:
{"DeviceName": "Mi Internet Speaker", "channel_title\": "XXX",
"current_state": "PLAYING", "hardware_version": "S602",
"play_mode": "REPEAT_ALL", "track_artist": "XXX",
"track_duration": "00:04:58", "track_title": "XXX",
"transport_channel": "PLAYLIST"}
"""
self.data = data
@property
def device_name(self) -> str:
"""Name of the device."""
return self.data["DeviceName"]
@property
def channel(self) -> str:
"""Name of the channel."""
return self.data["channel_title"]
@property
def state(self) -> PlayState:
"""State of the device, e.g. PLAYING."""
return PlayState(self.data["current_state"])
@property
def hardware_version(self) -> str:
return self.data["hardware_version"]
@property
def play_mode(self):
"""Play mode such as REPEAT_ALL."""
# note: this can be enumized when all values are known
return self.data["play_mode"]
@property
def track_artist(self) -> str:
"""Artist of the current track."""
return self.data["track_artist"]
@property
def track_title(self) -> str:
"""Title of the current track."""
return self.data["track_title"]
@property
def track_duration(self) -> str:
"""Total duration of the current track."""
return self.data["track_duration"]
@property
def transport_channel(self) -> TransportChannel:
"""Transport channel, e.g. PLAYLIST."""
return TransportChannel(self.data["transport_channel"])
class WifiSpeaker(Device):
"""Device class for Xiaomi Smart Wifi Speaker."""
_supported_models = ["xiaomi.wifispeaker.v2"]
@command(
default_output=format_output(
"",
"Device name: {result.device_name}\n"
"Channel: {result.channel}\n"
"State: {result.state}\n"
"Play mode: {result.play_mode}\n"
"Track artist: {result.track_artist}\n"
"Track title: {result.track_title}\n"
"Track duration: {result.track_duration}\n"
"Transport channel: {result.transport_channel}\n"
"Hardware version: {result.hardware_version}\n",
)
)
def status(self) -> WifiSpeakerStatus:
"""Return device status."""
return WifiSpeakerStatus(self.send("get_prop", ["umi"]))
@command(default_output=format_output("Powering on"))
def power(self):
"""Toggle power on and off."""
# is this a toggle?
return self.send("power")
@command(default_output=format_output("Toggling play"))
def toggle(self):
"""Toggle play."""
return self.send("toggle")
@command(
click.argument("amount", type=int),
default_output=format_output("Increasing volume by {amount} percent"),
)
def volume_up(self, amount: int = 5):
"""Set volume up."""
return self.send("vol_up", [amount])
@command(
click.argument("amount", type=int),
default_output=format_output("Decreasing volume by {amount} percent"),
)
def volume_down(self, amount: int = 5):
"""Set volume down."""
return self.send("vol_down", [amount])
@command(default_output=format_output("Playing previous track"))
def track_previous(self):
"""Move to previous track."""
return self.send("previous_track")
@command(default_output=format_output("Playing next track"))
def track_next(self):
"""Move to next track."""
return self.send("next_track")
@command(default_output=format_output("Switching to the next transport channel"))
def channel_next(self):
"""Change transport channel."""
return self.send("next_channel")
@command(default_output=format_output("Track position: {result.rel_time}"))
def track_position(self):
"""Return current track position."""
return self.send("get_prop", ["rel_time"])
def volume(self):
"""Speaker volume."""
return self.send("get_prop", ["volume"])
|