From b33ae47a4c7faadd1b2e9f2ff40d817c8c603ef4 Mon Sep 17 00:00:00 2001 From: Fabian Affolter Date: Mon, 22 Jun 2015 17:58:27 +0200 Subject: [PATCH] add arduino component --- homeassistant/components/arduino.py | 134 ++++++++++++++++++++++++++++ 1 file changed, 134 insertions(+) create mode 100644 homeassistant/components/arduino.py diff --git a/homeassistant/components/arduino.py b/homeassistant/components/arduino.py new file mode 100644 index 00000000000..e7131f9c9e0 --- /dev/null +++ b/homeassistant/components/arduino.py @@ -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()