Skip to content

Commit

Permalink
basic support for colored lights
Browse files Browse the repository at this point in the history
  • Loading branch information
Julius2342 committed Feb 3, 2018
1 parent 02d4b34 commit 6b5ee31
Show file tree
Hide file tree
Showing 9 changed files with 333 additions and 28 deletions.
15 changes: 14 additions & 1 deletion test/config_test.py
Expand Up @@ -33,7 +33,7 @@ def test_config_light(self):
xknx.devices['Living-Room.Light_1'],
Light(xknx,
'Living-Room.Light_1',
group_address_switch='1/6/7',
group_address_switch='1/6/9',
device_updated_cb=xknx.devices.device_updated))

def test_config_light_state(self):
Expand All @@ -49,6 +49,19 @@ def test_config_light_state(self):
group_address_brightness_state='1/7/7',
device_updated_cb=xknx.devices.device_updated))

def test_config_light_color(self):
"""Test reading Light with with dimming and color address."""
xknx = XKNX(config='xknx.yaml', loop=self.loop)
self.assertEqual(
xknx.devices['Diningroom.Light_1'],
Light(xknx,
'Diningroom.Light_1',
group_address_switch='1/6/4',
group_address_brightness='1/6/6',
group_address_color='1/6/7',
group_address_color_state='1/6/8',
device_updated_cb=xknx.devices.device_updated))

def test_config_switch(self):
"""Test reading Switch from config file."""
xknx = XKNX(config='xknx.yaml', loop=self.loop)
Expand Down
111 changes: 103 additions & 8 deletions test/light_test.py
Expand Up @@ -12,6 +12,8 @@
class TestLight(unittest.TestCase):
"""Class for testing Light objects."""

# pylint: disable=too-many-public-methods

def setUp(self):
"""Set up test class."""
self.loop = asyncio.new_event_loop()
Expand Down Expand Up @@ -41,6 +43,28 @@ def test_supports_dimm_no(self):
group_address_switch='1/6/4')
self.assertFalse(light.supports_dimming)

#
# TEST SUPPORT COLOR
#
def test_supports_color_true(self):
"""Test supports_color true."""
xknx = XKNX(loop=self.loop)
light = Light(
xknx,
'Diningroom.Light_1',
group_address_switch='1/6/4',
group_address_color='1/6/5')
self.assertTrue(light.supports_color)

def test_supports_color_false(self):
"""Test supports_color false."""
xknx = XKNX(loop=self.loop)
light = Light(
xknx,
'Diningroom.Light_1',
group_address_switch='1/6/4')
self.assertFalse(light.supports_color)

#
# SYNC
#
Expand All @@ -50,17 +74,22 @@ def test_sync(self):
light = Light(xknx,
name="TestLight",
group_address_switch='1/2/3',
group_address_brightness='1/2/5')
group_address_brightness='1/2/5',
group_address_color='1/2/6')
self.loop.run_until_complete(asyncio.Task(light.sync(False)))

self.assertEqual(xknx.telegrams.qsize(), 2)
self.assertEqual(xknx.telegrams.qsize(), 3)

telegram1 = xknx.telegrams.get_nowait()
self.assertEqual(telegram1,
Telegram(GroupAddress('1/2/3'), TelegramType.GROUP_READ))

telegram2 = xknx.telegrams.get_nowait()
self.assertEqual(telegram2,
Telegram(GroupAddress('1/2/6'), TelegramType.GROUP_READ))

telegram3 = xknx.telegrams.get_nowait()
self.assertEqual(telegram3,
Telegram(GroupAddress('1/2/5'), TelegramType.GROUP_READ))

#
Expand All @@ -72,19 +101,24 @@ def test_sync_state_address(self):
light = Light(xknx,
name="TestLight",
group_address_switch='1/2/3',
group_address_switch_state='1/2/6',
group_address_brightness='1/2/8',
group_address_brightness_state='1/2/9')
group_address_switch_state='1/2/4',
group_address_brightness='1/2/5',
group_address_brightness_state='1/2/6',
group_address_color='1/2/7',
group_address_color_state='1/2/8')
self.loop.run_until_complete(asyncio.Task(light.sync(False)))

self.assertEqual(xknx.telegrams.qsize(), 2)
self.assertEqual(xknx.telegrams.qsize(), 3)

telegram1 = xknx.telegrams.get_nowait()
self.assertEqual(telegram1,
Telegram(GroupAddress('1/2/6'), TelegramType.GROUP_READ))
Telegram(GroupAddress('1/2/4'), TelegramType.GROUP_READ))
telegram2 = xknx.telegrams.get_nowait()
self.assertEqual(telegram2,
Telegram(GroupAddress('1/2/9'), TelegramType.GROUP_READ))
Telegram(GroupAddress('1/2/8'), TelegramType.GROUP_READ))
telegram3 = xknx.telegrams.get_nowait()
self.assertEqual(telegram3,
Telegram(GroupAddress('1/2/6'), TelegramType.GROUP_READ))

#
# TEST SET ON
Expand Down Expand Up @@ -146,6 +180,35 @@ def test_set_brightness_not_dimmable(self):
self.assertEqual(xknx.telegrams.qsize(), 0)
mock_warn.assert_called_with('Dimming not supported for device %s', 'TestLight')

#
# TEST SET COLOR
#
def test_set_color(self):
"""Test setting the color of a Light."""
xknx = XKNX(loop=self.loop)
light = Light(xknx,
name="TestLight",
group_address_switch='1/2/3',
group_address_color='1/2/5')
self.loop.run_until_complete(asyncio.Task(light.set_color((23, 24, 25))))
self.assertEqual(xknx.telegrams.qsize(), 1)
telegram = xknx.telegrams.get_nowait()
self.assertEqual(telegram,
Telegram(GroupAddress('1/2/5'), payload=DPTArray((23, 24, 25))))
self.assertEqual(light.current_color(), (23, 24, 25))

def test_set_color_not_possible(self):
"""Test setting the color of a non light without color."""
# pylint: disable=invalid-name
xknx = XKNX(loop=self.loop)
light = Light(xknx,
name="TestLight",
group_address_switch='1/2/3')
with patch('logging.Logger.warning') as mock_warn:
self.loop.run_until_complete(asyncio.Task(light.set_color((23, 24, 25))))
self.assertEqual(xknx.telegrams.qsize(), 0)
mock_warn.assert_called_with('Colors not supported for device %s', 'TestLight')

#
# TEST PROCESS
#
Expand Down Expand Up @@ -224,6 +287,18 @@ def test_process_dimm_payload_invalid_length(self):
with self.assertRaises(CouldNotParseTelegram):
self.loop.run_until_complete(asyncio.Task(light.process(telegram)))

def test_process_color(self):
"""Test process / reading telegrams from telegram queue. Test if color is processed."""
xknx = XKNX(loop=self.loop)
light = Light(xknx,
name="TestLight",
group_address_switch='1/2/3',
group_address_color='1/2/5')
self.assertEqual(light.current_color(), None)
telegram = Telegram(GroupAddress('1/2/5'), payload=DPTArray((23, 24, 25)))
self.loop.run_until_complete(asyncio.Task(light.process(telegram)))
self.assertEqual(light.current_color(), (23, 24, 25))

#
# TEST DO
#
Expand Down Expand Up @@ -252,3 +327,23 @@ def test_wrong_do(self):
self.loop.run_until_complete(asyncio.Task(light.do("execute")))
self.assertEqual(xknx.telegrams.qsize(), 0)
mock_warn.assert_called_with('Could not understand action %s for device %s', 'execute', 'TestLight')

def test_has_group_address(self):
"""Test has_group_address."""
xknx = XKNX(config='xknx.yaml', loop=self.loop)
light = Light(
xknx,
'Office.Light_1',
group_address_switch='1/7/1',
group_address_switch_state='1/7/2',
group_address_brightness='1/7/3',
group_address_brightness_state='1/7/4',
group_address_color='1/7/5',
group_address_color_state='1/7/6')
self.assertTrue(light.has_group_address(GroupAddress('1/7/1')))
self.assertTrue(light.has_group_address(GroupAddress('1/7/2')))
self.assertTrue(light.has_group_address(GroupAddress('1/7/3')))
self.assertTrue(light.has_group_address(GroupAddress('1/7/4')))
self.assertTrue(light.has_group_address(GroupAddress('1/7/5')))
self.assertTrue(light.has_group_address(GroupAddress('1/7/6')))
self.assertFalse(light.has_group_address(GroupAddress('1/7/7')))
101 changes: 101 additions & 0 deletions test/remote_value_color_rgb_test.py
@@ -0,0 +1,101 @@
"""Unit test for RemoteValueColorRGB objects."""
import asyncio
import unittest

from xknx import XKNX
from xknx.knx import DPTArray, DPTBinary, Telegram, GroupAddress
from xknx.exceptions import ConversionError, CouldNotParseTelegram
from xknx.devices import RemoteValueColorRGB


class TestRemoteValueSensor(unittest.TestCase):
"""Test class for RemoteValueSensor objects."""

def setUp(self):
"""Set up test class."""
self.loop = asyncio.new_event_loop()
asyncio.set_event_loop(self.loop)

def tearDown(self):
"""Tear down test class."""
self.loop.close()

def test_to_knx(self):
"""Test to_knx function with normal operation."""
xknx = XKNX(loop=self.loop)
remote_value = RemoteValueColorRGB(xknx)
self.assertEqual(remote_value.to_knx((100, 101, 102)), DPTArray((0x64, 0x65, 0x66)))
self.assertEqual(remote_value.to_knx([100, 101, 102]), DPTArray((0x64, 0x65, 0x66)))

def test_from_knx(self):
"""Test from_knx function with normal operation."""
xknx = XKNX(loop=self.loop)
remote_value = RemoteValueColorRGB(xknx)
self.assertEqual(remote_value.from_knx(DPTArray((0x64, 0x65, 0x66))), (100, 101, 102))

def test_to_knx_error(self):
"""Test to_knx function with wrong parametern."""
xknx = XKNX(loop=self.loop)
remote_value = RemoteValueColorRGB(xknx)
with self.assertRaises(ConversionError):
remote_value.to_knx((100, 101, 102, 103))
with self.assertRaises(ConversionError):
remote_value.to_knx((100, 101, 256))
with self.assertRaises(ConversionError):
remote_value.to_knx((100, -101, 102))
with self.assertRaises(ConversionError):
remote_value.to_knx(("100", 101, 102))
with self.assertRaises(ConversionError):
remote_value.to_knx("100, 101, 102")

def test_set(self):
"""Test setting value."""
xknx = XKNX(loop=self.loop)
remote_value = RemoteValueColorRGB(
xknx,
group_address=GroupAddress("1/2/3"))
self.loop.run_until_complete(asyncio.Task(remote_value.set((100, 101, 102))))
self.assertEqual(xknx.telegrams.qsize(), 1)
telegram = xknx.telegrams.get_nowait()
self.assertEqual(
telegram,
Telegram(
GroupAddress('1/2/3'),
payload=DPTArray((0x64, 0x65, 0x66))))
self.loop.run_until_complete(asyncio.Task(remote_value.set((100, 101, 104))))
self.assertEqual(xknx.telegrams.qsize(), 1)
telegram = xknx.telegrams.get_nowait()
self.assertEqual(
telegram,
Telegram(
GroupAddress('1/2/3'),
payload=DPTArray((0x64, 0x65, 0x68))))

def test_process(self):
"""Test process telegram."""
xknx = XKNX(loop=self.loop)
remote_value = RemoteValueColorRGB(
xknx,
group_address=GroupAddress("1/2/3"))
telegram = Telegram(
group_address=GroupAddress("1/2/3"),
payload=DPTArray((0x64, 0x65, 0x66)))
self.loop.run_until_complete(asyncio.Task(remote_value.process(telegram)))
self.assertEqual(remote_value.value, (100, 101, 102))

def test_to_process_error(self):
"""Test process errornous telegram."""
xknx = XKNX(loop=self.loop)
remote_value = RemoteValueColorRGB(
xknx,
group_address=GroupAddress("1/2/3"))
with self.assertRaises(CouldNotParseTelegram):
telegram = Telegram(
group_address=GroupAddress("1/2/3"),
payload=DPTBinary(1))
self.loop.run_until_complete(asyncio.Task(remote_value.process(telegram)))
with self.assertRaises(CouldNotParseTelegram):
telegram = Telegram(
group_address=GroupAddress("1/2/3"),
payload=DPTArray((0x64, 0x65, 0x66, 0x67)))
self.loop.run_until_complete(asyncio.Task(remote_value.process(telegram)))
16 changes: 16 additions & 0 deletions test/str_test.py
Expand Up @@ -136,6 +136,22 @@ def test_light_dimmable(self):
'<Light name="Licht" switch="GroupAddress("1/2/3")/GroupAddress("1/2/4")/None/None" group_address_brightness="GroupAddress("1/2/5")'
'" group_address_brightness_state="GroupAddress("1/2/6")" brightness="0" />')

def test_light_color(self):
"""Test string representation of dimmable light object."""
xknx = XKNX(loop=self.loop)
light = Light(
xknx,
name='Licht',
group_address_switch='1/2/3',
group_address_switch_state='1/2/4',
group_address_color='1/2/5',
group_address_color_state='1/2/6')
self.assertEqual(
str(light),
'<Light name="Licht" '
'switch="GroupAddress("1/2/3")/GroupAddress("1/2/4")/None/None" '
'color="GroupAddress("1/2/5")/GroupAddress("1/2/6")/None/None" />')

def test_notification(self):
"""Test string representation of notification object."""
xknx = XKNX(loop=self.loop)
Expand Down
5 changes: 3 additions & 2 deletions xknx.yaml
Expand Up @@ -73,10 +73,11 @@ groups:
light:

Kitchen.Light_1: {group_address_switch: '1/6/1', group_address_brightness: '1/6/3'}
Diningroom.Light_1: {group_address_switch: '1/6/4', group_address_brightness: '1/6/6'}
Living-Room.Light_1: {group_address_switch: '1/6/7'}
Living-Room.Light_1: {group_address_switch: '1/6/9'}
# Light with extra addresses for states:
Office.Light_1: {group_address_switch: '1/7/4', group_address_switch_state: '1/7/5', group_address_brightness: '1/7/6', group_address_brightness_state: '1/7/7'}
# Light with color
Diningroom.Light_1: {group_address_switch: '1/6/4', group_address_brightness: '1/6/6', group_address_color: '1/6/7', group_address_color_state: '1/6/8'}

climate:
Kitchen.Climate: {group_address_temperature: '1/7/1'}
Expand Down
1 change: 1 addition & 0 deletions xknx/devices/__init__.py
Expand Up @@ -16,3 +16,4 @@
from .scene import Scene
from .remote_value import RemoteValue
from .remote_value_sensor import RemoteValueSensor
from .remote_value_color_rgb import RemoteValueColorRGB

0 comments on commit 6b5ee31

Please sign in to comment.