2015-10-12 03:11:30 +00:00
|
|
|
"""
|
2015-10-13 18:40:59 +00:00
|
|
|
Exposes regular shell commands as services.
|
2015-10-12 03:11:30 +00:00
|
|
|
|
2015-10-13 18:40:59 +00:00
|
|
|
For more details about this platform, please refer to the documentation at
|
2015-11-09 12:12:18 +00:00
|
|
|
https://home-assistant.io/components/shell_command/
|
2015-10-12 03:11:30 +00:00
|
|
|
"""
|
|
|
|
import logging
|
|
|
|
import subprocess
|
2016-06-23 15:47:56 +00:00
|
|
|
import shlex
|
2015-10-12 03:11:30 +00:00
|
|
|
|
2016-04-12 04:52:39 +00:00
|
|
|
import voluptuous as vol
|
|
|
|
|
2016-06-18 16:57:18 +00:00
|
|
|
from homeassistant.helpers import template
|
|
|
|
from homeassistant.exceptions import TemplateError
|
2016-04-12 04:52:39 +00:00
|
|
|
import homeassistant.helpers.config_validation as cv
|
2015-10-12 03:11:30 +00:00
|
|
|
|
|
|
|
DOMAIN = 'shell_command'
|
|
|
|
|
|
|
|
_LOGGER = logging.getLogger(__name__)
|
|
|
|
|
2016-04-12 04:52:39 +00:00
|
|
|
CONFIG_SCHEMA = vol.Schema({
|
|
|
|
DOMAIN: vol.Schema({
|
|
|
|
cv.slug: cv.string,
|
|
|
|
}),
|
|
|
|
}, extra=vol.ALLOW_EXTRA)
|
2015-10-12 03:11:30 +00:00
|
|
|
|
|
|
|
|
2016-04-12 04:52:39 +00:00
|
|
|
def setup(hass, config):
|
|
|
|
"""Setup the shell_command component."""
|
|
|
|
conf = config.get(DOMAIN, {})
|
2015-10-12 03:11:30 +00:00
|
|
|
|
2016-09-28 04:29:55 +00:00
|
|
|
cache = {}
|
|
|
|
|
2015-10-12 03:11:30 +00:00
|
|
|
def service_handler(call):
|
2016-03-07 17:49:31 +00:00
|
|
|
"""Execute a shell command service."""
|
2016-06-18 16:57:18 +00:00
|
|
|
cmd = conf[call.service]
|
2016-09-28 04:29:55 +00:00
|
|
|
|
|
|
|
if cmd in cache:
|
|
|
|
prog, args, args_compiled = cache[cmd]
|
|
|
|
elif ' ' not in cmd:
|
|
|
|
prog = cmd
|
|
|
|
args = None
|
|
|
|
args_compiled = None
|
|
|
|
cache[cmd] = prog, args, args_compiled
|
|
|
|
else:
|
|
|
|
prog, args = cmd.split(' ', 1)
|
|
|
|
args_compiled = template.Template(args, hass)
|
|
|
|
cache[cmd] = prog, args, args_compiled
|
|
|
|
|
|
|
|
if args_compiled:
|
|
|
|
try:
|
|
|
|
rendered_args = args_compiled.render(call.data)
|
|
|
|
except TemplateError as ex:
|
|
|
|
_LOGGER.exception('Error rendering command template: %s', ex)
|
|
|
|
return
|
|
|
|
else:
|
|
|
|
rendered_args = None
|
|
|
|
|
|
|
|
if rendered_args == args:
|
|
|
|
# no template used. default behavior
|
|
|
|
shell = True
|
|
|
|
else:
|
|
|
|
# template used. Break into list and use shell=False for security
|
|
|
|
cmd = [prog] + shlex.split(rendered_args)
|
|
|
|
shell = False
|
|
|
|
|
2015-10-12 03:11:30 +00:00
|
|
|
try:
|
2016-06-18 16:57:18 +00:00
|
|
|
subprocess.call(cmd, shell=shell,
|
2015-10-12 03:11:30 +00:00
|
|
|
stdout=subprocess.DEVNULL,
|
|
|
|
stderr=subprocess.DEVNULL)
|
|
|
|
except subprocess.SubprocessError:
|
2016-06-18 16:57:18 +00:00
|
|
|
_LOGGER.exception('Error running command: %s', cmd)
|
2015-10-12 03:11:30 +00:00
|
|
|
|
|
|
|
for name in conf.keys():
|
2016-06-23 15:47:56 +00:00
|
|
|
hass.services.register(DOMAIN, name, service_handler)
|
2015-10-12 03:11:30 +00:00
|
|
|
return True
|