Recieve signals from a keyboard and use keyboard as a remote control (#3305)
parent
04d31e4ef4
commit
1c706834e0
|
@ -146,6 +146,7 @@ omit =
|
|||
homeassistant/components/ifttt.py
|
||||
homeassistant/components/joaoapps_join.py
|
||||
homeassistant/components/keyboard.py
|
||||
homeassistant/components/keyboard_remote.py
|
||||
homeassistant/components/light/blinksticklight.py
|
||||
homeassistant/components/light/flux_led.py
|
||||
homeassistant/components/light/hue.py
|
||||
|
|
|
@ -0,0 +1,135 @@
|
|||
"""
|
||||
Recieve signals from a keyboard and use it as a remote control.
|
||||
|
||||
This component allows to use a keyboard as remote control. It will
|
||||
fire ´keyboard_remote_command_received´ events witch can then be used
|
||||
in automation rules.
|
||||
|
||||
The `evdev` package is used to interface with the keyboard and thus this
|
||||
is Linux only. It also means you can't use your normal keyboard for this,
|
||||
because `evdev` will block it.
|
||||
|
||||
Example:
|
||||
keyboard_remote:
|
||||
device_descriptor: '/dev/input/by-id/foo'
|
||||
key_value: 'key_up' # optional alternaive 'key_down' and 'key_hold'
|
||||
# be carefull, 'key_hold' fires a lot of events
|
||||
|
||||
and an automation rule to bring breath live into it.
|
||||
|
||||
automation:
|
||||
alias: Keyboard All light on
|
||||
trigger:
|
||||
platform: event
|
||||
event_type: keyboard_remote_command_received
|
||||
event_data:
|
||||
key_code: 107 # inspect log to obtain desired keycode
|
||||
action:
|
||||
service: light.turn_on
|
||||
entity_id: light.all
|
||||
"""
|
||||
|
||||
# pylint: disable=import-error
|
||||
import threading
|
||||
import logging
|
||||
import os
|
||||
|
||||
import voluptuous as vol
|
||||
|
||||
import homeassistant.helpers.config_validation as cv
|
||||
from homeassistant.const import (
|
||||
EVENT_HOMEASSISTANT_START,
|
||||
EVENT_HOMEASSISTANT_STOP
|
||||
)
|
||||
|
||||
DOMAIN = "keyboard_remote"
|
||||
REQUIREMENTS = ['evdev==0.6.1']
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
ICON = 'mdi:remote'
|
||||
KEYBOARD_REMOTE_COMMAND_RECEIVED = 'keyboard_remote_command_received'
|
||||
KEY_CODE = 'key_code'
|
||||
KEY_VALUE = {'key_up': 0, 'key_down': 1, 'key_hold': 2}
|
||||
TYPE = 'type'
|
||||
DEVICE_DESCRIPTOR = 'device_descriptor'
|
||||
|
||||
CONFIG_SCHEMA = vol.Schema({
|
||||
DOMAIN: vol.Schema({
|
||||
vol.Required(DEVICE_DESCRIPTOR): 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):
|
||||
"""Setup keyboard_remote."""
|
||||
config = config.get(DOMAIN)
|
||||
device_descriptor = config.get(DEVICE_DESCRIPTOR)
|
||||
if not device_descriptor or not os.path.isfile(device_descriptor):
|
||||
id_folder = '/dev/input/by-id/'
|
||||
_LOGGER.error(
|
||||
'A device_descriptor must be defined. '
|
||||
'Possible descriptors are %s:\n%s',
|
||||
id_folder, os.listdir(id_folder)
|
||||
)
|
||||
return
|
||||
|
||||
key_value = KEY_VALUE.get(config.get(TYPE, 'key_up'))
|
||||
|
||||
keyboard_remote = KeyboardRemote(
|
||||
hass,
|
||||
device_descriptor,
|
||||
key_value
|
||||
)
|
||||
|
||||
def _start_keyboard_remote(_event):
|
||||
keyboard_remote.run()
|
||||
|
||||
def _stop_keyboard_remote(_event):
|
||||
keyboard_remote.stopped.set()
|
||||
|
||||
hass.bus.listen_once(
|
||||
EVENT_HOMEASSISTANT_START,
|
||||
_start_keyboard_remote
|
||||
)
|
||||
hass.bus.listen_once(
|
||||
EVENT_HOMEASSISTANT_STOP,
|
||||
_stop_keyboard_remote
|
||||
)
|
||||
|
||||
return True
|
||||
|
||||
|
||||
class KeyboardRemote(threading.Thread):
|
||||
"""This interfaces with the inputdevice using evdev."""
|
||||
|
||||
def __init__(self, hass, device_descriptor, key_value):
|
||||
"""Construct a KeyboardRemote interface object."""
|
||||
from evdev import InputDevice
|
||||
|
||||
self.dev = InputDevice(device_descriptor)
|
||||
threading.Thread.__init__(self)
|
||||
self.stopped = threading.Event()
|
||||
self.hass = hass
|
||||
self.key_value = key_value
|
||||
|
||||
def run(self):
|
||||
"""Main loop of the KeyboardRemote."""
|
||||
from evdev import categorize, ecodes
|
||||
_LOGGER.debug('KeyboardRemote interface started for %s', self.dev)
|
||||
|
||||
self.dev.grab()
|
||||
|
||||
while not self.stopped.isSet():
|
||||
event = self.dev.read_one()
|
||||
|
||||
if not event:
|
||||
continue
|
||||
|
||||
# pylint: disable=no-member
|
||||
if event.type is ecodes.EV_KEY and event.value is self.key_value:
|
||||
_LOGGER.debug(categorize(event))
|
||||
self.hass.bus.fire(
|
||||
KEYBOARD_REMOTE_COMMAND_RECEIVED,
|
||||
{KEY_CODE: event.code}
|
||||
)
|
|
@ -80,6 +80,9 @@ eliqonline==1.0.12
|
|||
# homeassistant.components.enocean
|
||||
enocean==0.31
|
||||
|
||||
# homeassistant.components.keyboard_remote
|
||||
evdev==0.6.1
|
||||
|
||||
# homeassistant.components.climate.honeywell
|
||||
# homeassistant.components.thermostat.honeywell
|
||||
evohomeclient==0.2.5
|
||||
|
|
Loading…
Reference in New Issue