From c691f2a5594ea62ea745fbeb6a4c5babf6282280 Mon Sep 17 00:00:00 2001 From: Pascal Vizeli Date: Tue, 12 Dec 2017 20:01:02 +0100 Subject: [PATCH] Auto mapping UART devices from host (#276) * Add hardware to docker api * set hardware to docker * add loop to dns * Use loop for dns * Update const.py * Update API.md * Update validate.py * Update addon.py * Update addon.py * fix lint * style * Update hardware.py --- API.md | 1 + hassio/addons/addon.py | 7 ++++++- hassio/addons/validate.py | 3 ++- hassio/const.py | 1 + hassio/core.py | 4 ++-- hassio/dns.py | 4 +++- hassio/dock/__init__.py | 3 ++- hassio/dock/addon.py | 11 +++++++---- hassio/hardware.py | 2 +- 9 files changed, 25 insertions(+), 11 deletions(-) diff --git a/API.md b/API.md index 835138be9..2b5362ad0 100644 --- a/API.md +++ b/API.md @@ -389,6 +389,7 @@ Get all available addons. "host_dbus": "bool", "privileged": ["NET_ADMIN", "SYS_ADMIN"], "devices": ["/dev/xy"], + "auto_uart": "bool", "logo": "bool", "changelog": "bool", "hassio_api": "bool", diff --git a/hassio/addons/addon.py b/hassio/addons/addon.py index 4dc929b47..cb47ce7cc 100644 --- a/hassio/addons/addon.py +++ b/hassio/addons/addon.py @@ -22,7 +22,7 @@ from ..const import ( ATTR_STATE, ATTR_TIMEOUT, ATTR_AUTO_UPDATE, ATTR_NETWORK, ATTR_WEBUI, ATTR_HASSIO_API, ATTR_AUDIO, ATTR_AUDIO_OUTPUT, ATTR_AUDIO_INPUT, ATTR_GPIO, ATTR_HOMEASSISTANT_API, ATTR_STDIN, ATTR_LEGACY, ATTR_HOST_IPC, - ATTR_HOST_DBUS) + ATTR_HOST_DBUS, ATTR_AUTO_UART) from .util import check_installed from ..dock.addon import DockerAddon from ..tools import write_json_file, read_json_file @@ -259,6 +259,11 @@ class Addon(object): """Return devices of addon.""" return self._mesh.get(ATTR_DEVICES) + @property + def auto_uart(self): + """Return True if we should map all uart device.""" + return self._mesh.get(ATTR_AUTO_UART) + @property def tmpfs(self): """Return tmpfs of addon.""" diff --git a/hassio/addons/validate.py b/hassio/addons/validate.py index 8efaab9dc..a0001d289 100644 --- a/hassio/addons/validate.py +++ b/hassio/addons/validate.py @@ -17,7 +17,7 @@ from ..const import ( ATTR_AUTO_UPDATE, ATTR_WEBUI, ATTR_AUDIO, ATTR_AUDIO_INPUT, ATTR_HOST_IPC, ATTR_AUDIO_OUTPUT, ATTR_HASSIO_API, ATTR_BUILD_FROM, ATTR_SQUASH, ATTR_ARGS, ATTR_GPIO, ATTR_HOMEASSISTANT_API, ATTR_STDIN, ATTR_LEGACY, - ATTR_HOST_DBUS) + ATTR_HOST_DBUS, ATTR_AUTO_UART) from ..validate import NETWORK_PORT, DOCKER_PORTS, ALSA_CHANNEL _LOGGER = logging.getLogger(__name__) @@ -96,6 +96,7 @@ SCHEMA_ADDON_CONFIG = vol.Schema({ vol.Optional(ATTR_HOST_IPC, default=False): vol.Boolean(), vol.Optional(ATTR_HOST_DBUS, default=False): vol.Boolean(), vol.Optional(ATTR_DEVICES): [vol.Match(r"^(.*):(.*):([rwm]{1,3})$")], + vol.Optional(ATTR_AUTO_UART, default=False): vol.Boolean(), vol.Optional(ATTR_TMPFS): vol.Match(r"^size=(\d)*[kmg](,uid=\d{1,4})?(,rw)?$"), vol.Optional(ATTR_MAP, default=[]): [vol.Match(RE_VOLUME)], diff --git a/hassio/const.py b/hassio/const.py index 90e3b45c1..1a1bf30b2 100644 --- a/hassio/const.py +++ b/hassio/const.py @@ -66,6 +66,7 @@ ATTR_SOURCE = 'source' ATTR_FEATURES = 'features' ATTR_ADDONS = 'addons' ATTR_VERSION = 'version' +ATTR_AUTO_UART = 'auto_uart' ATTR_LAST_BOOT = 'last_boot' ATTR_LAST_VERSION = 'last_version' ATTR_BETA_CHANNEL = 'beta_channel' diff --git a/hassio/core.py b/hassio/core.py index 6150b0e1b..0043c505b 100644 --- a/hassio/core.py +++ b/hassio/core.py @@ -42,8 +42,8 @@ class HassIO(object): self.scheduler = Scheduler(loop) self.api = RestAPI(config, loop) self.hardware = Hardware() - self.docker = DockerAPI() - self.dns = DNSForward() + self.docker = DockerAPI(self.hardware) + self.dns = DNSForward(loop) # init basic docker container self.supervisor = DockerSupervisor( diff --git a/hassio/dns.py b/hassio/dns.py index e02f0182a..359abadc5 100644 --- a/hassio/dns.py +++ b/hassio/dns.py @@ -11,8 +11,9 @@ COMMAND = "socat UDP-RECVFROM:53,fork UDP-SENDTO:127.0.0.11:53" class DNSForward(object): """Manage DNS forwarding to internal DNS.""" - def __init__(self): + def __init__(self, loop): """Initialize DNS forwarding.""" + self.loop = loop self.proc = None async def start(self): @@ -23,6 +24,7 @@ class DNSForward(object): stdin=asyncio.subprocess.DEVNULL, stdout=asyncio.subprocess.DEVNULL, stderr=asyncio.subprocess.DEVNULL, + loop=self.loop ) except OSError as err: _LOGGER.error("Can't start DNS forwarding -> %s", err) diff --git a/hassio/dock/__init__.py b/hassio/dock/__init__.py index 35d773629..580b51559 100644 --- a/hassio/dock/__init__.py +++ b/hassio/dock/__init__.py @@ -16,11 +16,12 @@ class DockerAPI(object): This class is not AsyncIO safe! """ - def __init__(self): + def __init__(self, hardware): """Initialize docker base wrapper.""" self.docker = docker.DockerClient( base_url="unix:/{}".format(str(SOCKET_DOCKER)), version='auto') self.network = DockerNetwork(self.docker) + self.hardware = hardware @property def images(self): diff --git a/hassio/dock/addon.py b/hassio/dock/addon.py index 73c943279..fa9b075e5 100644 --- a/hassio/dock/addon.py +++ b/hassio/dock/addon.py @@ -80,14 +80,17 @@ class DockerAddon(DockerInterface): """Return needed devices.""" devices = self.addon.devices or [] - # use audio devices + # Use audio devices if self.addon.with_audio and AUDIO_DEVICE not in devices: devices.append(AUDIO_DEVICE) + # Auto mapping UART devices + if self.addon.auto_uart: + for uart_dev in self.docker.hardware.serial_devices: + devices.append("{0}:{0}:rwm".format(uart_dev)) + # Return None if no devices is present - if devices: - return devices - return None + return devices or None @property def ports(self): diff --git a/hassio/hardware.py b/hassio/hardware.py index ef296dd4e..d8ba8eb82 100644 --- a/hassio/hardware.py +++ b/hassio/hardware.py @@ -35,7 +35,7 @@ class Hardware(object): """Return all serial and connected devices.""" dev_list = set() for device in self.context.list_devices(subsystem='tty'): - if 'ID_VENDOR' in device or RE_TTY.match(device.device_node): + if 'ID_VENDOR' in device or RE_TTY.search(device.device_node): dev_list.add(device.device_node) return dev_list