Skip to content

Commit

Permalink
Allow using more than one keyboard remote (home-assistant#11061)
Browse files Browse the repository at this point in the history
* Allow using more than one keyboard remote

This sets up one thread per keyboard remote, listening for events.

* Remove enclosing block in keyboard_remote

* Remove unnecessary semantic check for keyboard_remote
  • Loading branch information
BryanJacobs authored and balloob committed Dec 14, 2017
1 parent 2cced1d commit 3473ef6
Showing 1 changed file with 48 additions and 21 deletions.
69 changes: 48 additions & 21 deletions homeassistant/components/keyboard_remote.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
_LOGGER = logging.getLogger(__name__)

DEVICE_DESCRIPTOR = 'device_descriptor'
DEVICE_ID_GROUP = 'Device descriptor or name'
DEVICE_ID_GROUP = 'Device description'
DEVICE_NAME = 'device_name'
DOMAIN = 'keyboard_remote'

Expand All @@ -36,24 +36,20 @@
TYPE = 'type'

CONFIG_SCHEMA = vol.Schema({
DOMAIN: vol.Schema({
vol.Exclusive(DEVICE_DESCRIPTOR, DEVICE_ID_GROUP): cv.string,
vol.Exclusive(DEVICE_NAME, DEVICE_ID_GROUP): cv.string,
vol.Optional(TYPE, default='key_up'):
vol.All(cv.string, vol.Any('key_up', 'key_down', 'key_hold')),
}),
DOMAIN:
vol.All(cv.ensure_list, [vol.Schema({
vol.Exclusive(DEVICE_DESCRIPTOR, DEVICE_ID_GROUP): cv.string,
vol.Exclusive(DEVICE_NAME, DEVICE_ID_GROUP): cv.string,
vol.Optional(TYPE, default='key_up'):
vol.All(cv.string, vol.Any('key_up', 'key_down', 'key_hold'))
})])
}, extra=vol.ALLOW_EXTRA)


def setup(hass, config):
"""Set up the keyboard_remote."""
config = config.get(DOMAIN)

if not config.get(DEVICE_DESCRIPTOR) and\
not config.get(DEVICE_NAME):
_LOGGER.error("No device_descriptor or device_name found")
return

keyboard_remote = KeyboardRemote(
hass,
config
Expand All @@ -63,7 +59,7 @@ def _start_keyboard_remote(_event):
keyboard_remote.run()

def _stop_keyboard_remote(_event):
keyboard_remote.stopped.set()
keyboard_remote.stop()

hass.bus.listen_once(
EVENT_HOMEASSISTANT_START,
Expand All @@ -77,19 +73,21 @@ def _stop_keyboard_remote(_event):
return True


class KeyboardRemote(threading.Thread):
class KeyboardRemoteThread(threading.Thread):
"""This interfaces with the inputdevice using evdev."""

def __init__(self, hass, config):
"""Construct a KeyboardRemote interface object."""
from evdev import InputDevice, list_devices
def __init__(self, hass, device_name, device_descriptor, key_value):
"""Construct a thread listening for events on one device."""
self.hass = hass
self.device_name = device_name
self.device_descriptor = device_descriptor
self.key_value = key_value

self.device_descriptor = config.get(DEVICE_DESCRIPTOR)
self.device_name = config.get(DEVICE_NAME)
if self.device_descriptor:
self.device_id = self.device_descriptor
else:
self.device_id = self.device_name

self.dev = self._get_keyboard_device()
if self.dev is not None:
_LOGGER.debug("Keyboard connected, %s", self.device_id)
Expand All @@ -103,6 +101,7 @@ def __init__(self, hass, config):
id_folder = '/dev/input/by-id/'

if os.path.isdir(id_folder):
from evdev import InputDevice, list_devices
device_names = [InputDevice(file_name).name
for file_name in list_devices()]
_LOGGER.debug(
Expand All @@ -116,7 +115,6 @@ def __init__(self, hass, config):
threading.Thread.__init__(self)
self.stopped = threading.Event()
self.hass = hass
self.key_value = KEY_VALUE.get(config.get(TYPE, 'key_up'))

def _get_keyboard_device(self):
"""Get the keyboard device."""
Expand Down Expand Up @@ -145,7 +143,7 @@ def run(self):

while not self.stopped.isSet():
# Sleeps to ease load on processor
time.sleep(.1)
time.sleep(.05)

if self.dev is None:
self.dev = self._get_keyboard_device()
Expand Down Expand Up @@ -178,3 +176,32 @@ def run(self):
KEYBOARD_REMOTE_COMMAND_RECEIVED,
{KEY_CODE: event.code}
)


class KeyboardRemote(object):
"""Sets up one thread per device."""

def __init__(self, hass, config):
"""Construct a KeyboardRemote interface object."""
self.threads = []
for dev_block in config:
device_descriptor = dev_block.get(DEVICE_DESCRIPTOR)
device_name = dev_block.get(DEVICE_NAME)
key_value = KEY_VALUE.get(dev_block.get(TYPE, 'key_up'))

if device_descriptor is not None\
or device_name is not None:
thread = KeyboardRemoteThread(hass, device_name,
device_descriptor,
key_value)
self.threads.append(thread)

def run(self):
"""Run all event listener threads."""
for thread in self.threads:
thread.start()

def stop(self):
"""Stop all event listener threads."""
for thread in self.threads:
thread.stopped.set()

0 comments on commit 3473ef6

Please sign in to comment.