Learn more  » Push, build, and install  RubyGems npm packages Python packages Maven artifacts PHP packages Go Modules Bower components Debian packages RPM packages NuGet packages

aroundthecode / python-miio   python

Repository URL to install this package:

Version: 0.4.4 

/ wifispeaker.py

import enum
import logging
import warnings

import click

from .click_common import command, format_output
from .device import Device

_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:
    """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"])

    def __repr__(self) -> str:
        s = "<WifiSpeakerStatus " \
            "device_name=%s, " \
            "channel=%s, " \
            "state=%s, " \
            "play_mode=%s, " \
            "track_artist=%s, " \
            "track_title=%s, " \
            "track_duration=%s, " \
            "transport_channel=%s, " \
            "hardware_version=%s>" % \
            (self.device_name,
             self.channel,
             self.state,
             self.play_mode,
             self.track_artist,
             self.track_title,
             self.track_duration,
             self.transport_channel,
             self.hardware_version)

        return s

    def __json__(self):
        return self.data


class WifiSpeaker(Device):
    """Device class for Xiaomi Smart Wifi Speaker."""
    def __init__(self, *args, **kwargs):
        warnings.warn("Please help to complete this by providing more "
                      "information about possible values for `state`, "
                      "`play_mode` and `transport_channel`.", stacklevel=2)
        super().__init__(*args, **kwargs)

    @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"])