Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 20 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,17 @@ You can then update your DevDeck configuration to use decks and controls from th

## Controls

* `KeylightToggleControl`
* `key_light_toggle_control.KeylightToggleControl`

Can be used to toggle the state of an Elgato Key Light
Can be used to toggle the state of an Elgato Key Light.

* `brightness.Increase`

Can be use to increase light brightness by a static amount.

* `brightness.Decrease`

Can be use to decrease light brightness by a static amount.

## Configuration

Expand All @@ -29,3 +37,13 @@ Example configuration:
key: 0
settings:
host: 192.168.1.23
- name: devdeck_key_light.brightness.Increase
key: 1
settings:
host: 192.168.1.23
step: 20
- name: devdeck_key_light.brightness.Decrease
key: 1
settings:
host: 192.168.1.23
step: 20
Binary file added devdeck_key_light/assets/brightness-high.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added devdeck_key_light/assets/brightness-low.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file removed devdeck_key_light/assets/key-light-off.png
Binary file not shown.
Binary file removed devdeck_key_light/assets/key-light-on.png
Binary file not shown.
Binary file added devdeck_key_light/assets/lightbulb-filled.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added devdeck_key_light/assets/lightbulb-outlined.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
72 changes: 72 additions & 0 deletions devdeck_key_light/brightness.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import abc
import logging
import os
import requests

from devdeck_core.controls.deck_control import DeckControl


class _BrightnessBase(abc.ABC, DeckControl):
def __init__(self, key_no, **kwargs):
self.elgato = None
self.__logger = logging.getLogger('devdeck')
super().__init__(key_no, **kwargs)

@property
@abc.abstractmethod
def image_file(self):
'Image file to render. Relative path to assets directory.'
...

@property
def endpoint(self):
return 'http://{}:9123/elgato/lights'.format(self.settings['host'])

def initialize(self):
with self.deck_context() as context:
with context.renderer() as r:
r.image(os.path.join(os.path.dirname(__file__), 'assets', self.image_file)).end()

@property
def brightness(self):
try:
r = requests.get(self.endpoint)
except requests.exceptions.ConnectionError as ex:
self.__logger.warning("Error communicating with Elgato Key Light: %s", str(ex))
return 0
return r.json()['lights'][0]['brightness']

@brightness.setter
def brightness(self, value):
if not 0 <= value <= 100:
raise ValueError('Valid brightness values are between 0 and 100 inclusive.')
data = {
'lights': [
{
'brightness': int(value),
}
],
'numberOfLights': 1
}
try:
requests.put(self.endpoint, json=data)
except requests.exceptions.ConnectionError as ex:
self.__logger.warning("Error communicating with Elgato Key Light: %s", str(ex))


class Increase(_BrightnessBase):
@property
def image_file(self):
return 'brightness-high.png'

def pressed(self):
self.brightness = min(100, self.brightness + self.settings['step'])


class Decrease(_BrightnessBase):
@property
def image_file(self):
return 'brightness-low.png'

def pressed(self):
self.brightness = max(0, self.brightness - self.settings['step'])
4 changes: 2 additions & 2 deletions devdeck_key_light/key_light_toggle_control.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,10 +42,10 @@ def __render_icon(self):
with self.deck_context() as context:
if data['lights'][0]['on'] == 1:
with context.renderer() as r:
r.image(os.path.join(os.path.dirname(__file__), "assets", 'key-light-on.png')).end()
r.image(os.path.join(os.path.dirname(__file__), "assets", 'lightbulb-filled.png')).end()
else:
with context.renderer() as r:
r.image(os.path.join(os.path.dirname(__file__), "assets", 'key-light-off.png')).end()
r.image(os.path.join(os.path.dirname(__file__), "assets", 'lightbulb-outlined.png')).end()
except requests.exceptions.ConnectionError as ex:
self.__logger.warning("Error communicating with Elgato Key Light: %s", str(ex))
with self.deck_context() as context:
Expand Down
4 changes: 2 additions & 2 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
assertpy==1.1
devdeck-core==1.0.7
devdeck-core==1.0.8
pytest==6.2.1
requests==2.25.1
vcrpy==4.1.1
vcrpy==4.1.1
22 changes: 22 additions & 0 deletions tests/devdeck_key_light/test_brightness.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import vcr
from devdeck_core.mock_deck_context import mock_context, assert_rendered
from tests.testing_utils import TestingUtils

from devdeck_key_light.brightness import Increase


class TestBrightness:
def test_simple_increase(self):
settings = {
'host': '192.168.2.25',
'step': 20,
}
control = Increase(0, **settings)
with vcr.use_cassette('tests/fixtures/test_brightness/test_simple_increase.yaml',
match_on=['uri', 'method', 'body']) as cass:
with mock_context(control) as ctx:
control.initialize()
assert_rendered(ctx, TestingUtils.get_filename(
'../devdeck_key_light/assets/brightness-high.png'))
control.pressed()
assert cass.all_played
4 changes: 2 additions & 2 deletions tests/devdeck_key_light/test_keylight_toggle_control.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ def test_initialize_sets_icon(self):
control = KeyLightToggleControl(0, **settings)
with mock_context(control) as ctx:
control.initialize()
assert_rendered(ctx, TestingUtils.get_filename('../devdeck_key_light/assets/key-light-on.png'))
assert_rendered(ctx, TestingUtils.get_filename('../devdeck_key_light/assets/lightbulb-filled.png'))

@vcr.use_cassette('tests/fixtures/test_key_light_toggle/test_initialize_sets_icon_off.yaml')
def test_initialize_sets_icon_off(self):
Expand All @@ -24,4 +24,4 @@ def test_initialize_sets_icon_off(self):
control = KeyLightToggleControl(0, **settings)
with mock_context(control) as ctx:
control.initialize()
assert_rendered(ctx, TestingUtils.get_filename('../devdeck_key_light/assets/key-light-off.png'))
assert_rendered(ctx, TestingUtils.get_filename('../devdeck_key_light/assets/lightbulb-outlined.png'))
36 changes: 36 additions & 0 deletions tests/fixtures/test_brightness/test_simple_increase.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
interactions:
- request:
body: null
headers:
Accept: ['*/*']
Accept-Encoding: ['gzip, deflate']
Connection: [keep-alive]
User-Agent: [python-requests/2.25.1]
method: GET
uri: http://192.168.2.25:9123/elgato/lights
response:
body: {string: '{"numberOfLights":1,"lights":[{"on":1,"brightness":33,"temperature":215}]}'}
headers:
Connection: [keep-alive]
Content-Length: ['74']
Content-Type: [application/json; charset=utf-8]
status: {code: 200, message: OK}
- request:
body: '{"lights": [{"brightness": 53}], "numberOfLights": 1}'
headers:
Accept: ['*/*']
Accept-Encoding: ['gzip, deflate']
Connection: [keep-alive]
Content-Length: ['53']
Content-Type: [application/json]
User-Agent: [python-requests/2.25.1]
method: PUT
uri: http://192.168.2.25:9123/elgato/lights
response:
body: {string: '{"numberOfLights":1,"lights":[{"on":1,"brightness":100,"temperature":215}]}'}
headers:
Connection: [keep-alive]
Content-Length: ['75']
Content-Type: [application/json; charset=utf-8]
status: {code: 200, message: OK}
version: 1