From d91f414313c7cff5db30294e69a56d39ce9d3e5a Mon Sep 17 00:00:00 2001 From: Wolfgang Ettlinger Date: Tue, 2 Jun 2015 15:40:02 +0200 Subject: [PATCH 1/3] added generic module to switch swiches using shell commands --- README.md | 1 + .../components/switch/command_switch.py | 68 +++++++++++++++++++ 2 files changed, 69 insertions(+) create mode 100644 homeassistant/components/switch/command_switch.py diff --git a/README.md b/README.md index 5eb5ad4937a..1648b526332 100644 --- a/README.md +++ b/README.md @@ -12,6 +12,7 @@ It offers the following functionality through built-in components: * Track and control [Google Chromecasts](http://www.google.com/intl/en/chrome/devices/chromecast) * Track running services by monitoring `ps` output * Track and control [Tellstick devices and sensors](http://www.telldus.se/products/tellstick) + * Control low-cost 433 MHz remote control wall-socket devices (https://github.com/r10r/rcswitch-pi) and other switches that can be turned on/off with shell commands * Turn on the lights when people get home after sun set * Turn on lights slowly during sun set to compensate for light loss * Turn off all lights and devices when everybody leaves the house diff --git a/homeassistant/components/switch/command_switch.py b/homeassistant/components/switch/command_switch.py new file mode 100644 index 00000000000..163881bbf19 --- /dev/null +++ b/homeassistant/components/switch/command_switch.py @@ -0,0 +1,68 @@ +# -*- coding: utf-8 -*- +import logging +from homeassistant.helpers.entity import ToggleEntity +from homeassistant.const import STATE_ON, STATE_OFF, DEVICE_DEFAULT_NAME +import subprocess + +_LOGGER = logging.getLogger(__name__) + + +# pylint: disable=unused-argument +def setup_platform(hass, config, add_devices_callback, discovery_info=None): + """ Find and return switches controlled by shell commands. """ + + switches = config.get('switches', {}) + devices = [] + + for k, v in switches.items(): + devices.append( + CommandSwitch( + k, + v.get('oncmd', 'true'), + v.get('offcmd', 'true'))) + + add_devices_callback(devices) + + +class CommandSwitch(ToggleEntity): + def __init__(self, name, command_on, command_off): + self._name = name or DEVICE_DEFAULT_NAME + self._state = STATE_OFF + self._command_on = command_on + self._command_off = command_off + + @staticmethod + def _switch(command): + _LOGGER.info('Running command: {}'.format(command)) + + success = (subprocess.call(command, shell=True) == 0) + + if not success: + _LOGGER.error('Command failed: {}'.format(command)) + + return success + + @property + def should_poll(self): + return False + + @property + def name(self): + return self._name + + @property + def state(self): + return self._state + + @property + def is_on(self): + return self._state == STATE_ON + + def turn_on(self, **kwargs): + if CommandSwitch._switch(self._command_on): + self._state = STATE_ON + + def turn_off(self, **kwargs): + if CommandSwitch._switch(self._command_off): + self._state = STATE_OFF + From b35bdc606ab47c9e920883ad65fb637a32ef708f Mon Sep 17 00:00:00 2001 From: Wolfgang Ettlinger Date: Tue, 2 Jun 2015 15:54:43 +0200 Subject: [PATCH 2/3] style adaptions --- .../components/switch/command_switch.py | 23 +++++++++++++++---- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/homeassistant/components/switch/command_switch.py b/homeassistant/components/switch/command_switch.py index 163881bbf19..d57871153c9 100644 --- a/homeassistant/components/switch/command_switch.py +++ b/homeassistant/components/switch/command_switch.py @@ -1,4 +1,10 @@ # -*- coding: utf-8 -*- +""" +homeassistant.components.switch.command_switch +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Allows to configure custom shell commands to turn a switch on/off. +""" import logging from homeassistant.helpers.entity import ToggleEntity from homeassistant.const import STATE_ON, STATE_OFF, DEVICE_DEFAULT_NAME @@ -14,17 +20,18 @@ def setup_platform(hass, config, add_devices_callback, discovery_info=None): switches = config.get('switches', {}) devices = [] - for k, v in switches.items(): + for dev_name, properties in switches.items(): devices.append( CommandSwitch( - k, - v.get('oncmd', 'true'), - v.get('offcmd', 'true'))) + dev_name, + properties.get('oncmd', 'true'), + properties.get('offcmd', 'true'))) add_devices_callback(devices) class CommandSwitch(ToggleEntity): + """ Represents a switch that can be togggled using shell commands """ def __init__(self, name, command_on, command_off): self._name = name or DEVICE_DEFAULT_NAME self._state = STATE_OFF @@ -33,6 +40,7 @@ class CommandSwitch(ToggleEntity): @staticmethod def _switch(command): + """ Execute the actual commands """ _LOGGER.info('Running command: {}'.format(command)) success = (subprocess.call(command, shell=True) == 0) @@ -44,25 +52,30 @@ class CommandSwitch(ToggleEntity): @property def should_poll(self): + """ No polling needed """ return False @property def name(self): + """ The name of the switch """ return self._name @property def state(self): + """ Returns the state of the switch. """ return self._state @property def is_on(self): + """ True if device is on. """ return self._state == STATE_ON def turn_on(self, **kwargs): + """ Turn the device on. """ if CommandSwitch._switch(self._command_on): self._state = STATE_ON def turn_off(self, **kwargs): + """ Turn the device off. """ if CommandSwitch._switch(self._command_off): self._state = STATE_OFF - From 5d1e0d5c440db7c8ff470834aa4048c53ffa6cb5 Mon Sep 17 00:00:00 2001 From: Wolfgang Ettlinger Date: Tue, 2 Jun 2015 17:04:14 +0200 Subject: [PATCH 3/3] fixed pylint warnings --- homeassistant/components/switch/command_switch.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/homeassistant/components/switch/command_switch.py b/homeassistant/components/switch/command_switch.py index d57871153c9..291cd3af04d 100644 --- a/homeassistant/components/switch/command_switch.py +++ b/homeassistant/components/switch/command_switch.py @@ -41,12 +41,12 @@ class CommandSwitch(ToggleEntity): @staticmethod def _switch(command): """ Execute the actual commands """ - _LOGGER.info('Running command: {}'.format(command)) + _LOGGER.info('Running command: %s', command) success = (subprocess.call(command, shell=True) == 0) if not success: - _LOGGER.error('Command failed: {}'.format(command)) + _LOGGER.error('Command failed: %s', command) return success