Add Remote RPi Component (#23518)

* Add Remote RPi Component

* Add Remote RPi Component

* fix imports

* Added support for setup as switch and binary_sensor

* remove pylint error handling

* Changed to domain config

* Changed to domain config

* Changed to domain config

* Changed to domain config

* Update __init__.py

* Update manifest.json

* Update requirements_all.txt

* Update switch.py

* Update binary_sensor.py

* Changed to domain config
This commit is contained in:
jgriff2 2019-05-26 04:52:06 -07:00 committed by Pascal Vizeli
parent 9438dd1cbd
commit 6e1728542e
6 changed files with 274 additions and 0 deletions

View File

@ -487,6 +487,7 @@ omit =
homeassistant/components/reddit/*
homeassistant/components/rejseplanen/sensor.py
homeassistant/components/remember_the_milk/__init__.py
homeassistant/components/remote_rpi_gpio/*
homeassistant/components/rest/binary_sensor.py
homeassistant/components/rest/notify.py
homeassistant/components/rest/switch.py

View File

@ -0,0 +1,63 @@
"""Support for controlling GPIO pins of a Raspberry Pi."""
import logging
_LOGGER = logging.getLogger(__name__)
CONF_BOUNCETIME = 'bouncetime'
CONF_INVERT_LOGIC = 'invert_logic'
CONF_PULL_MODE = 'pull_mode'
DEFAULT_BOUNCETIME = 50
DEFAULT_INVERT_LOGIC = False
DEFAULT_PULL_MODE = "UP"
DOMAIN = 'remote_rpi_gpio'
def setup(hass, config):
"""Set up the Raspberry Pi Remote GPIO component."""
return True
def setup_output(address, port, invert_logic):
"""Set up a GPIO as output."""
from gpiozero import LED
from gpiozero.pins.pigpio import PiGPIOFactory
try:
return LED(port, active_high=invert_logic,
pin_factory=PiGPIOFactory(address))
except (ValueError, IndexError, KeyError):
return None
def setup_input(address, port, pull_mode, bouncetime):
"""Set up a GPIO as input."""
from gpiozero import Button
from gpiozero.pins.pigpio import PiGPIOFactory
if pull_mode == "UP":
pull_gpio_up = True
elif pull_mode == "DOWN":
pull_gpio_up = False
try:
return Button(port,
pull_up=pull_gpio_up,
bounce_time=bouncetime,
pin_factory=PiGPIOFactory(address))
except (ValueError, IndexError, KeyError, IOError):
return None
def write_output(switch, value):
"""Write a value to a GPIO."""
if value == 1:
switch.on()
if value == 0:
switch.off()
def read_input(button):
"""Read a value from a GPIO."""
return button.is_pressed

View File

@ -0,0 +1,106 @@
"""Support for binary sensor using RPi GPIO."""
import logging
import voluptuous as vol
import requests
from homeassistant.const import CONF_HOST
from homeassistant.components.binary_sensor import (
BinarySensorDevice, PLATFORM_SCHEMA)
import homeassistant.helpers.config_validation as cv
from . import (CONF_BOUNCETIME, CONF_PULL_MODE, CONF_INVERT_LOGIC,
DEFAULT_BOUNCETIME, DEFAULT_INVERT_LOGIC, DEFAULT_PULL_MODE)
from .. import remote_rpi_gpio
_LOGGER = logging.getLogger(__name__)
CONF_PORTS = 'ports'
_SENSORS_SCHEMA = vol.Schema({
cv.positive_int: cv.string,
})
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
vol.Required(CONF_HOST): cv.string,
vol.Required(CONF_PORTS): _SENSORS_SCHEMA,
vol.Optional(CONF_INVERT_LOGIC,
default=DEFAULT_INVERT_LOGIC): cv.boolean,
vol.Optional(CONF_BOUNCETIME,
default=DEFAULT_BOUNCETIME): cv.positive_int,
vol.Optional(CONF_PULL_MODE,
default=DEFAULT_PULL_MODE): cv.string,
})
def setup_platform(hass, config, add_entities, discovery_info=None):
"""Set up the Raspberry PI GPIO devices."""
address = config['host']
invert_logic = config[CONF_INVERT_LOGIC]
pull_mode = config[CONF_PULL_MODE]
ports = config['ports']
bouncetime = config[CONF_BOUNCETIME]/1000
devices = []
for port_num, port_name in ports.items():
try:
button = remote_rpi_gpio.setup_input(address,
port_num,
pull_mode,
bouncetime)
except (ValueError, IndexError, KeyError, IOError):
return
new_sensor = RemoteRPiGPIOBinarySensor(port_name, button, invert_logic)
devices.append(new_sensor)
add_entities(devices, True)
class RemoteRPiGPIOBinarySensor(BinarySensorDevice):
"""Represent a binary sensor that uses a Remote Raspberry Pi GPIO."""
def __init__(self, name, button, invert_logic):
"""Initialize the RPi binary sensor."""
self._name = name
self._invert_logic = invert_logic
self._state = False
self._button = button
async def async_added_to_hass(self):
"""Run when entity about to be added to hass."""
def read_gpio():
"""Read state from GPIO."""
self._state = remote_rpi_gpio.read_input(self._button)
self.schedule_update_ha_state()
self._button.when_released = read_gpio
self._button.when_pressed = read_gpio
@property
def should_poll(self):
"""No polling needed."""
return False
@property
def name(self):
"""Return the name of the sensor."""
return self._name
@property
def is_on(self):
"""Return the state of the entity."""
return self._state != self._invert_logic
@property
def device_class(self):
"""Return the class of this sensor, from DEVICE_CLASSES."""
return
def update(self):
"""Update the GPIO state."""
try:
self._state = remote_rpi_gpio.read_input(self._button)
except requests.exceptions.ConnectionError:
return

View File

@ -0,0 +1,10 @@
{
"domain": "remote_rpi_gpio",
"name": "remote_rpi_gpio",
"documentation": "https://www.home-assistant.io/components/remote_rpi_gpio",
"requirements": [
"gpiozero==1.4.1"
],
"dependencies": [],
"codeowners": []
}

View File

@ -0,0 +1,91 @@
"""Allows to configure a switch using RPi GPIO."""
import logging
import voluptuous as vol
from homeassistant.components.switch import SwitchDevice, PLATFORM_SCHEMA
from homeassistant.const import DEVICE_DEFAULT_NAME, CONF_HOST
import homeassistant.helpers.config_validation as cv
from . import CONF_INVERT_LOGIC, DEFAULT_INVERT_LOGIC
from .. import remote_rpi_gpio
_LOGGER = logging.getLogger(__name__)
CONF_PORTS = 'ports'
_SENSORS_SCHEMA = vol.Schema({
cv.positive_int: cv.string,
})
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
vol.Required(CONF_HOST): cv.string,
vol.Required(CONF_PORTS): _SENSORS_SCHEMA,
vol.Optional(CONF_INVERT_LOGIC,
default=DEFAULT_INVERT_LOGIC): cv.boolean
})
def setup_platform(hass, config, add_entities, discovery_info=None):
"""Set up the Remote Raspberry PI GPIO devices."""
address = config[CONF_HOST]
invert_logic = config[CONF_INVERT_LOGIC]
ports = config[CONF_PORTS]
devices = []
for port, name in ports.items():
try:
led = remote_rpi_gpio.setup_output(
address, port, invert_logic)
except (ValueError, IndexError, KeyError, IOError):
return
new_switch = RemoteRPiGPIOSwitch(name, led, invert_logic)
devices.append(new_switch)
add_entities(devices)
class RemoteRPiGPIOSwitch(SwitchDevice):
"""Representation of a Remtoe Raspberry Pi GPIO."""
def __init__(self, name, led, invert_logic):
"""Initialize the pin."""
self._name = name or DEVICE_DEFAULT_NAME
self._state = False
self._invert_logic = invert_logic
self._switch = led
@property
def name(self):
"""Return the name of the switch."""
return self._name
@property
def should_poll(self):
"""No polling needed."""
return False
@property
def assumed_state(self):
"""If unable to access real state of the entity."""
return True
@property
def is_on(self):
"""Return true if device is on."""
return self._state
def turn_on(self, **kwargs):
"""Turn the device on."""
remote_rpi_gpio.write_output(self._switch,
0 if self._invert_logic else 1)
self._state = True
self.schedule_update_ha_state()
def turn_off(self, **kwargs):
"""Turn the device off."""
remote_rpi_gpio.write_output(self._switch,
1 if self._invert_logic else 0)
self._state = False
self.schedule_update_ha_state()

View File

@ -518,6 +518,9 @@ googledevices==1.0.2
# homeassistant.components.google_travel_time
googlemaps==2.5.1
# homeassistant.components.remote_rpi_gpio
gpiozero==1.4.1
# homeassistant.components.gpsd
gps3==0.33.3