├── pyproject.toml
├── custom_components
└── hisensetv
│ ├── pyproject.toml
│ ├── __init__.py
│ ├── manifest.json
│ └── switch.py
├── hacs.json
├── .travis.yml
└── README.rst
/pyproject.toml:
--------------------------------------------------------------------------------
1 | [tool.black]
2 | line-length=79
3 |
--------------------------------------------------------------------------------
/custom_components/hisensetv/pyproject.toml:
--------------------------------------------------------------------------------
1 | [tool.black]
2 | line-length=79
3 |
--------------------------------------------------------------------------------
/custom_components/hisensetv/__init__.py:
--------------------------------------------------------------------------------
1 | """ Hisense Television Integration. """
2 |
--------------------------------------------------------------------------------
/hacs.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "Hisense Television",
3 | "domains": ["switch"]
4 | }
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: python
2 | python:
3 | - "3.7"
4 | - "3.8"
5 | install:
6 | - pip install flake8>=3.8.2 flake8-bugbear>=20.1.4 pep8-naming>=0.10.0
7 | - pip install black>=19.10b0
8 | script:
9 | - black --check .
10 | - flake8
11 |
--------------------------------------------------------------------------------
/custom_components/hisensetv/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "domain": "hisensetv",
3 | "name": "Hisense Television",
4 | "documentation": "https://developers.home-assistant.io/docs/creating_integration_manifest/",
5 | "dependencies": [],
6 | "codeowners": ["@newAM"],
7 | "requirements": ["hisensetv==0.0.7", "wakeonlan==1.1.6"]
8 | }
9 |
--------------------------------------------------------------------------------
/README.rst:
--------------------------------------------------------------------------------
1 | README
2 | ######
3 |
4 | |hacs_badge| |Build Status|
5 |
6 | **Update 2020-07-09** This repository is no longer maintained. I do not use this component anymore. I found that my TV would drop the Ethernet connection and require physically unplugging/replugging it to maintain connectivity.
7 |
8 | Installation
9 | ************
10 | Place the ``custom_components`` folder into your configuration directory
11 | (or add its contents to an existing ``custom_components`` folder).
12 |
13 | Alternatively install with `HACS `_.
14 |
15 | Authentication
16 | **************
17 | You will need to perform one-time authentication for the API to work.
18 |
19 | This authentication can be performed on your local computer, or on your
20 | home-assistant server.
21 |
22 | .. code:: bash
23 |
24 | pip install hisensetv
25 | hisensetv 10.0.0.28 --authorize
26 |
27 | See `newAM/hisensetv `_ for more details.
28 |
29 | Configuration
30 | *************
31 |
32 | .. code:: yaml
33 |
34 | switch:
35 | - platform: hisensetv
36 | host: 10.0.0.28
37 | mac: ab:cd:ef:12:34:56
38 | name: tv
39 |
40 | * ``host`` is the (static) IP address of your TV.
41 | * ``mac`` if the TVs MAC address for Wake on LAN (WOL).
42 |
43 | Warning
44 | *******
45 | This is provided **as-is**.
46 | This is my first time going this deep into homeassistant and I have no idea
47 | if I have horribly messed something up.
48 |
49 | .. |hacs_badge| image:: https://img.shields.io/badge/HACS-Custom-orange.svg
50 | :target: https://github.com/custom-components/hacs
51 | .. |Build Status| image:: https://api.travis-ci.com/newAM/hisensetv_hass.svg?branch=master
52 | :target: https://travis-ci.com/newAM/hisensetv_hass
53 |
--------------------------------------------------------------------------------
/custom_components/hisensetv/switch.py:
--------------------------------------------------------------------------------
1 | """ Hisense Television Integration. """
2 | from hisensetv import HisenseTv
3 | from homeassistant.components.switch import PLATFORM_SCHEMA
4 | from homeassistant.components.switch import SwitchDevice
5 | from homeassistant.const import CONF_BROADCAST_ADDRESS
6 | from homeassistant.const import CONF_HOST
7 | from homeassistant.const import CONF_MAC
8 | from homeassistant.const import CONF_NAME
9 | from homeassistant.helpers.typing import ConfigType
10 | from homeassistant.helpers.typing import HomeAssistantType
11 | from typing import Callable
12 | from typing import Optional
13 | import homeassistant.helpers.config_validation as cv
14 | import logging
15 | import platform
16 | import socket
17 | import subprocess as sp
18 | import voluptuous as vol
19 | import wakeonlan
20 | import time
21 |
22 | _LOGGER = logging.getLogger(__name__)
23 |
24 | DEFAULT_NAME = "tv"
25 | DEFAULT_PING_TIMEOUT = 1
26 |
27 | DOMAIN = "hisensetv"
28 | _LOGGER = logging.getLogger(__name__)
29 |
30 | PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend(
31 | {
32 | vol.Required(CONF_HOST): cv.string,
33 | vol.Required(CONF_MAC): cv.string,
34 | vol.Optional(CONF_BROADCAST_ADDRESS): cv.string,
35 | vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string,
36 | }
37 | )
38 |
39 |
40 | def setup_platform(
41 | hass: HomeAssistantType,
42 | config: ConfigType,
43 | add_entities: Callable,
44 | discovery_info: Optional[dict] = None,
45 | ):
46 | """Set up a Hisense TV."""
47 | broadcast_address = config.get(CONF_BROADCAST_ADDRESS)
48 | host = config[CONF_HOST]
49 | mac = config[CONF_MAC]
50 | name = config[CONF_NAME]
51 |
52 | add_entities(
53 | [
54 | HisenseTvEntity(
55 | host=host,
56 | mac=mac,
57 | name=name,
58 | broadcast_address=broadcast_address,
59 | )
60 | ],
61 | True,
62 | )
63 |
64 |
65 | class HisenseTvEntity(SwitchDevice):
66 | def __init__(self, host: str, mac: str, name: str, broadcast_address: str):
67 | self._name = name
68 | self._host = host
69 | self._mac = mac
70 | self._broadcast_address = broadcast_address
71 | self._is_on = True
72 | self._state = False
73 | self._last_state_change = 0
74 |
75 | def turn_on(self, **kwargs):
76 | if self._broadcast_address:
77 | wakeonlan.send_magic_packet(
78 | self._mac, ip_address=self._broadcast_address
79 | )
80 | else:
81 | wakeonlan.send_magic_packet(self._mac)
82 |
83 | self._state = True
84 | self._last_state_change = time.monotonic()
85 |
86 | def turn_off(self, **kwargs):
87 | try:
88 | with HisenseTv(self._host) as tv:
89 | tv.send_key_power()
90 | self._state = False
91 | self._last_state_change = time.monotonic()
92 | except socket.error as e:
93 | if "host is unreachable" in str(e).lower():
94 | _LOGGER.debug("unable to reach TV, likely powered off already")
95 | else:
96 | raise
97 |
98 | @property
99 | def is_on(self):
100 | """Return true if switch is on."""
101 | return self._state
102 |
103 | @property
104 | def name(self):
105 | """Return the name of the switch."""
106 | return self._name
107 |
108 | def update(self):
109 | """Check if device is on and update the state."""
110 | # skip updating via ping if power state has changed in last 15s
111 | if time.monotonic() - self._last_state_change < 15:
112 | return
113 |
114 | if platform.system().lower() == "windows":
115 | ping_cmd = [
116 | "ping",
117 | "-n",
118 | "1",
119 | "-w",
120 | str(DEFAULT_PING_TIMEOUT * 1000),
121 | str(self._host),
122 | ]
123 | else:
124 | ping_cmd = [
125 | "ping",
126 | "-c",
127 | "1",
128 | "-W",
129 | str(DEFAULT_PING_TIMEOUT),
130 | str(self._host),
131 | ]
132 |
133 | status = sp.call(ping_cmd, stdout=sp.DEVNULL, stderr=sp.DEVNULL)
134 | self._state = not bool(status)
135 |
--------------------------------------------------------------------------------