Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .coveragerc
Original file line number Diff line number Diff line change
Expand Up @@ -416,6 +416,7 @@ omit =
homeassistant/components/openweathermap/sensor.py
homeassistant/components/openweathermap/weather.py
homeassistant/components/opple/light.py
homeassistant/components/orangepi_gpio/*
homeassistant/components/orvibo/switch.py
homeassistant/components/osramlightify/light.py
homeassistant/components/otp/sensor.py
Expand Down
83 changes: 83 additions & 0 deletions homeassistant/components/orangepi_gpio/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
"""Support for controlling GPIO pins of a Orange Pi."""
import logging

from homeassistant.const import (
EVENT_HOMEASSISTANT_START, EVENT_HOMEASSISTANT_STOP)

REQUIREMENTS = ['OPi.GPIO==0.3.6']
Comment thread
pascallj marked this conversation as resolved.
Outdated

_LOGGER = logging.getLogger(__name__)

CONF_PINMODE = 'pinmode'
Comment thread
pascallj marked this conversation as resolved.
DOMAIN = 'orangepi_gpio'
PINMODES = ['pc', 'zeroplus', 'zeroplus2', 'deo', 'neocore2']


def setup(hass, config):
"""Set up the Orange Pi GPIO component."""
from OPi import GPIO # pylint: disable=import-error

def cleanup_gpio(event):
"""Stuff to do before stopping."""
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)
return True


def setup_mode(mode):
"""Set GPIO pin mode."""
from OPi import GPIO # pylint: disable=import-error
Comment thread
pascallj marked this conversation as resolved.
Outdated

if mode == 'pc':
import orangepi.pc
GPIO.setmode(orangepi.pc.BOARD)
elif mode == 'zeroplus':
import orangepi.zeroplus
GPIO.setmode(orangepi.zeroplus.BOARD)
elif mode == 'zeroplus2':
import orangepi.zeroplus
GPIO.setmode(orangepi.zeroplus2.BOARD)
elif mode == 'duo':
import nanopi.duo
GPIO.setmode(nanopi.duo.BOARD)
elif mode == 'neocore2':
import nanopi.neocore2
GPIO.setmode(nanopi.neocore2.BOARD)


def setup_output(port):
"""Set up a GPIO as output."""
from OPi import GPIO # pylint: disable=import-error
GPIO.setup(port, GPIO.OUT)


def setup_input(port):
"""Set up a GPIO as input."""
from OPi import GPIO # pylint: disable=import-error
GPIO.setup(port, GPIO.IN)


def write_output(port, value):
"""Write a value to a GPIO."""
from OPi import GPIO # pylint: disable=import-error
GPIO.output(port, value)


def read_input(port):
"""Read a value from a GPIO."""
from OPi import GPIO # pylint: disable=import-error
return GPIO.input(port)


def edge_detect(port, event_callback):
"""Add detection for RISING and FALLING events."""
from OPi import GPIO # pylint: disable=import-error
GPIO.add_event_detect(
port,
GPIO.BOTH,
callback=event_callback)
70 changes: 70 additions & 0 deletions homeassistant/components/orangepi_gpio/binary_sensor.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
"""Support for binary sensor using Orange Pi GPIO."""
import logging

from homeassistant.components import orangepi_gpio
Comment thread
pascallj marked this conversation as resolved.
from homeassistant.components.binary_sensor import (
BinarySensorDevice, PLATFORM_SCHEMA)
from homeassistant.const import DEVICE_DEFAULT_NAME

from . import CONF_PINMODE
from .const import CONF_INVERT_LOGIC, CONF_PORTS, PORT_SCHEMA

_LOGGER = logging.getLogger(__name__)

DEPENDENCIES = ['orangepi_gpio']
Comment thread
pascallj marked this conversation as resolved.
Outdated

PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend(PORT_SCHEMA)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since we know that more platforms are likely incoming, it would be better to have all config under the integrating component section, and set up platforms via discovery helper. See the netgear_lte component for example.



def setup_platform(hass, config, add_entities, discovery_info=None):
"""Set up the Orange Pi GPIO devices."""
pinmode = config.get(CONF_PINMODE)
Comment thread
pascallj marked this conversation as resolved.
Outdated
orangepi_gpio.setup_mode(pinmode)

invert_logic = config[CONF_INVERT_LOGIC]

binary_sensors = []
ports = config.get(CONF_PORTS)
for port_num, port_name in ports.items():
binary_sensors.append(OPiGPIOBinarySensor(
port_name, port_num, invert_logic))
add_entities(binary_sensors, True)


class OPiGPIOBinarySensor(BinarySensorDevice):
"""Represent a binary sensor that uses Orange Pi GPIO."""

def __init__(self, name, port, invert_logic):
"""Initialize the Orange Pi binary sensor."""
self._name = name or DEVICE_DEFAULT_NAME
self._port = port
self._invert_logic = invert_logic
self._state = None

orangepi_gpio.setup_input(self._port)
Comment thread
pascallj marked this conversation as resolved.

def read_gpio(port):
"""Read state from GPIO."""
self._state = orangepi_gpio.read_input(self._port)
self.schedule_update_ha_state()

orangepi_gpio.edge_detect(self._port, read_gpio)
Comment thread
pascallj marked this conversation as resolved.

@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

def update(self):
"""Update the GPIO state."""
self._state = orangepi_gpio.read_input(self._port)
21 changes: 21 additions & 0 deletions homeassistant/components/orangepi_gpio/const.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
"""Constants for Orange Pi GPIO."""
import voluptuous as vol

from homeassistant.helpers import config_validation as cv

from . import CONF_PINMODE, PINMODES

CONF_INVERT_LOGIC = 'invert_logic'
CONF_PORTS = 'ports'

DEFAULT_INVERT_LOGIC = False

_SENSORS_SCHEMA = vol.Schema({
cv.positive_int: cv.string,
})

PORT_SCHEMA = {
vol.Required(CONF_PORTS): _SENSORS_SCHEMA,
vol.Required(CONF_PINMODE): vol.In(PINMODES),
vol.Optional(CONF_INVERT_LOGIC, default=DEFAULT_INVERT_LOGIC): cv.boolean,
}
10 changes: 10 additions & 0 deletions homeassistant/components/orangepi_gpio/manifest.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"domain": "orangepi_gpio",
"name": "Orangepi GPIO",
"documentation": "https://www.home-assistant.io/components/orangepi_gpio",
"requirements": [
"OPi.GPIO==0.3.6"
],
"dependencies": [],
"codeowners": []
Comment thread
pascallj marked this conversation as resolved.
Outdated
}
70 changes: 70 additions & 0 deletions homeassistant/components/orangepi_gpio/switch.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
"""Allows to configure a switch using Orange Pi GPIO."""
import logging

from homeassistant.components.switch import PLATFORM_SCHEMA
from homeassistant.components import orangepi_gpio
from homeassistant.const import DEVICE_DEFAULT_NAME
from homeassistant.helpers.entity import ToggleEntity

from . import CONF_PINMODE
from .const import CONF_INVERT_LOGIC, CONF_PORTS, PORT_SCHEMA

_LOGGER = logging.getLogger(__name__)

DEPENDENCIES = ['orangepi_gpio']

PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend(PORT_SCHEMA)


def setup_platform(hass, config, add_entities, discovery_info=None):
"""Set up the Orange Pi GPIO devices."""
pinmode = config.get(CONF_PINMODE)
Comment thread
pascallj marked this conversation as resolved.
Outdated
orangepi_gpio.setup_mode(pinmode)

invert_logic = config[CONF_INVERT_LOGIC]

switches = []
ports = config.get(CONF_PORTS)
for port, name in ports.items():
switches.append(OPiGPIOSwitch(name, port, invert_logic))
add_entities(switches)


class OPiGPIOSwitch(ToggleEntity):
"""Representation of a Orange Pi GPIO."""

def __init__(self, name, port, invert_logic):
"""Initialize the pin."""
self._name = name or DEVICE_DEFAULT_NAME
self._port = port
self._invert_logic = invert_logic
self._state = False
orangepi_gpio.setup_output(self._port)
orangepi_gpio.write_output(self._port, 1 if self._invert_logic else 0)
Comment thread
pascallj marked this conversation as resolved.
Outdated

@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 is_on(self):
"""Return true if device is on."""
return self._state

def turn_on(self, **kwargs):
"""Turn the device on."""
orangepi_gpio.write_output(self._port, 0 if self._invert_logic else 1)
self._state = True
self.schedule_update_ha_state()
Comment thread
pascallj marked this conversation as resolved.
Outdated

def turn_off(self, **kwargs):
"""Turn the device off."""
orangepi_gpio.write_output(self._port, 1 if self._invert_logic else 0)
self._state = False
self.schedule_update_ha_state()
Comment thread
pascallj marked this conversation as resolved.
Outdated
3 changes: 3 additions & 0 deletions requirements_all.txt
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@ HAP-python==2.4.2
# homeassistant.components.mastodon
Mastodon.py==1.3.1

# homeassistant.components.orangepi_gpio
OPi.GPIO==0.3.6

# homeassistant.components.github
PyGithub==1.43.5

Expand Down