Merge pull request #278 from sfam/dev

New RPi_GPIO sensor and switch improvements
pull/283/head
Paulus Schoutsen 2015-08-26 08:40:54 -07:00
commit e2cfe2a7d2
3 changed files with 152 additions and 5 deletions

View File

@ -62,6 +62,7 @@ omit =
homeassistant/components/sensor/mysensors.py
homeassistant/components/sensor/openweathermap.py
homeassistant/components/sensor/rfxtrx.py
homeassistant/components/sensor/rpi_gpio.py
homeassistant/components/sensor/sabnzbd.py
homeassistant/components/sensor/swiss_public_transport.py
homeassistant/components/sensor/systemmonitor.py

View File

@ -0,0 +1,133 @@
# -*- coding: utf-8 -*-
"""
homeassistant.components.sensor.rpi_gpio
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Allows to configure a binary state sensor using RPi GPIO.
Note: To use RPi GPIO, Home Assistant must be run as root.
sensor:
platform: rpi_gpio
pull_mode: "UP"
value_high: "Active"
value_low: "Inactive"
ports:
11: PIR Office
12: PIR Bedroom
Variables:
pull_mode
*Optional
The internal pull to use (UP or DOWN). Default is UP.
value_high
*Optional
The value of the sensor when the port is HIGH. Default is "HIGH".
value_low
*Optional
The value of the sensor when the port is LOW. Default is "LOW".
bouncetime
*Optional
The time in milliseconds for port debouncing. Default is 50ms.
ports
*Required
An array specifying the GPIO ports to use and the name to use in the frontend.
"""
import logging
from homeassistant.helpers.entity import Entity
try:
import RPi.GPIO as GPIO
except ImportError:
GPIO = None
from homeassistant.const import (DEVICE_DEFAULT_NAME,
EVENT_HOMEASSISTANT_START,
EVENT_HOMEASSISTANT_STOP)
DEFAULT_PULL_MODE = "UP"
DEFAULT_VALUE_HIGH = "HIGH"
DEFAULT_VALUE_LOW = "LOW"
DEFAULT_BOUNCETIME = 50
REQUIREMENTS = ['RPi.GPIO>=0.5.11']
_LOGGER = logging.getLogger(__name__)
# pylint: disable=unused-argument
def setup_platform(hass, config, add_devices, discovery_info=None):
""" Sets up the Raspberry PI GPIO ports. """
if GPIO is None:
_LOGGER.error('RPi.GPIO not available. rpi_gpio ports ignored.')
return
# pylint: disable=no-member
GPIO.setmode(GPIO.BCM)
sensors = []
pull_mode = config.get('pull_mode', DEFAULT_PULL_MODE)
value_high = config.get('value_high', DEFAULT_VALUE_HIGH)
value_low = config.get('value_low', DEFAULT_VALUE_LOW)
bouncetime = config.get('bouncetime', DEFAULT_BOUNCETIME)
ports = config.get('ports')
for port_num, port_name in ports.items():
sensors.append(RPiGPIOSensor(
port_name, port_num, pull_mode,
value_high, value_low, bouncetime))
add_devices(sensors)
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)
# pylint: disable=too-many-arguments, too-many-instance-attributes
class RPiGPIOSensor(Entity):
""" Sets up the Raspberry PI GPIO ports. """
def __init__(self, port_name, port_num, pull_mode,
value_high, value_low, bouncetime):
# pylint: disable=no-member
self._name = port_name or DEVICE_DEFAULT_NAME
self._port = port_num
self._pull = GPIO.PUD_DOWN if pull_mode == "DOWN" else GPIO.PUD_UP
self._vhigh = value_high
self._vlow = value_low
self._bouncetime = bouncetime
GPIO.setup(self._port, GPIO.IN, pull_up_down=self._pull)
self._state = self._vhigh if GPIO.input(self._port) else self._vlow
def edge_callback(channel):
""" port changed state """
# pylint: disable=no-member
self._state = self._vhigh if GPIO.input(channel) else self._vlow
self.update_ha_state()
GPIO.add_event_detect(
self._port,
GPIO.BOTH,
callback=edge_callback,
bouncetime=self._bouncetime)
@property
def should_poll(self):
""" No polling needed """
return False
@property
def name(self):
""" The name of the sensor """
return self._name
@property
def state(self):
""" Returns the state of the entity. """
return self._state

View File

@ -2,21 +2,28 @@
homeassistant.components.switch.rpi_gpio
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Allows to control the GPIO pins of a Raspberry Pi.
Note: To use RPi GPIO, Home Assistant must be run as root.
Configuration:
switch:
platform: rpi_gpio
invert_logic: false
ports:
11: Fan Office
12: Light Desk
Variables:
invert_logic
*Optional
If true, inverts the output logic to ACTIVE LOW. Default is false (ACTIVE HIGH)
ports
*Required
An array specifying the GPIO ports to use and the name to use in the frontend.
"""
import logging
try:
import RPi.GPIO as GPIO
@ -27,6 +34,8 @@ from homeassistant.const import (DEVICE_DEFAULT_NAME,
EVENT_HOMEASSISTANT_START,
EVENT_HOMEASSISTANT_STOP)
DEFAULT_INVERT_LOGIC = False
REQUIREMENTS = ['RPi.GPIO>=0.5.11']
_LOGGER = logging.getLogger(__name__)
@ -37,11 +46,14 @@ def setup_platform(hass, config, add_devices, discovery_info=None):
if GPIO is None:
_LOGGER.error('RPi.GPIO not available. rpi_gpio ports ignored.')
return
# pylint: disable=no-member
GPIO.setmode(GPIO.BCM)
switches = []
invert_logic = config.get('invert_logic', DEFAULT_INVERT_LOGIC)
ports = config.get('ports')
for port_num, port_name in ports.items():
switches.append(RPiGPIOSwitch(port_name, port_num))
switches.append(RPiGPIOSwitch(port_name, port_num, invert_logic))
add_devices(switches)
def cleanup_gpio(event):
@ -59,10 +71,11 @@ def setup_platform(hass, config, add_devices, discovery_info=None):
class RPiGPIOSwitch(ToggleEntity):
""" Represents a port that can be toggled using Raspberry Pi GPIO. """
def __init__(self, name, gpio):
def __init__(self, name, gpio, invert_logic):
self._name = name or DEVICE_DEFAULT_NAME
self._state = False
self._gpio = gpio
self._active_state = not invert_logic
self._state = not self._active_state
# pylint: disable=no-member
GPIO.setup(gpio, GPIO.OUT)
@ -83,13 +96,13 @@ class RPiGPIOSwitch(ToggleEntity):
def turn_on(self, **kwargs):
""" Turn the device on. """
if self._switch(True):
if self._switch(self._active_state):
self._state = True
self.update_ha_state()
def turn_off(self, **kwargs):
""" Turn the device off. """
if self._switch(False):
if self._switch(not self._active_state):
self._state = False
self.update_ha_state()