From dd7bffc28cb41a7dea4e0dec76defaa629bb1bfe Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Simon=20N=C3=B8rager=20S=C3=B8rensen?=
 <6843486+fattdev@users.noreply.github.com>
Date: Sat, 17 Feb 2018 00:09:20 +0100
Subject: [PATCH] Add the Xiaomi TV platform. (#12359)

* Added the Xiaomi TV platform.

* Implemented a more efficient default name.

* Fixed a few style errors that slipped past the eye.

* Indicate that state is assumed.
---
 .coveragerc                                   |   1 +
 CODEOWNERS                                    |   1 +
 .../components/media_player/xiaomi_tv.py      | 112 ++++++++++++++++++
 requirements_all.txt                          |   3 +
 4 files changed, 117 insertions(+)
 create mode 100644 homeassistant/components/media_player/xiaomi_tv.py

diff --git a/.coveragerc b/.coveragerc
index 4b19519038f..ec41cf05b7c 100644
--- a/.coveragerc
+++ b/.coveragerc
@@ -462,6 +462,7 @@ omit =
     homeassistant/components/media_player/vizio.py
     homeassistant/components/media_player/vlc.py
     homeassistant/components/media_player/volumio.py
+    homeassistant/components/media_player/xiaomi_tv.py
     homeassistant/components/media_player/yamaha.py
     homeassistant/components/media_player/yamaha_musiccast.py
     homeassistant/components/media_player/ziggo_mediabox_xl.py
diff --git a/CODEOWNERS b/CODEOWNERS
index af887118923..e7811d7fdeb 100644
--- a/CODEOWNERS
+++ b/CODEOWNERS
@@ -56,6 +56,7 @@ homeassistant/components/light/yeelight.py @rytilahti
 homeassistant/components/media_player/kodi.py @armills
 homeassistant/components/media_player/mediaroom.py @dgomes
 homeassistant/components/media_player/monoprice.py @etsinko
+homeassistant/components/media_player/xiaomi_tv.py @fattdev
 homeassistant/components/media_player/yamaha_musiccast.py @jalmeroth
 homeassistant/components/plant.py @ChristianKuehnel
 homeassistant/components/sensor/airvisual.py @bachya
diff --git a/homeassistant/components/media_player/xiaomi_tv.py b/homeassistant/components/media_player/xiaomi_tv.py
new file mode 100644
index 00000000000..be40bf7d010
--- /dev/null
+++ b/homeassistant/components/media_player/xiaomi_tv.py
@@ -0,0 +1,112 @@
+"""
+Add support for the Xiaomi TVs.
+
+For more details about this platform, please refer to the documentation at
+https://home-assistant.io/components/xiaomi_tv/
+"""
+
+import logging
+import voluptuous as vol
+import homeassistant.helpers.config_validation as cv
+from homeassistant.const import (CONF_HOST, CONF_NAME, STATE_OFF, STATE_ON)
+from homeassistant.components.media_player import (
+    SUPPORT_TURN_ON, SUPPORT_TURN_OFF, MediaPlayerDevice, PLATFORM_SCHEMA,
+    SUPPORT_VOLUME_STEP)
+
+REQUIREMENTS = ['pymitv==1.0.0']
+
+DEFAULT_NAME = "Xiaomi TV"
+
+_LOGGER = logging.getLogger(__name__)
+
+SUPPORT_XIAOMI_TV = SUPPORT_VOLUME_STEP | SUPPORT_TURN_ON | \
+                    SUPPORT_TURN_OFF
+
+# No host is needed for configuration, however it can be set.
+PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
+    vol.Optional(CONF_HOST): cv.string,
+    vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string,
+})
+
+
+def setup_platform(hass, config, add_devices, discovery_info=None):
+    """Set up the Xiaomi TV platform."""
+    from pymitv import Discover
+
+    # If a hostname is set. Discovery is skipped.
+    host = config.get(CONF_HOST)
+    name = config.get(CONF_NAME)
+
+    if host is not None:
+        # Check if there's a valid TV at the IP address.
+        if not Discover().checkIp(host):
+            _LOGGER.error(
+                "Could not find Xiaomi TV with specified IP: %s", host
+            )
+        else:
+            # Register TV with Home Assistant.
+            add_devices([XiaomiTV(host, name)])
+    else:
+        # Otherwise, discover TVs on network.
+        add_devices(XiaomiTV(tv, DEFAULT_NAME) for tv in Discover().scan())
+
+
+class XiaomiTV(MediaPlayerDevice):
+    """Represent the Xiaomi TV for Home Assistant."""
+
+    def __init__(self, ip, name):
+        """Receive IP address and name to construct class."""
+        # Import pymitv library.
+        from pymitv import TV
+
+        # Initialize the Xiaomi TV.
+        self._tv = TV(ip)
+        # Default name value, only to be overridden by user.
+        self._name = name
+        self._state = STATE_OFF
+
+    @property
+    def name(self):
+        """Return the display name of this TV."""
+        return self._name
+
+    @property
+    def state(self):
+        """Return _state variable, containing the appropriate constant."""
+        return self._state
+
+    @property
+    def assumed_state(self):
+        """Indicate that state is assumed."""
+        return True
+
+    @property
+    def supported_features(self):
+        """Flag media player features that are supported."""
+        return SUPPORT_XIAOMI_TV
+
+    def turn_off(self):
+        """
+        Instruct the TV to turn sleep.
+
+        This is done instead of turning off,
+        because the TV won't accept any input when turned off. Thus, the user
+        would be unable to turn the TV back on, unless it's done manually.
+        """
+        self._tv.sleep()
+
+        self._state = STATE_OFF
+
+    def turn_on(self):
+        """Wake the TV back up from sleep."""
+        self._tv.wake()
+
+        self._state = STATE_ON
+
+    def volume_up(self):
+        """Increase volume by one."""
+        self._tv.volume_up()
+
+    def volume_down(self):
+        """Decrease volume by one."""
+        self._tv.volume_down()
diff --git a/requirements_all.txt b/requirements_all.txt
index c226adc6ae8..5fbc448c015 100644
--- a/requirements_all.txt
+++ b/requirements_all.txt
@@ -787,6 +787,9 @@ pymailgunner==1.4
 # homeassistant.components.media_player.mediaroom
 pymediaroom==0.5
 
+# homeassistant.components.media_player.xiaomi_tv
+pymitv==1.0.0
+
 # homeassistant.components.mochad
 pymochad==0.2.0
 
-- 
GitLab