Properly detect advertised features, expose alias

Signed-off-by: Martin Weinelt <hexa@darmstadt.ccc.de>
This commit is contained in:
Martin Weinelt 2016-11-22 00:39:17 +01:00
parent 08fb487a06
commit 33b2800fe8
No known key found for this signature in database
GPG Key ID: BD4AA0528F63F17E

View File

@ -15,18 +15,25 @@
import datetime import datetime
import json import json
import logging import logging
import re
import socket import socket
import sys import sys
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
# possible device features
FEATURE_ENERGY_METER = 'ENE'
FEATURE_TIMER = 'TIM'
ALL_FEATURES = (FEATURE_ENERGY_METER, FEATURE_TIMER)
class SmartPlug(object): class SmartPlug(object):
"""Representation of a TP-Link Smart Switch. """Representation of a TP-Link Smart Switch.
Usage example when used as library: Usage example when used as library:
p = SmartPlug("192.168.1.105") p = SmartPlug("192.168.1.105")
# print the devices alias
print(p.alias)
# change state of plug # change state of plug
p.state = "OFF" p.state = "OFF"
p.state = "ON" p.state = "ON"
@ -39,15 +46,13 @@ class SmartPlug(object):
def __init__(self, ip): def __init__(self, ip):
"""Create a new SmartPlug instance identified by the IP.""" """Create a new SmartPlug instance identified by the IP."""
self.ip = ip self.ip = ip
self.port = 9999 self.alias, self.model, self.features = self.identify()
self._error_report = False
self.model = self._identify_model()
@property @property
def state(self): def state(self):
"""Get the device state (i.e. ON or OFF).""" """Get the device state (i.e. ON or OFF)."""
response = self.get_info() response = self.get_sysinfo()
relay_state = response["system"]["get_sysinfo"]["relay_state"] relay_state = response['relay_state']
if relay_state is None: if relay_state is None:
return 'unknown' return 'unknown'
@ -74,10 +79,11 @@ class SmartPlug(object):
else: else:
raise TypeError("State %s is not valid." % str(value)) raise TypeError("State %s is not valid." % str(value))
def get_info(self): def get_sysinfo(self):
"""Interrogate the switch""" """Interrogate the switch"""
return TPLinkSmartHomeProtocol.query( return TPLinkSmartHomeProtocol.query(
host=self.ip, request='{"system":{"get_sysinfo":{}}}') host=self.ip, request='{"system":{"get_sysinfo":{}}}'
)['system']['get_sysinfo']
def turn_on(self): def turn_on(self):
"""Turns the switch on """Turns the switch on
@ -109,6 +115,10 @@ class SmartPlug(object):
return False return False
@property
def has_emeter(self):
return FEATURE_ENERGY_METER in self.features
def get_emeter_realtime(self): def get_emeter_realtime(self):
"""Gets the current energy readings from the switch """Gets the current energy readings from the switch
@ -116,7 +126,7 @@ class SmartPlug(object):
False if command is not successful or the switch doesn't support energy metering False if command is not successful or the switch doesn't support energy metering
Dict with the current readings Dict with the current readings
""" """
if self.model != 110: if not self.has_emeter:
return False return False
response = TPLinkSmartHomeProtocol.query( response = TPLinkSmartHomeProtocol.query(
@ -139,7 +149,7 @@ class SmartPlug(object):
False if command is not successful or the switch doesn't support energy metering False if command is not successful or the switch doesn't support energy metering
Dict where the keys represent the days, and the values are the aggregated statistics Dict where the keys represent the days, and the values are the aggregated statistics
""" """
if self.model != 110: if not self.has_emeter:
return False return False
response = TPLinkSmartHomeProtocol.query( response = TPLinkSmartHomeProtocol.query(
@ -166,7 +176,7 @@ class SmartPlug(object):
False if command is not successful or the switch doesn't support energy metering False if command is not successful or the switch doesn't support energy metering
Dict - the keys represent the months, the values are the aggregated statistics Dict - the keys represent the months, the values are the aggregated statistics
""" """
if self.model != 110: if not self.has_emeter:
return False return False
response = TPLinkSmartHomeProtocol.query( response = TPLinkSmartHomeProtocol.query(
@ -190,7 +200,7 @@ class SmartPlug(object):
True: Success True: Success
False: Failure or not supported by switch False: Failure or not supported by switch
""" """
if self.model != 110: if not self.has_emeter:
return False return False
response = TPLinkSmartHomeProtocol.query( response = TPLinkSmartHomeProtocol.query(
@ -203,18 +213,30 @@ class SmartPlug(object):
def current_consumption(self): def current_consumption(self):
"""Get the current power consumption in Watt.""" """Get the current power consumption in Watt."""
if self.model != 110: if not self.has_emeter:
return False return False
response = self.get_emeter_realtime() response = self.get_emeter_realtime()
return response["power"] return response["power"]
def _identify_model(self): def identify(self):
"""Query sysinfo and determine model""" """
sys_info = self.get_info() Query device information to identify model and featureset
model = re.sub('HS', '', sys_info["system"]["get_sysinfo"]["model"][:5])
return model :return: str model, list of supported features
"""
sys_info = self.get_sysinfo()
alias = sys_info['alias']
model = sys_info["model"]
features = sys_info['feature'].split(':')
for feature in features:
if feature not in ALL_FEATURES:
_LOGGER.warn('Unknown feature %s on device %s.', feature, model)
return alias, model, features
class TPLinkSmartHomeProtocol: class TPLinkSmartHomeProtocol: