From e97e73e66ef2bd075a6157ce2bfdcd4a724d1d27 Mon Sep 17 00:00:00 2001 From: Guillem Barba Date: Sun, 2 Aug 2015 18:05:28 +0200 Subject: [PATCH 1/4] Add rpi_gpio platform to switch --- .coveragerc | 2 + homeassistant/components/switch/rpi_gpio.py | 124 ++++++++++++++++++++ requirements.txt | 3 + 3 files changed, 129 insertions(+) create mode 100644 homeassistant/components/switch/rpi_gpio.py diff --git a/.coveragerc b/.coveragerc index 0d501e223f0..e87e736ce61 100644 --- a/.coveragerc +++ b/.coveragerc @@ -7,6 +7,8 @@ omit = homeassistant/external/* # omit pieces of code that rely on external devices being present + homeassistant/components/switch/rpi_gpio.py + homeassistant/components/arduino.py homeassistant/components/*/arduino.py diff --git a/homeassistant/components/switch/rpi_gpio.py b/homeassistant/components/switch/rpi_gpio.py new file mode 100644 index 00000000000..c3a16b71ca1 --- /dev/null +++ b/homeassistant/components/switch/rpi_gpio.py @@ -0,0 +1,124 @@ +""" +homeassistant.components.switch.rpi_gpio +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Allows to control a swith using Raspberry GPIO. +Support for switching Raspberry GPIO pins on and off. + +Configuration: + +switch: + platform: rpi_gpio + ports: + 11: Fan Office + 12: Light Desk + +Variables: + +ports +*Required +An array specifying the GPIO ports to use and the name usd in the fronted. + +""" +import logging +try: + import RPi.GPIO as GPIO +except ImportError: + GPIO = None +from homeassistant.helpers.entity import ToggleEntity +from homeassistant.const import (DEVICE_DEFAULT_NAME, + EVENT_HOMEASSISTANT_START, + EVENT_HOMEASSISTANT_STOP) + +_LOGGER = logging.getLogger(__name__) +DEMO = True + + +# pylint: disable=unused-argument +def setup_platform(hass, config, add_devices, discovery_info=None): + """ Sets up the Raspberry PI GPIO switches. """ + if not DEMO and GPIO is None: + _LOGGER.error('RPi.GPIO not available. rpi_gpio switches ignored.') + return + + switches = [] + ports = config.get('ports') + for port_num, port_name in ports.items(): + switches.append(RPiGPIOSwitch(port_name, port_num)) + add_devices(switches) + + def cleanup_gpio(event): + """ Stop the Arduino service. """ + GPIO.cleanup() + + def prepare_gpio(event): + """ Start the Arduino service. """ + hass.bus.listen_once(EVENT_HOMEASSISTANT_STOP, cleanup_gpio) + + hass.bus.listen_once(EVENT_HOMEASSISTANT_START, prepare_gpio) + + +class RPiGPIOSwitch(ToggleEntity): + + ''' + Represents a switch that can be toggled using Raspberry Pi GPIO. + ''' + + def __init__(self, name, gpio): + self._name = name or DEVICE_DEFAULT_NAME + self._state = False + self._gpio = gpio + if not DEMO: + GPIO.setup(gpio, GPIO.OUT) + + @property + def name(self): + """ The name of the port """ + return self._name + + @property + def should_poll(self): + """ No polling needed """ + return False + + @property + def is_on(self): + """ True if device is on. """ + return self._state + + def turn_on(self, **kwargs): + """ Turn the device on. """ + if self._switch(True): + self._state = True + self.update_ha_state() + + def turn_off(self, **kwargs): + """ Turn the device off. """ + if self._switch(False): + self._state = False + self.update_ha_state() + + def _switch(self, new_state): + """ Execute the actual commands """ + _LOGGER.info('Setting GPIO %s to %s', self._gpio, new_state) + try: + if not DEMO: + GPIO.output(self._gpio, 1 if new_state else 0) + except: + _LOGGER.error('GPIO "%s" output failed', self._gpio) + return False + return True + + @property + def device_state_attributes(self): + """ Returns device specific state attributes. """ + return None + + @property + def state_attributes(self): + """ Returns optional state attributes. """ + data = {} + device_attr = self.device_state_attributes + if device_attr is not None: + data.update(device_attr) + return data diff --git a/requirements.txt b/requirements.txt index 42842212907..dfa5ea933b9 100644 --- a/requirements.txt +++ b/requirements.txt @@ -100,3 +100,6 @@ https://github.com/rkabadi/temper-python/archive/master.zip # PyEdimax https://github.com/rkabadi/pyedimax/archive/master.zip + +# RPI-GPIO platform +RPi.GPIO>=0.5.11 From d6c7bf5ac889f5d75cde41fccb6cce0f52994687 Mon Sep 17 00:00:00 2001 From: Guillem Barba Date: Sun, 2 Aug 2015 23:24:36 +0200 Subject: [PATCH 2/4] Remove usless DEMO constant. Add version information in RPi.GPIO requirement --- homeassistant/components/switch/rpi_gpio.py | 10 ++++------ requirements.txt | 2 +- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/homeassistant/components/switch/rpi_gpio.py b/homeassistant/components/switch/rpi_gpio.py index c3a16b71ca1..2096d13b55a 100644 --- a/homeassistant/components/switch/rpi_gpio.py +++ b/homeassistant/components/switch/rpi_gpio.py @@ -30,14 +30,14 @@ from homeassistant.const import (DEVICE_DEFAULT_NAME, EVENT_HOMEASSISTANT_START, EVENT_HOMEASSISTANT_STOP) +REQUIREMENTS = ['RPi.GPIO>=0.5.11'] _LOGGER = logging.getLogger(__name__) -DEMO = True # pylint: disable=unused-argument def setup_platform(hass, config, add_devices, discovery_info=None): """ Sets up the Raspberry PI GPIO switches. """ - if not DEMO and GPIO is None: + if GPIO is None: _LOGGER.error('RPi.GPIO not available. rpi_gpio switches ignored.') return @@ -68,8 +68,7 @@ class RPiGPIOSwitch(ToggleEntity): self._name = name or DEVICE_DEFAULT_NAME self._state = False self._gpio = gpio - if not DEMO: - GPIO.setup(gpio, GPIO.OUT) + GPIO.setup(gpio, GPIO.OUT) @property def name(self): @@ -102,8 +101,7 @@ class RPiGPIOSwitch(ToggleEntity): """ Execute the actual commands """ _LOGGER.info('Setting GPIO %s to %s', self._gpio, new_state) try: - if not DEMO: - GPIO.output(self._gpio, 1 if new_state else 0) + GPIO.output(self._gpio, 1 if new_state else 0) except: _LOGGER.error('GPIO "%s" output failed', self._gpio) return False diff --git a/requirements.txt b/requirements.txt index dfa5ea933b9..f2f532ca19c 100644 --- a/requirements.txt +++ b/requirements.txt @@ -102,4 +102,4 @@ https://github.com/rkabadi/temper-python/archive/master.zip https://github.com/rkabadi/pyedimax/archive/master.zip # RPI-GPIO platform -RPi.GPIO>=0.5.11 +RPi.GPIO >=0.5.11 From e6b4dba330f4554e311c198ba6ba0428064d90e2 Mon Sep 17 00:00:00 2001 From: Guillem Barba Date: Mon, 3 Aug 2015 19:15:27 +0200 Subject: [PATCH 3/4] Remove usless comments --- homeassistant/components/switch/rpi_gpio.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/homeassistant/components/switch/rpi_gpio.py b/homeassistant/components/switch/rpi_gpio.py index 2096d13b55a..e78c5373b13 100644 --- a/homeassistant/components/switch/rpi_gpio.py +++ b/homeassistant/components/switch/rpi_gpio.py @@ -48,11 +48,9 @@ def setup_platform(hass, config, add_devices, discovery_info=None): add_devices(switches) def cleanup_gpio(event): - """ Stop the Arduino service. """ GPIO.cleanup() def prepare_gpio(event): - """ Start the Arduino service. """ hass.bus.listen_once(EVENT_HOMEASSISTANT_STOP, cleanup_gpio) hass.bus.listen_once(EVENT_HOMEASSISTANT_START, prepare_gpio) From 91961e629fba492a8ba8daa5ec0a4a14821b6a51 Mon Sep 17 00:00:00 2001 From: Guillem Barba Date: Thu, 6 Aug 2015 09:56:02 +0200 Subject: [PATCH 4/4] Resolve pylint errors and warnings --- homeassistant/components/switch/rpi_gpio.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/homeassistant/components/switch/rpi_gpio.py b/homeassistant/components/switch/rpi_gpio.py index e78c5373b13..b5f51182748 100644 --- a/homeassistant/components/switch/rpi_gpio.py +++ b/homeassistant/components/switch/rpi_gpio.py @@ -48,9 +48,12 @@ def setup_platform(hass, config, add_devices, discovery_info=None): add_devices(switches) def cleanup_gpio(event): + """ Stuff to do before stop home assistant """ + # pylint: disable=no-member GPIO.cleanup() def prepare_gpio(event): + """ Stuff to do when home assistant starts""" hass.bus.listen_once(EVENT_HOMEASSISTANT_STOP, cleanup_gpio) hass.bus.listen_once(EVENT_HOMEASSISTANT_START, prepare_gpio) @@ -66,6 +69,7 @@ class RPiGPIOSwitch(ToggleEntity): self._name = name or DEVICE_DEFAULT_NAME self._state = False self._gpio = gpio + # pylint: disable=no-member GPIO.setup(gpio, GPIO.OUT) @property @@ -96,15 +100,18 @@ class RPiGPIOSwitch(ToggleEntity): self.update_ha_state() def _switch(self, new_state): - """ Execute the actual commands """ + """ Change the output value to Raspberry Pi GPIO port """ _LOGGER.info('Setting GPIO %s to %s', self._gpio, new_state) + # pylint: disable=bare-except try: + # pylint: disable=no-member GPIO.output(self._gpio, 1 if new_state else 0) except: _LOGGER.error('GPIO "%s" output failed', self._gpio) return False return True + # pylint: disable=no-self-use @property def device_state_attributes(self): """ Returns device specific state attributes. """