From 70b8735d1787a7810bef1c29dbb50cd9e0dbda2a Mon Sep 17 00:00:00 2001 From: Barry John Williams Date: Fri, 12 May 2017 19:50:57 +0100 Subject: [PATCH] Add philips hue support --- .coveragerc | 13 +++++++ requirements.txt | 3 +- src/action.py | 41 +++++++++++++++++++++ tests/test_change_light_color.py | 63 ++++++++++++++++++++++++++++++++ 4 files changed, 119 insertions(+), 1 deletion(-) create mode 100644 .coveragerc create mode 100644 tests/test_change_light_color.py diff --git a/.coveragerc b/.coveragerc new file mode 100644 index 00000000..47840bab --- /dev/null +++ b/.coveragerc @@ -0,0 +1,13 @@ +[run] +branch = True +source = src + +[report] +exclude_lines = + if self.debug: + pragma: no cover + raise NotImplementedError + if __name__ == .__main__.: +ignore_errors = True +omit = + tests/* \ No newline at end of file diff --git a/requirements.txt b/requirements.txt index 8422f47c..adc1edc5 100644 --- a/requirements.txt +++ b/requirements.txt @@ -2,4 +2,5 @@ google-assistant-sdk[auth_helpers]==0.1.0 grpc-google-cloud-speech-v1beta1==0.14.0 protobuf==3.1.0 configargparse==0.11.0 - +phue==0.9 +rgbxy==0.5 diff --git a/src/action.py b/src/action.py index 0946076c..85999ad4 100644 --- a/src/action.py +++ b/src/action.py @@ -18,6 +18,9 @@ import logging import subprocess +import phue +from rgbxy import Converter + import actionbase # ============================================================================= @@ -194,6 +197,44 @@ def run(self, voice_command): self.say(to_repeat) +# Example: Change Philips Light Color +# ==================================== +# +# This example will change the color of the named bulb to that of the +# HEX RGB color and respond with 'ok' +# +# actor.add_keyword(_('change to ocean blue'), \ +# ChangeLightColor(say, "philips-hue", "Lounge Lamp", "0077be")) + +class ChangeLightColor(object): + + """Change a Philips Hue bulb color.""" + + def __init__(self, say, bridge_address, bulb_name, hex_color): + self.converter = Converter() + self.say = say + self.hex_color = hex_color + self.bulb_name = bulb_name + self.bridge_address = bridge_address + + def run(self): + bridge = self.find_bridge() + if bridge: + light = bridge.get_light_objects("name")[self.bulb_name] + light.on = True + light.xy = self.converter.hex_to_xy(self.hex_color) + self.say(_("Ok")) + + def find_bridge(self): + try: + bridge = phue.Bridge(self.bridge_address) + bridge.connect() + return bridge + except phue.PhueRegistrationException: + logging.info("hue: No bridge registered, press button on bridge and try again") + self.say(_("No bridge registered, press button on bridge and try again")) + + # ========================================= # Makers! Implement your own actions here. # ========================================= diff --git a/tests/test_change_light_color.py b/tests/test_change_light_color.py new file mode 100644 index 00000000..401f7359 --- /dev/null +++ b/tests/test_change_light_color.py @@ -0,0 +1,63 @@ + +"""Test the change light color action.""" + +import mock +import unittest + +import phue +import action + +action._ = lambda s: s + + +class TestChangeLightColor(unittest.TestCase): + + def _say(self, text): + self._say_text = text + + def setUp(self): + self._say_text = None + + @mock.patch("action.phue") + def test_change_light_color_no_bridge(self, mockedPhue): + mockedPhue.PhueRegistrationException = phue.PhueRegistrationException + bridge = mock.MagicMock() + bridge.connect.side_effect = mockedPhue.PhueRegistrationException(0, "error") + mockedPhue.Bridge.return_value = bridge + + action.ChangeLightColor(self._say, "philips-hue", "Lounge Lamp", "0077be").run() + + self.assertEqual(self._say_text, + "No bridge registered, press button on bridge and try again") + + @mock.patch("action.phue") + @mock.patch("action.Converter") + def test_change_light_color(self, Converter, mockedPhue): + + xyValue = [0.1, 0.2] + + converter = mock.MagicMock() + Converter.return_value = converter + converter.hex_to_xy.return_value = xyValue + + light = mock.MagicMock() + lights = { + "Lounge Lamp": light + } + bridge = mock.MagicMock() + bridge.get_light_objects.return_value = lights + mockedPhue.Bridge.return_value = bridge + + action.ChangeLightColor(self._say, "philips-hue", "Lounge Lamp", "0077be").run() + + mockedPhue.Bridge.assert_called_with("philips-hue") + bridge.connect.assert_called() + bridge.get_light_objects.assert_called_with("name") + self.assertEqual(light.on, True) + converter.hex_to_xy.assert_called_with("0077be") + self.assertEqual(light.xy, xyValue) + self.assertEqual(self._say_text, "Ok") + + +if __name__ == "__main__": + unittest.main()