commit
7f0c334391
5 changed files with 320 additions and 0 deletions
|
@ -7,6 +7,9 @@ omit =
|
|||
homeassistant/external/*
|
||||
|
||||
# omit pieces of code that rely on external devices being present
|
||||
homeassistant/components/arduino.py
|
||||
homeassistant/components/*/arduino.py
|
||||
|
||||
homeassistant/components/wink.py
|
||||
homeassistant/components/*/wink.py
|
||||
|
||||
|
|
134
homeassistant/components/arduino.py
Normal file
134
homeassistant/components/arduino.py
Normal file
|
@ -0,0 +1,134 @@
|
|||
"""
|
||||
components.arduino
|
||||
~~~~~~~~~~~~~~~~~~
|
||||
Arduino component that connects to a directly attached Arduino board which
|
||||
runs with the Firmata firmware.
|
||||
|
||||
Configuration:
|
||||
|
||||
To use the Arduino board you will need to add something like the following
|
||||
to your config/configuration.yaml
|
||||
|
||||
arduino:
|
||||
port: /dev/ttyACM0
|
||||
|
||||
Variables:
|
||||
|
||||
port
|
||||
*Required
|
||||
The port where is your board connected to your Home Assistant system.
|
||||
If you are using an original Arduino the port will be named ttyACM*. The exact
|
||||
number can be determined with 'ls /dev/ttyACM*' or check your 'dmesg'/
|
||||
'journalctl -f' output. Keep in mind that Arduino clones are often using a
|
||||
different name for the port (e.g. '/dev/ttyUSB*').
|
||||
|
||||
A word of caution: The Arduino is not storing states. This means that with
|
||||
every initialization the pins are set to off/low.
|
||||
"""
|
||||
import logging
|
||||
|
||||
from PyMata.pymata import PyMata
|
||||
import serial
|
||||
|
||||
from homeassistant.helpers import validate_config
|
||||
from homeassistant.const import (EVENT_HOMEASSISTANT_START,
|
||||
EVENT_HOMEASSISTANT_STOP)
|
||||
|
||||
DOMAIN = "arduino"
|
||||
DEPENDENCIES = []
|
||||
BOARD = None
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def setup(hass, config):
|
||||
""" Setup the Arduino component. """
|
||||
|
||||
if not validate_config(config,
|
||||
{DOMAIN: ['port']},
|
||||
_LOGGER):
|
||||
return False
|
||||
|
||||
# pylint: disable=global-statement
|
||||
global BOARD
|
||||
try:
|
||||
BOARD = ArduinoBoard(config[DOMAIN]['port'])
|
||||
except (serial.serialutil.SerialException, FileNotFoundError):
|
||||
_LOGGER.exception("Your port is not accessible.")
|
||||
return False
|
||||
|
||||
if BOARD.get_firmata()[1] <= 2:
|
||||
_LOGGER.error("The StandardFirmata sketch should be 2.2 or newer.")
|
||||
return False
|
||||
|
||||
def stop_arduino(event):
|
||||
""" Stop the Arduino service. """
|
||||
BOARD.disconnect()
|
||||
|
||||
def start_arduino(event):
|
||||
""" Start the Arduino service. """
|
||||
hass.bus.listen_once(EVENT_HOMEASSISTANT_STOP, stop_arduino)
|
||||
|
||||
hass.bus.listen_once(EVENT_HOMEASSISTANT_START, start_arduino)
|
||||
|
||||
return True
|
||||
|
||||
|
||||
class ArduinoBoard(object):
|
||||
""" Represents an Arduino board. """
|
||||
|
||||
def __init__(self, port):
|
||||
self._port = port
|
||||
self._board = PyMata(self._port, verbose=False)
|
||||
|
||||
def set_mode(self, pin, direction, mode):
|
||||
""" Sets the mode and the direction of a given pin. """
|
||||
if mode == 'analog' and direction == 'in':
|
||||
self._board.set_pin_mode(pin,
|
||||
self._board.INPUT,
|
||||
self._board.ANALOG)
|
||||
elif mode == 'analog' and direction == 'out':
|
||||
self._board.set_pin_mode(pin,
|
||||
self._board.OUTPUT,
|
||||
self._board.ANALOG)
|
||||
elif mode == 'digital' and direction == 'in':
|
||||
self._board.set_pin_mode(pin,
|
||||
self._board.OUTPUT,
|
||||
self._board.DIGITAL)
|
||||
elif mode == 'digital' and direction == 'out':
|
||||
self._board.set_pin_mode(pin,
|
||||
self._board.OUTPUT,
|
||||
self._board.DIGITAL)
|
||||
elif mode == 'pwm':
|
||||
self._board.set_pin_mode(pin,
|
||||
self._board.OUTPUT,
|
||||
self._board.PWM)
|
||||
|
||||
def get_analog_inputs(self):
|
||||
""" Get the values from the pins. """
|
||||
self._board.capability_query()
|
||||
return self._board.get_analog_response_table()
|
||||
|
||||
def set_digital_out_high(self, pin):
|
||||
""" Sets a given digital pin to high. """
|
||||
self._board.digital_write(pin, 1)
|
||||
|
||||
def set_digital_out_low(self, pin):
|
||||
""" Sets a given digital pin to low. """
|
||||
self._board.digital_write(pin, 0)
|
||||
|
||||
def get_digital_in(self, pin):
|
||||
""" Gets the value from a given digital pin. """
|
||||
self._board.digital_read(pin)
|
||||
|
||||
def get_analog_in(self, pin):
|
||||
""" Gets the value from a given analog pin. """
|
||||
self._board.analog_read(pin)
|
||||
|
||||
def get_firmata(self):
|
||||
""" Return the version of the Firmata firmware. """
|
||||
return self._board.get_firmata_version()
|
||||
|
||||
def disconnect(self):
|
||||
""" Disconnects the board and closes the serial connection. """
|
||||
self._board.reset()
|
||||
self._board.close()
|
87
homeassistant/components/sensor/arduino.py
Normal file
87
homeassistant/components/sensor/arduino.py
Normal file
|
@ -0,0 +1,87 @@
|
|||
"""
|
||||
homeassistant.components.sensor.arduino
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
Support for getting information from Arduino pins. Only analog pins are
|
||||
supported.
|
||||
|
||||
Configuration:
|
||||
|
||||
sensor:
|
||||
platform: arduino
|
||||
pins:
|
||||
7:
|
||||
name: Door switch
|
||||
type: analog
|
||||
0:
|
||||
name: Brightness
|
||||
type: analog
|
||||
|
||||
Variables:
|
||||
|
||||
pins
|
||||
*Required
|
||||
An array specifying the digital pins to use on the Arduino board.
|
||||
|
||||
These are the variables for the pins array:
|
||||
|
||||
name
|
||||
*Required
|
||||
The name for the pin that will be used in the frontend.
|
||||
|
||||
type
|
||||
*Required
|
||||
The type of the pin: 'analog'.
|
||||
"""
|
||||
import logging
|
||||
|
||||
import homeassistant.components.arduino as arduino
|
||||
from homeassistant.helpers.entity import Entity
|
||||
from homeassistant.const import DEVICE_DEFAULT_NAME
|
||||
|
||||
DEPENDENCIES = ['arduino']
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def setup_platform(hass, config, add_devices, discovery_info=None):
|
||||
""" Sets up the Arduino platform. """
|
||||
|
||||
# Verify that Arduino board is present
|
||||
if arduino.BOARD is None:
|
||||
_LOGGER.error('A connection has not been made to the Arduino board.')
|
||||
return False
|
||||
|
||||
sensors = []
|
||||
pins = config.get('pins')
|
||||
for pinnum, pin in pins.items():
|
||||
if pin.get('name'):
|
||||
sensors.append(ArduinoSensor(pin.get('name'),
|
||||
pinnum,
|
||||
'analog'))
|
||||
add_devices(sensors)
|
||||
|
||||
|
||||
class ArduinoSensor(Entity):
|
||||
""" Represents an Arduino Sensor. """
|
||||
def __init__(self, name, pin, pin_type):
|
||||
self._pin = pin
|
||||
self._name = name or DEVICE_DEFAULT_NAME
|
||||
self.pin_type = pin_type
|
||||
self.direction = 'in'
|
||||
self._value = None
|
||||
|
||||
arduino.BOARD.set_mode(self._pin, self.direction, self.pin_type)
|
||||
|
||||
@property
|
||||
def state(self):
|
||||
""" Returns the state of the sensor. """
|
||||
return self._value
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
""" Get the name of the sensor. """
|
||||
return self._name
|
||||
|
||||
def update(self):
|
||||
""" Get the latest value from the pin. """
|
||||
self._value = arduino.BOARD.get_analog_inputs()[self._pin][1]
|
93
homeassistant/components/switch/arduino.py
Normal file
93
homeassistant/components/switch/arduino.py
Normal file
|
@ -0,0 +1,93 @@
|
|||
"""
|
||||
homeassistant.components.switch.arduino
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
Support for switching Arduino pins on and off. So fare only digital pins are
|
||||
supported.
|
||||
|
||||
Configuration:
|
||||
|
||||
switch:
|
||||
platform: arduino
|
||||
pins:
|
||||
11:
|
||||
name: Fan Office
|
||||
type: digital
|
||||
12:
|
||||
name: Light Desk
|
||||
type: digital
|
||||
|
||||
Variables:
|
||||
|
||||
pins
|
||||
*Required
|
||||
An array specifying the digital pins to use on the Arduino board.
|
||||
|
||||
These are the variables for the pins array:
|
||||
|
||||
name
|
||||
*Required
|
||||
The name for the pin that will be used in the frontend.
|
||||
|
||||
type
|
||||
*Required
|
||||
The type of the pin: 'digital'.
|
||||
"""
|
||||
import logging
|
||||
|
||||
import homeassistant.components.arduino as arduino
|
||||
from homeassistant.components.switch import SwitchDevice
|
||||
from homeassistant.const import DEVICE_DEFAULT_NAME
|
||||
|
||||
DEPENDENCIES = ['arduino']
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def setup_platform(hass, config, add_devices, discovery_info=None):
|
||||
""" Sets up the Arduino platform. """
|
||||
|
||||
# Verify that Arduino board is present
|
||||
if arduino.BOARD is None:
|
||||
_LOGGER.error('A connection has not been made to the Arduino board.')
|
||||
return False
|
||||
|
||||
switches = []
|
||||
pins = config.get('pins')
|
||||
for pinnum, pin in pins.items():
|
||||
if pin.get('name'):
|
||||
switches.append(ArduinoSwitch(pin.get('name'),
|
||||
pinnum,
|
||||
pin.get('type')))
|
||||
add_devices(switches)
|
||||
|
||||
|
||||
class ArduinoSwitch(SwitchDevice):
|
||||
""" Represents an Arduino Switch. """
|
||||
def __init__(self, name, pin, pin_type):
|
||||
self._pin = pin
|
||||
self._name = name or DEVICE_DEFAULT_NAME
|
||||
self.pin_type = pin_type
|
||||
self.direction = 'out'
|
||||
self._state = False
|
||||
|
||||
arduino.BOARD.set_mode(self._pin, self.direction, self.pin_type)
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
""" Get the name of the pin. """
|
||||
return self._name
|
||||
|
||||
@property
|
||||
def is_on(self):
|
||||
""" Returns True if pin is high/on. """
|
||||
return self._state
|
||||
|
||||
def turn_on(self):
|
||||
""" Turns the pin to high/on. """
|
||||
self._state = True
|
||||
arduino.BOARD.set_digital_out_high(self._pin)
|
||||
|
||||
def turn_off(self):
|
||||
""" Turns the pin to low/off. """
|
||||
self._state = False
|
||||
arduino.BOARD.set_digital_out_low(self._pin)
|
|
@ -73,3 +73,6 @@ jsonrpc-requests>=0.1
|
|||
|
||||
# Forecast.io Bindings (sensor.forecast)
|
||||
python-forecastio>=1.3.3
|
||||
|
||||
# Firmata Bindings (*.arduino)
|
||||
PyMata==2.07a
|
||||
|
|
Loading…
Add table
Reference in a new issue