forked from platypush/platypush
166 lines
4.9 KiB
Python
166 lines
4.9 KiB
Python
from typing import Union, Dict, List
|
|
|
|
from pyHS100 import SmartDevice, SmartPlug, SmartBulb, SmartStrip, Discover, SmartDeviceException
|
|
|
|
from platypush.plugins import action
|
|
from platypush.plugins.switch import SwitchPlugin
|
|
|
|
|
|
class SwitchTplinkPlugin(SwitchPlugin):
|
|
"""
|
|
Plugin to interact with TP-Link smart switches/plugs like the HS100
|
|
(https://www.tp-link.com/us/products/details/cat-5516_HS100.html).
|
|
|
|
Requires:
|
|
|
|
* **pyHS100** (``pip install pyHS100``)
|
|
|
|
"""
|
|
|
|
_ip_to_dev = {}
|
|
_alias_to_dev = {}
|
|
|
|
def __init__(self, plugs: Union[Dict[str, str], List[str]] = None, bulbs: Union[Dict[str, str], List[str]] = None,
|
|
strips: Union[Dict[str, str], List[str]] = None, **kwargs):
|
|
"""
|
|
:param plugs: Optional list of IP addresses or name->address mapping if you have a static list of
|
|
TpLink plugs and you want to save on the scan time.
|
|
:param bulbs: Optional list of IP addresses or name->address mapping if you have a static list of
|
|
TpLink bulbs and you want to save on the scan time.
|
|
:param strips: Optional list of IP addresses or name->address mapping if you have a static list of
|
|
TpLink strips and you want to save on the scan time.
|
|
"""
|
|
super().__init__(**kwargs)
|
|
self._ip_to_dev = {}
|
|
self._alias_to_dev = {}
|
|
self._static_devices = {}
|
|
|
|
if isinstance(plugs, list):
|
|
plugs = {addr: addr for addr in plugs}
|
|
if isinstance(bulbs, list):
|
|
bulbs = {addr: addr for addr in bulbs}
|
|
if isinstance(strips, list):
|
|
strips = {addr: addr for addr in strips}
|
|
|
|
for name, addr in (plugs or {}).items():
|
|
self._static_devices[addr] = {
|
|
'name': name,
|
|
'type': SmartPlug,
|
|
}
|
|
|
|
for name, addr in (bulbs or {}).items():
|
|
self._static_devices[addr] = {
|
|
'name': name,
|
|
'type': SmartBulb,
|
|
}
|
|
|
|
for name, addr in (strips or {}).items():
|
|
self._static_devices[addr] = {
|
|
'name': name,
|
|
'type': SmartStrip,
|
|
}
|
|
|
|
self._update_devices()
|
|
|
|
def _update_devices(self, devices: Dict[str, SmartDevice] = None):
|
|
for (addr, info) in self._static_devices.items():
|
|
try:
|
|
dev = info['type'](addr)
|
|
self._alias_to_dev[info.get('name', dev.alias)] = dev
|
|
self._ip_to_dev[addr] = dev
|
|
except SmartDeviceException as e:
|
|
self.logger.warning('Could not communicate with device {}: {}'.format(addr, str(e)))
|
|
|
|
for (ip, dev) in (devices or {}).items():
|
|
self._ip_to_dev[ip] = dev
|
|
self._alias_to_dev[dev.alias] = dev
|
|
|
|
def _scan(self):
|
|
devices = Discover.discover()
|
|
self._update_devices(devices)
|
|
return devices
|
|
|
|
def _get_device(self, device, use_cache=True):
|
|
if not use_cache:
|
|
self._scan()
|
|
|
|
if device in self._ip_to_dev:
|
|
return self._ip_to_dev[device]
|
|
|
|
if device in self._alias_to_dev:
|
|
return self._alias_to_dev[device]
|
|
|
|
if use_cache:
|
|
return self._get_device(device, use_cache=False)
|
|
else:
|
|
raise RuntimeError('Device {} not found'.format(device))
|
|
|
|
@action
|
|
def on(self, device, **kwargs):
|
|
"""
|
|
Turn on a device
|
|
|
|
:param device: Device IP, hostname or alias
|
|
:type device: str
|
|
"""
|
|
|
|
device = self._get_device(device)
|
|
device.turn_on()
|
|
return self.status(device)
|
|
|
|
@action
|
|
def off(self, device, **kwargs):
|
|
"""
|
|
Turn off a device
|
|
|
|
:param device: Device IP, hostname or alias
|
|
:type device: str
|
|
"""
|
|
|
|
device = self._get_device(device)
|
|
device.turn_off()
|
|
return self.status(device)
|
|
|
|
@action
|
|
def toggle(self, device, **kwargs):
|
|
"""
|
|
Toggle the state of a device (on/off)
|
|
|
|
:param device: Device IP, hostname or alias
|
|
:type device: str
|
|
"""
|
|
|
|
device = self._get_device(device)
|
|
|
|
if device.is_on:
|
|
device.turn_off()
|
|
else:
|
|
device.turn_on()
|
|
|
|
return {
|
|
'current_consumption': device.current_consumption(),
|
|
'id': device.host,
|
|
'ip': device.host,
|
|
'host': device.host,
|
|
'hw_info': device.hw_info,
|
|
'name': device.alias,
|
|
'on': device.is_on,
|
|
}
|
|
|
|
@property
|
|
def devices(self):
|
|
return [
|
|
{
|
|
'current_consumption': dev.current_consumption(),
|
|
'id': ip,
|
|
'ip': ip,
|
|
'host': dev.host,
|
|
'hw_info': dev.hw_info,
|
|
'name': dev.alias,
|
|
'on': dev.is_on,
|
|
} for (ip, dev) in self._scan().items()
|
|
]
|
|
|
|
|
|
# vim:sw=4:ts=4:et:
|