Fix handling of symlinked device descriptors in keyboard_remote and move remaining sync io to executor thread pool (#30206)

* fix handling of symlinked device decriptors

* make check for symlinked paths more efficient

* make variable names pylint compliant

* move sync io during setup and device connect/disconnect to executor thread pool

* move remaining sync io during setup to executor thread pool

* remove unnecessary lambda functions
This commit is contained in:
Josh Bendavid 2019-12-26 13:06:57 -05:00 committed by Martin Hjelmare
parent b2753b7578
commit d6744fbc4e

View File

@ -2,6 +2,7 @@
# pylint: disable=import-error # pylint: disable=import-error
import asyncio import asyncio
import logging import logging
import os
import aionotify import aionotify
from evdev import InputDevice, categorize, ecodes, list_devices from evdev import InputDevice, categorize, ecodes, list_devices
@ -119,9 +120,11 @@ class KeyboardRemote:
# add initial devices (do this AFTER starting watcher in order to # add initial devices (do this AFTER starting watcher in order to
# avoid race conditions leading to missing device connections) # avoid race conditions leading to missing device connections)
initial_start_monitoring = set() initial_start_monitoring = set()
descriptors = list_devices(DEVINPUT) descriptors = await self.hass.async_add_executor_job(list_devices, DEVINPUT)
for descriptor in descriptors: for descriptor in descriptors:
dev, handler = self.get_device_handler(descriptor) dev, handler = await self.hass.async_add_executor_job(
self.get_device_handler, descriptor
)
if handler is None: if handler is None:
continue continue
@ -165,6 +168,15 @@ class KeyboardRemote:
handler = self.handlers_by_descriptor[descriptor] handler = self.handlers_by_descriptor[descriptor]
elif dev.name in self.handlers_by_name: elif dev.name in self.handlers_by_name:
handler = self.handlers_by_name[dev.name] handler = self.handlers_by_name[dev.name]
else:
# check for symlinked paths matching descriptor
for test_descriptor, test_handler in self.handlers_by_descriptor.items():
if test_handler.dev is not None:
fullpath = test_handler.dev.path
else:
fullpath = os.path.realpath(test_descriptor)
if fullpath == descriptor:
handler = test_handler
return (dev, handler) return (dev, handler)
@ -186,7 +198,9 @@ class KeyboardRemote:
(event.flags & aionotify.Flags.CREATE) (event.flags & aionotify.Flags.CREATE)
or (event.flags & aionotify.Flags.ATTRIB) or (event.flags & aionotify.Flags.ATTRIB)
) and not descriptor_active: ) and not descriptor_active:
dev, handler = self.get_device_handler(descriptor) dev, handler = await self.hass.async_add_executor_job(
self.get_device_handler, descriptor
)
if handler is None: if handler is None:
continue continue
self.active_handlers_by_descriptor[descriptor] = handler self.active_handlers_by_descriptor[descriptor] = handler
@ -242,7 +256,7 @@ class KeyboardRemote:
"""Stop event monitoring task and issue event.""" """Stop event monitoring task and issue event."""
if self.monitor_task is not None: if self.monitor_task is not None:
try: try:
self.dev.ungrab() await self.hass.async_add_executor_job(self.dev.ungrab)
except OSError: except OSError:
pass pass
# monitoring of the device form the event loop and closing of the # monitoring of the device form the event loop and closing of the
@ -272,7 +286,7 @@ class KeyboardRemote:
try: try:
_LOGGER.debug("Start device monitoring") _LOGGER.debug("Start device monitoring")
dev.grab() await self.hass.async_add_executor_job(dev.grab)
async for event in dev.async_read_loop(): async for event in dev.async_read_loop():
if event.type is ecodes.EV_KEY: if event.type is ecodes.EV_KEY:
if event.value in self.key_values: if event.value in self.key_values: