Skip to content

Commit

Permalink
Adding support for GU10 lights (#141)
Browse files Browse the repository at this point in the history
* Adding support for GU10 lights
* Bump version of gateway that pytradfri works with
* Finalize rename to DeviceControl
  • Loading branch information
Patrik authored Jan 21, 2018
1 parent 0a3b4e2 commit b252867
Show file tree
Hide file tree
Showing 5 changed files with 75 additions and 28 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[![Coverage Status](https://coveralls.io/repos/github/ggravlingen/pytradfri/badge.svg?branch=master)](https://coveralls.io/github/ggravlingen/pytradfri?branch=master)
[![PyPI version](https://badge.fury.io/py/pytradfri.svg)](https://badge.fury.io/py/pytradfri)

**NB:** Latest Gateway version tested and working - 1.2.42.
**NB:** Latest Gateway version tested and working - 1.3.14.

Python class to communicate with the [IKEA Trådfri](http://www.ikea.com/us/en/catalog/products/00337813/) (Tradfri) ZigBee-based Gateway. Using this library you can, by communicating with the gateway, control IKEA lights (including the RGB ones). Some of the features include:

Expand Down
59 changes: 36 additions & 23 deletions pytradfri/device.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
RANGE_BRIGHTNESS,
RANGE_X,
RANGE_Y,
ROOT_SWITCH,
SUPPORT_BRIGHTNESS,
SUPPORT_COLOR_TEMP,
SUPPORT_HEX_COLOR,
Expand All @@ -34,6 +35,14 @@
from .error import ColorError


def device_type(data):
"""If regular bulb=>ATTR_LIGHT_CONTROL If GU10 light=>ROOT_SWITCH."""
if ATTR_LIGHT_CONTROL in data:
return ATTR_LIGHT_CONTROL
elif ROOT_SWITCH in data:
return ROOT_SWITCH


class Device(ApiResource):
"""Base class for devices."""

Expand Down Expand Up @@ -62,11 +71,13 @@ def reachable(self):
@property
def has_light_control(self):
return (self.raw is not None and
len(self.raw.get(ATTR_LIGHT_CONTROL, "")) > 0)
(len(self.raw.get(ATTR_LIGHT_CONTROL, "")) > 0 or
len(self.raw.get(ROOT_SWITCH, "")) > 0)
)

@property
def light_control(self):
return LightControl(self)
return DeviceControl(self)

def __repr__(self):
return "<{} - {} ({})>".format(self.id, self.name,
Expand Down Expand Up @@ -140,22 +151,22 @@ def raw(self):
return self._device.raw[ATTR_DEVICE_INFO]


class LightControl:
"""Class to control the lights."""
class DeviceControl:
"""Class to control devices."""

def __init__(self, device):
self._device = device

@property
def raw(self):
"""Return raw data that it represents."""
return self._device.raw[device_type(self._device.raw)]

@property
def lights(self):
"""Return light objects of the light control."""
return [Light(self._device, i) for i in range(len(self.raw))]

@property
def raw(self):
"""Return raw data that it represents."""
return self._device.raw[ATTR_LIGHT_CONTROL]

def set_state(self, state, *, index=0):
"""Set state of a light."""
return self.set_values({
Expand Down Expand Up @@ -246,36 +257,35 @@ def set_predefined_color(self, colorname, *, index=0,
raise ColorError('Invalid color specified: %s',
colorname)

def _value_validate(self, value, rnge, identifier="Given"):
"""
Make sure a value is within a given range
"""
if value is not None and (value < rnge[0] or value > rnge[1]):
raise ValueError('%s value must be between %d and %d.'
% (identifier, rnge[0], rnge[1]))

def set_values(self, values, *, index=0):
"""
Set values on light control.
Returns a Command.
"""
assert len(self.raw) == 1, \
'Only devices with 1 light supported'

return Command('put', self._device.path, {
ATTR_LIGHT_CONTROL: [
device_type(self._device.raw): [
values
]
})

def _value_validate(self, value, rnge, identifier="Given"):
"""
Make sure a value is within a given range
"""
if value is not None and (value < rnge[0] or value > rnge[1]):
raise ValueError('%s value must be between %d and %d.'
% (identifier, rnge[0], rnge[1]))

def __repr__(self):
return '<LightControl for {} ({} lights)>'.format(self._device.name,
len(self.raw))
return '<DeviceControl for {} ({} lights)>'.format(self._device.name,
len(self.raw))


class Light:
"""Represent a light control.
"""Represent a light.
https://github.com/IPSO-Alliance/pub/blob/master/docs/IPSO-Smart-Objects.pdf
"""
Expand Down Expand Up @@ -325,7 +335,10 @@ def hsb_xy_color(self):
@property
def raw(self):
"""Return raw data that it represents."""
return self.device.raw[ATTR_LIGHT_CONTROL][self.index]
if ATTR_LIGHT_CONTROL in self.device.raw:
return self.device.raw[device_type(self.device.raw)][self.index]
elif ROOT_SWITCH in self.device.raw:
return self.device.raw[device_type(self.device.raw)][self.index]

def __repr__(self):
state = "on" if self.state else "off"
Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
with open(path.join(here, 'README.md'), encoding='utf-8') as f:
long_description = f.read()

VERSION = "5.2.2"
VERSION = "5.3.0"
DOWNLOAD_URL = \
'https://github.com/ggravlingen/pytradfri/archive/{}.zip'.format(VERSION)

Expand Down
30 changes: 30 additions & 0 deletions tests/devices.py
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,36 @@
'9054': 0,
}

# Retrieved from Gateway running on 1.3.002
LIGHT_GU10 = {
"9001": "mhlund #1",
"5750": 0,
"9002": 1515435391,
"9020": 1516008285,
"9003": 65540,
"9054": 0,
"9019": 1,
"3": {
"0": "IKEA of Sweden",
"1": "TRADFRI bulb GU10 WS 400lm",
"2": "",
"3": "1.2.217",
"6": 1
},
"15009": [
{
"5851": 10,
"5850": 0,
"5717": 0,
"5711": 450,
"5709": 30138,
"5710": 26909,
"5706": "efd275",
"9003": 0
}
]
}

# Retrieved from Gateway running on 1.2.42
REMOTE_CONTROL = {
'3': {'0': 'IKEA of Sweden',
Expand Down
10 changes: 7 additions & 3 deletions tests/test_light.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,20 @@
LIGHT_WS,
LIGHT_WS_CUSTOM_COLOR,
LIGHT_CWS,
LIGHT_CWS_CUSTOM_COLOR
LIGHT_CWS_CUSTOM_COLOR,
LIGHT_GU10
)


def light(raw):
return Device(raw).light_control.lights[0]


def light_device_control(raw):
return Device(raw).light_control
def test_gu10():
bulb = light(LIGHT_GU10)

assert bulb.hex_color == 'efd275'
assert bulb.xy_color == (30138, 26909)


def test_white_bulb():
Expand Down

0 comments on commit b252867

Please sign in to comment.