python-kasa/pyHS100/smartbulb.py
Teemu R 07af48e41a Discover refactoring, enhancements to the cli tool (#71)
* Discover refactoring, enhancements to the cli tool

* Discover tries to detect the type of the device from sysinfo response
* Discover.discover() returns an IP address keyed dictionary,
  values are initialized instances of the automatically detected device type.

* When no IP is given, autodetect all supported devices and print out their states
* When only IP but no type is given, autodetect type and make a call based on that information.
  * One can define --bulb or --plug to skip the detection.

* renamed pyHS100.py -> smartdevice.py

* SmartPlugException -> SmartDeviceException in comments

* fix mic_type check

* make time() return None on failure as we don't know which devices support getting the time and it's used in the cli tool

* hw_info: check if key exists before accessing it, add mic_mac and mic_type

* Check for mic_mac on mac, based on work by kdschloesser on issue #59

* make hound happy, __init__ on SmartDevice cannot error out so removing 'raises' documentation
2017-08-05 15:49:56 +02:00

266 lines
7.0 KiB
Python

from pyHS100 import SmartDevice
class SmartBulb(SmartDevice):
"""Representation of a TP-Link Smart Bulb.
Usage example when used as library:
p = SmartBulb("192.168.1.105")
# print the devices alias
print(p.alias)
# change state of bulb
p.state = "ON"
p.state = "OFF"
# query and print current state of plug
print(p.state)
# check whether the bulb supports color changes
if p.is_color:
# set the color to an HSV tuple
p.hsv = (100, 0, 255)
# get the current HSV value
print(p.hsv)
# check whether the bulb supports setting color temperature
if p.is_variable_color_temp:
# set the color temperature in Kelvin
p.color_temp = 3000
# get the current color temperature
print(p.color_temp)
# check whether the bulb is dimmable
if p.is_dimmable:
# set the bulb to 50% brightness
p.brightness = 50
# check the current brightness
print(p.brightness)
Errors reported by the device are raised as SmartDeviceExceptions,
and should be handled by the user of the library.
"""
# bulb states
BULB_STATE_ON = 'ON'
BULB_STATE_OFF = 'OFF'
def __init__(self, ip_address, protocol=None):
SmartDevice.__init__(self, ip_address, protocol)
self.emeter_type = "smartlife.iot.common.emeter"
self.emeter_units = True
@property
def is_color(self):
"""
Whether the bulb supports color changes
:return: True if the bulb supports color changes, False otherwise
:rtype: bool
"""
return bool(self.sys_info['is_color'])
@property
def is_dimmable(self):
"""
Whether the bulb supports brightness changes
:return: True if the bulb supports brightness changes, False otherwise
:rtype: bool
"""
return bool(self.sys_info['is_dimmable'])
@property
def is_variable_color_temp(self):
"""
Whether the bulb supports color temperature changes
:return: True if the bulb supports color temperature changes, False
otherwise
:rtype: bool
"""
return bool(self.sys_info['is_variable_color_temp'])
def get_light_state(self):
return self._query_helper("smartlife.iot.smartbulb.lightingservice",
"get_light_state")
def set_light_state(self, state):
return self._query_helper("smartlife.iot.smartbulb.lightingservice",
"transition_light_state", state)
@property
def hsv(self):
"""
Returns the current HSV state of the bulb, if supported
:return: tuple containing current hue, saturation and value (0-255)
:rtype: tuple
"""
if not self.is_color:
return None
light_state = self.get_light_state()
if not self.is_on:
hue = light_state['dft_on_state']['hue']
saturation = light_state['dft_on_state']['saturation']
value = int(light_state['dft_on_state']['brightness'] * 255 / 100)
else:
hue = light_state['hue']
saturation = light_state['saturation']
value = int(light_state['brightness'] * 255 / 100)
return hue, saturation, value
@hsv.setter
def hsv(self, state):
"""
Sets new HSV, if supported
:param tuple state: hue, saturation and value (0-255 each)
"""
if not self.is_color:
return None
light_state = {
"hue": state[0],
"saturation": state[1],
"brightness": int(state[2] * 100 / 255),
"color_temp": 0
}
return self.set_light_state(light_state)
@property
def color_temp(self):
"""
Color temperature of the device, if supported
:return: Color temperature in Kelvin
:rtype: int
"""
if not self.is_variable_color_temp:
return None
light_state = self.get_light_state()
if not self.is_on:
return light_state['dft_on_state']['color_temp']
else:
return light_state['color_temp']
@color_temp.setter
def color_temp(self, temp):
"""
Set the color temperature of the device, if supported
:param int temp: The new color temperature, in Kelvin
"""
if not self.is_variable_color_temp:
return None
light_state = {
"color_temp": temp,
}
return self.set_light_state(light_state)
@property
def brightness(self):
"""
Current brightness of the device, if supported
:return: brightness in percent
:rtype: int
"""
if not self.is_dimmable:
return None
light_state = self.get_light_state()
if not self.is_on:
return light_state['dft_on_state']['brightness']
else:
return light_state['brightness']
@brightness.setter
def brightness(self, brightness):
"""
Set the current brightness of the device, if supported
:param int brightness: brightness in percent
"""
if not self.is_dimmable:
return None
light_state = {
"brightness": brightness,
}
return self.set_light_state(light_state)
@property
def state(self):
"""
Retrieve the bulb state
:returns: one of
BULB_STATE_ON
BULB_STATE_OFF
:rtype: str
"""
light_state = self.get_light_state()
if light_state['on_off']:
return self.BULB_STATE_ON
return self.BULB_STATE_OFF
@property
def state_information(self):
"""
Return bulb-specific state information.
:return: Bulb information dict, keys in user-presentable form.
:rtype: dict
"""
info = {
'Brightness': self.brightness,
'Is dimmable': self.is_dimmable,
}
if self.is_variable_color_temp:
info["Color temperature"] = self.color_temp
if self.is_color:
info["HSV"] = self.hsv
return info
@property
def is_on(self):
return self.state == self.BULB_STATE_ON
def turn_off(self):
"""
Turn the bulb off.
"""
self.state = self.BULB_STATE_OFF
def turn_on(self):
"""
Turn the bulb on.
"""
self.state = self.BULB_STATE_ON
@state.setter
def state(self, bulb_state):
"""
Set the new bulb state
:param bulb_state: one of
BULB_STATE_ON
BULB_STATE_OFF
"""
if bulb_state == self.BULB_STATE_ON:
bulb_state = 1
elif bulb_state == self.BULB_STATE_OFF:
bulb_state = 0
else:
raise ValueError
light_state = {
"on_off": bulb_state,
}
return self.set_light_state(light_state)
@property
def has_emeter(self):
return True