From 475b631d9c6a86b2bdc2f272137bd65d940c8c2f Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Thu, 14 Jan 2016 22:51:28 -0800 Subject: [PATCH 01/23] Initial version input_boolean --- homeassistant/components/input_boolean.py | 124 ++++++++++++++++++++++ tests/components/test_input_boolean.py | 95 +++++++++++++++++ 2 files changed, 219 insertions(+) create mode 100644 homeassistant/components/input_boolean.py create mode 100644 tests/components/test_input_boolean.py diff --git a/homeassistant/components/input_boolean.py b/homeassistant/components/input_boolean.py new file mode 100644 index 00000000000..27216782ba1 --- /dev/null +++ b/homeassistant/components/input_boolean.py @@ -0,0 +1,124 @@ +""" +Component to keep track of user controlled booleans for within automation. + +For more details about this component, please refer to the documentation +at https://home-assistant.io/components/input_boolean/ +""" +import logging + +from homeassistant.const import ( + STATE_ON, SERVICE_TURN_ON, SERVICE_TURN_OFF, ATTR_ENTITY_ID) +from homeassistant.helpers.entity_component import EntityComponent +from homeassistant.helpers.entity import ToggleEntity +from homeassistant.util import slugify + +DOMAIN = 'input_boolean' + +ENTITY_ID_FORMAT = DOMAIN + '.{}' + +_LOGGER = logging.getLogger(__name__) + +CONF_NAME = "name" +CONF_INITIAL = "initial" +CONF_ICON = "icon" + + +def is_on(hass, entity_id): + """Test if input_boolean is True.""" + return hass.states.is_state(entity_id, STATE_ON) + + +def turn_on(hass, entity_id): + """Set input_boolean to True.""" + hass.services.call(DOMAIN, SERVICE_TURN_ON, {ATTR_ENTITY_ID: entity_id}) + + +def turn_off(hass, entity_id): + """Set input_boolean to False.""" + hass.services.call(DOMAIN, SERVICE_TURN_OFF, {ATTR_ENTITY_ID: entity_id}) + + +def setup(hass, config): + """Set up input booleans.""" + if not isinstance(config.get(DOMAIN), dict): + _LOGGER.error('Expected %s config to be a dictionary', DOMAIN) + return False + + component = EntityComponent(_LOGGER, DOMAIN, hass) + + entities = [] + + for object_id, cfg in config[DOMAIN].items(): + if object_id != slugify(object_id): + _LOGGER.warning("Found invalid key for boolean input: %s. " + "Use %s instead", object_id, slugify(object_id)) + continue + if not cfg: + cfg = {} + + name = cfg.get(CONF_NAME) + state = cfg.get(CONF_INITIAL, False) + icon = cfg.get(CONF_ICON) + + entities.append(InputBoolean(object_id, name, state, icon)) + + if not entities: + return False + + component.add_entities(entities) + + def toggle_service(service): + """Handle a calls to the input boolean services.""" + target_inputs = component.extract_from_service(service) + + for input_b in target_inputs: + if service.service == SERVICE_TURN_ON: + input_b.turn_on() + else: + input_b.turn_off() + + hass.services.register(DOMAIN, SERVICE_TURN_OFF, toggle_service) + hass.services.register(DOMAIN, SERVICE_TURN_ON, toggle_service) + + return True + + +class InputBoolean(ToggleEntity): + """Represent a boolean input within Home Assistant.""" + + def __init__(self, object_id, name, state, icon): + """Initialize a boolean input.""" + self.entity_id = ENTITY_ID_FORMAT.format(object_id) + self._name = name + self._state = state + self._icon = icon + + @property + def should_poll(self): + """If entitiy should be polled.""" + return False + + @property + def name(self): + """Name of the boolean input.""" + return self._name + + @property + def icon(self): + """Icon to be used for this entity.""" + return self._icon + + @property + def is_on(self): + """True if entity is on.""" + return self._state + + def turn_on(self, **kwargs): + """Turn the entity on.""" + self._state = True + self.update_ha_state() + + def turn_off(self, **kwargs): + """Turn the entity off.""" + self._state = False + self.update_ha_state() diff --git a/tests/components/test_input_boolean.py b/tests/components/test_input_boolean.py new file mode 100644 index 00000000000..a7366d91fd3 --- /dev/null +++ b/tests/components/test_input_boolean.py @@ -0,0 +1,95 @@ +""" +tests.components.test_input_boolean +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Tests input_boolean component. +""" +# pylint: disable=too-many-public-methods,protected-access +import unittest + +from homeassistant.components import input_boolean +from homeassistant.const import ( + STATE_ON, STATE_OFF, ATTR_ICON, ATTR_FRIENDLY_NAME) + +from tests.common import get_test_home_assistant + + +class TestInputBoolean(unittest.TestCase): + """ Test the input boolean module. """ + + def setUp(self): # pylint: disable=invalid-name + self.hass = get_test_home_assistant() + + def tearDown(self): # pylint: disable=invalid-name + """ Stop down stuff we started. """ + self.hass.stop() + + def test_config(self): + """Test config.""" + self.assertFalse(input_boolean.setup(self.hass, { + 'input_boolean': { + 'test 1': None, + } + })) + + self.assertFalse(input_boolean.setup(self.hass, { + 'input_boolean': { + } + })) + + def test_methods(self): + """ Test is_on, turn_on, turn_off methods. """ + self.assertTrue(input_boolean.setup(self.hass, { + 'input_boolean': { + 'test_1': None, + } + })) + entity_id = 'input_boolean.test_1' + + self.assertFalse( + input_boolean.is_on(self.hass, entity_id)) + + input_boolean.turn_on(self.hass, entity_id) + + self.hass.pool.block_till_done() + + self.assertTrue( + input_boolean.is_on(self.hass, entity_id)) + + input_boolean.turn_off(self.hass, entity_id) + + self.hass.pool.block_till_done() + + self.assertFalse( + input_boolean.is_on(self.hass, entity_id)) + + def test_config_options(self): + count_start = len(self.hass.states.entity_ids()) + + self.assertTrue(input_boolean.setup(self.hass, { + 'input_boolean': { + 'test_1': None, + 'test_2': { + 'name': 'Hello World', + 'icon': 'work', + 'initial': True, + }, + }, + })) + + self.assertEqual(count_start + 2, len(self.hass.states.entity_ids())) + + state_1 = self.hass.states.get('input_boolean.test_1') + state_2 = self.hass.states.get('input_boolean.test_2') + + self.assertIsNotNone(state_1) + self.assertIsNotNone(state_2) + + self.assertEqual(STATE_OFF, state_1.state) + self.assertNotIn(ATTR_ICON, state_1.attributes) + self.assertNotIn(ATTR_FRIENDLY_NAME, state_1.attributes) + + self.assertEqual(STATE_ON, state_2.state) + self.assertEqual('Hello World', + state_2.attributes.get(ATTR_FRIENDLY_NAME)) + self.assertEqual('work', state_2.attributes.get(ATTR_ICON)) From 0a711922efd202e7472d40b48e5f3e0226374762 Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Thu, 14 Jan 2016 23:19:08 -0800 Subject: [PATCH 02/23] Remove unnecessary instance variable --- homeassistant/components/script.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/script.py b/homeassistant/components/script.py index 3e13db66699..238bea7dd4c 100644 --- a/homeassistant/components/script.py +++ b/homeassistant/components/script.py @@ -81,7 +81,7 @@ def setup(hass, config): object_id) continue alias = cfg.get(CONF_ALIAS, object_id) - script = Script(hass, object_id, alias, cfg[CONF_SEQUENCE]) + script = Script(object_id, alias, cfg[CONF_SEQUENCE]) component.add_entities((script,)) hass.services.register(DOMAIN, object_id, service_handler) @@ -106,8 +106,7 @@ def setup(hass, config): class Script(ToggleEntity): """ Represents a script. """ # pylint: disable=too-many-instance-attributes - def __init__(self, hass, object_id, name, sequence): - self.hass = hass + def __init__(self, object_id, name, sequence): self.entity_id = ENTITY_ID_FORMAT.format(object_id) self._name = name self.sequence = sequence From 6b899ddc1db3b59bb2c26ae22c172b75a352d0bf Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Thu, 14 Jan 2016 23:25:25 -0800 Subject: [PATCH 03/23] 100% test coverage for input_boolean --- homeassistant/components/input_boolean.py | 4 ++-- tests/components/test_input_boolean.py | 6 +++++- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/input_boolean.py b/homeassistant/components/input_boolean.py index 27216782ba1..f86fffcaeb6 100644 --- a/homeassistant/components/input_boolean.py +++ b/homeassistant/components/input_boolean.py @@ -65,8 +65,6 @@ def setup(hass, config): if not entities: return False - component.add_entities(entities) - def toggle_service(service): """Handle a calls to the input boolean services.""" target_inputs = component.extract_from_service(service) @@ -80,6 +78,8 @@ def setup(hass, config): hass.services.register(DOMAIN, SERVICE_TURN_OFF, toggle_service) hass.services.register(DOMAIN, SERVICE_TURN_ON, toggle_service) + component.add_entities(entities) + return True diff --git a/tests/components/test_input_boolean.py b/tests/components/test_input_boolean.py index a7366d91fd3..ace91018ccd 100644 --- a/tests/components/test_input_boolean.py +++ b/tests/components/test_input_boolean.py @@ -26,14 +26,18 @@ class TestInputBoolean(unittest.TestCase): def test_config(self): """Test config.""" + self.assertFalse(input_boolean.setup(self.hass, { + 'input_boolean': None + })) + self.assertFalse(input_boolean.setup(self.hass, { 'input_boolean': { - 'test 1': None, } })) self.assertFalse(input_boolean.setup(self.hass, { 'input_boolean': { + 'name with space': None } })) From c4e10356387899d25a0ad61271687294adbb7879 Mon Sep 17 00:00:00 2001 From: pavoni Date: Fri, 15 Jan 2016 09:21:48 +0000 Subject: [PATCH 04/23] Add humidity sensor, add units for humidity and light sensors. --- homeassistant/components/sensor/vera.py | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/sensor/vera.py b/homeassistant/components/sensor/vera.py index b381974ab31..cef4edb036d 100644 --- a/homeassistant/components/sensor/vera.py +++ b/homeassistant/components/sensor/vera.py @@ -45,7 +45,10 @@ def get_devices(hass, config): hass.bus.listen_once(EVENT_HOMEASSISTANT_STOP, stop_subscription) - categories = ['Temperature Sensor', 'Light Sensor', 'Sensor'] + categories = ['Temperature Sensor', + 'Light Sensor', + 'Humidity Sensor', + 'Sensor'] devices = [] try: devices = vera_controller.get_devices(categories) @@ -106,7 +109,12 @@ class VeraSensor(Entity): @property def unit_of_measurement(self): """ Unit of measurement of this entity, if any. """ - return self._temperature_units + if self.vera_device.category == "Temperature Sensor": + return self._temperature_units + elif self.vera_device.category == "Light Sensor": + return 'lux' + elif self.vera_device.category == "Humidity Sensor": + return '%' @property def state_attributes(self): @@ -140,7 +148,7 @@ class VeraSensor(Entity): def update(self): if self.vera_device.category == "Temperature Sensor": current_temp = self.vera_device.get_value('CurrentTemperature') - vera_temp_units = self.vera_device.veraController.temperature_units + vera_temp_units = self.vera_device.vera_controller.temperature_units if vera_temp_units == 'F': self._temperature_units = TEMP_FAHRENHEIT @@ -157,6 +165,8 @@ class VeraSensor(Entity): self.current_value = current_temp elif self.vera_device.category == "Light Sensor": self.current_value = self.vera_device.get_value('CurrentLevel') + elif self.vera_device.category == "Humidity Sensor": + self.current_value = self.vera_device.get_value('CurrentLevel') elif self.vera_device.category == "Sensor": tripped = self.vera_device.get_value('Tripped') self.current_value = 'Tripped' if tripped == '1' else 'Not Tripped' From 4bc33d03521baca23c0702900167a07760ae5902 Mon Sep 17 00:00:00 2001 From: pavoni Date: Fri, 15 Jan 2016 10:34:14 +0000 Subject: [PATCH 05/23] Bump pyvera version. --- homeassistant/components/light/vera.py | 2 +- homeassistant/components/sensor/vera.py | 2 +- homeassistant/components/switch/vera.py | 2 +- requirements_all.txt | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/homeassistant/components/light/vera.py b/homeassistant/components/light/vera.py index 42a5e7b7899..937c1ea4a4d 100644 --- a/homeassistant/components/light/vera.py +++ b/homeassistant/components/light/vera.py @@ -15,7 +15,7 @@ from homeassistant.components.light import ATTR_BRIGHTNESS from homeassistant.const import EVENT_HOMEASSISTANT_STOP, STATE_ON -REQUIREMENTS = ['pyvera==0.2.3'] +REQUIREMENTS = ['pyvera==0.2.4'] _LOGGER = logging.getLogger(__name__) diff --git a/homeassistant/components/sensor/vera.py b/homeassistant/components/sensor/vera.py index cef4edb036d..7d94236a62f 100644 --- a/homeassistant/components/sensor/vera.py +++ b/homeassistant/components/sensor/vera.py @@ -15,7 +15,7 @@ from homeassistant.const import ( ATTR_BATTERY_LEVEL, ATTR_TRIPPED, ATTR_ARMED, ATTR_LAST_TRIP_TIME, TEMP_CELCIUS, TEMP_FAHRENHEIT, EVENT_HOMEASSISTANT_STOP) -REQUIREMENTS = ['pyvera==0.2.3'] +REQUIREMENTS = ['pyvera==0.2.4'] _LOGGER = logging.getLogger(__name__) diff --git a/homeassistant/components/switch/vera.py b/homeassistant/components/switch/vera.py index 4094fe61f4f..2eb1da8ceb9 100644 --- a/homeassistant/components/switch/vera.py +++ b/homeassistant/components/switch/vera.py @@ -21,7 +21,7 @@ from homeassistant.const import ( STATE_ON, STATE_OFF) -REQUIREMENTS = ['pyvera==0.2.3'] +REQUIREMENTS = ['pyvera==0.2.4'] _LOGGER = logging.getLogger(__name__) diff --git a/requirements_all.txt b/requirements_all.txt index 11f3873c4b1..2105f1b2763 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -62,7 +62,7 @@ tellcore-py==1.1.2 # homeassistant.components.light.vera # homeassistant.components.sensor.vera # homeassistant.components.switch.vera -pyvera==0.2.3 +pyvera==0.2.4 # homeassistant.components.wink # homeassistant.components.light.wink From 719f9a63d900d3da868ed9a809cb958f85210e03 Mon Sep 17 00:00:00 2001 From: pavoni Date: Fri, 15 Jan 2016 10:52:58 +0000 Subject: [PATCH 06/23] Fix style issue --- homeassistant/components/sensor/vera.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/homeassistant/components/sensor/vera.py b/homeassistant/components/sensor/vera.py index 7d94236a62f..3d37c457be2 100644 --- a/homeassistant/components/sensor/vera.py +++ b/homeassistant/components/sensor/vera.py @@ -148,7 +148,8 @@ class VeraSensor(Entity): def update(self): if self.vera_device.category == "Temperature Sensor": current_temp = self.vera_device.get_value('CurrentTemperature') - vera_temp_units = self.vera_device.vera_controller.temperature_units + vera_temp_units = ( + self.vera_device.vera_controller.temperature_units) if vera_temp_units == 'F': self._temperature_units = TEMP_FAHRENHEIT From 4fd79afa42f5c3d815d0d07449d8db6ff60fefb0 Mon Sep 17 00:00:00 2001 From: pavoni Date: Fri, 15 Jan 2016 11:45:17 +0000 Subject: [PATCH 07/23] Bump pyvera version. --- homeassistant/components/light/vera.py | 2 +- homeassistant/components/sensor/vera.py | 2 +- homeassistant/components/switch/vera.py | 2 +- requirements_all.txt | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/homeassistant/components/light/vera.py b/homeassistant/components/light/vera.py index 937c1ea4a4d..5b2e74f3ac8 100644 --- a/homeassistant/components/light/vera.py +++ b/homeassistant/components/light/vera.py @@ -15,7 +15,7 @@ from homeassistant.components.light import ATTR_BRIGHTNESS from homeassistant.const import EVENT_HOMEASSISTANT_STOP, STATE_ON -REQUIREMENTS = ['pyvera==0.2.4'] +REQUIREMENTS = ['pyvera==0.2.5'] _LOGGER = logging.getLogger(__name__) diff --git a/homeassistant/components/sensor/vera.py b/homeassistant/components/sensor/vera.py index 3d37c457be2..9bf1c071450 100644 --- a/homeassistant/components/sensor/vera.py +++ b/homeassistant/components/sensor/vera.py @@ -15,7 +15,7 @@ from homeassistant.const import ( ATTR_BATTERY_LEVEL, ATTR_TRIPPED, ATTR_ARMED, ATTR_LAST_TRIP_TIME, TEMP_CELCIUS, TEMP_FAHRENHEIT, EVENT_HOMEASSISTANT_STOP) -REQUIREMENTS = ['pyvera==0.2.4'] +REQUIREMENTS = ['pyvera==0.2.5'] _LOGGER = logging.getLogger(__name__) diff --git a/homeassistant/components/switch/vera.py b/homeassistant/components/switch/vera.py index 2eb1da8ceb9..ec7f7395e26 100644 --- a/homeassistant/components/switch/vera.py +++ b/homeassistant/components/switch/vera.py @@ -21,7 +21,7 @@ from homeassistant.const import ( STATE_ON, STATE_OFF) -REQUIREMENTS = ['pyvera==0.2.4'] +REQUIREMENTS = ['pyvera==0.2.5'] _LOGGER = logging.getLogger(__name__) diff --git a/requirements_all.txt b/requirements_all.txt index 2105f1b2763..24be13da807 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -62,7 +62,7 @@ tellcore-py==1.1.2 # homeassistant.components.light.vera # homeassistant.components.sensor.vera # homeassistant.components.switch.vera -pyvera==0.2.4 +pyvera==0.2.5 # homeassistant.components.wink # homeassistant.components.light.wink From 8617b92d1b064dc193a68ba9668d8cccdefaba66 Mon Sep 17 00:00:00 2001 From: sfam Date: Fri, 15 Jan 2016 11:59:58 +0000 Subject: [PATCH 08/23] Update RPi.GPIO version and code refactoring --- .coveragerc | 1 + .../components/binary_sensor/rpi_gpio.py | 73 ++++++++++++++++ homeassistant/components/rpi_gpio.py | 68 +++++++++++++++ homeassistant/components/sensor/rpi_gpio.py | 81 +++++------------- homeassistant/components/switch/rpi_gpio.py | 84 ++++--------------- requirements_all.txt | 3 +- 6 files changed, 182 insertions(+), 128 deletions(-) create mode 100644 homeassistant/components/binary_sensor/rpi_gpio.py create mode 100644 homeassistant/components/rpi_gpio.py diff --git a/.coveragerc b/.coveragerc index f5eabf3b7f6..8f83575342c 100644 --- a/.coveragerc +++ b/.coveragerc @@ -43,6 +43,7 @@ omit = homeassistant/components/binary_sensor/arest.py homeassistant/components/binary_sensor/rest.py + homeassistant/components/binary_sensor/rpi_gpio.py homeassistant/components/browser.py homeassistant/components/camera/* homeassistant/components/device_tracker/actiontec.py diff --git a/homeassistant/components/binary_sensor/rpi_gpio.py b/homeassistant/components/binary_sensor/rpi_gpio.py new file mode 100644 index 00000000000..b6fb43a8372 --- /dev/null +++ b/homeassistant/components/binary_sensor/rpi_gpio.py @@ -0,0 +1,73 @@ +""" +homeassistant.components.binary_sensor.rpi_gpio +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Allows to configure a binary_sensor state sensor using RPi GPIO. + +For more details about this platform, please refer to the documentation at +https://home-assistant.io/components/binary_sensor.rpi_gpio/ +""" + +import logging +import homeassistant.components.rpi_gpio as rpi_gpio +from homeassistant.helpers.entity import Entity +from homeassistant.const import (STATE_ON, STATE_OFF, DEVICE_DEFAULT_NAME) + +DEFAULT_PULL_MODE = "UP" +DEFAULT_BOUNCETIME = 50 +DEFAULT_INVERT_LOGIC = False + +DEPENDENCIES = ['rpi_gpio'] +_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. """ + + pull_mode = config.get('pull_mode', DEFAULT_PULL_MODE) + bouncetime = config.get('bouncetime', DEFAULT_BOUNCETIME) + invert_logic = config.get('invert_logic', DEFAULT_INVERT_LOGIC) + + binary_sensors = [] + ports = config.get('ports') + for port_num, port_name in ports.items(): + binary_sensors.append(RPiGPIOBinarySensor( + port_name, port_num, pull_mode, bouncetime, invert_logic)) + add_devices(binary_sensors) + + +# pylint: disable=too-many-arguments, too-many-instance-attributes +class RPiGPIOBinarySensor(Entity): + """ Sets up the Raspberry PI GPIO ports. """ + def __init__(self, name, port, pull_mode, bouncetime, invert_logic): + # pylint: disable=no-member + + self._name = name or DEVICE_DEFAULT_NAME + self._port = port + self._pull_mode = pull_mode + self._bouncetime = bouncetime + self._invert_logic = invert_logic + + rpi_gpio.setup_input(self._port, self._pull_mode) + self._state = rpi_gpio.read_input(self._port) + + def read_gpio(port): + """ Reads state from GPIO. """ + self._state = rpi_gpio.read_input(self._port) + self.update_ha_state() + rpi_gpio.edge_detect(self._port, read_gpio, 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 STATE_ON if self._state != self._invert_logic else STATE_OFF diff --git a/homeassistant/components/rpi_gpio.py b/homeassistant/components/rpi_gpio.py new file mode 100644 index 00000000000..cb81fecfdc0 --- /dev/null +++ b/homeassistant/components/rpi_gpio.py @@ -0,0 +1,68 @@ +""" +homeassistant.components.switch.rpi_gpio +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Allows to control the GPIO pins of a Raspberry Pi. + +For more details about this platform, please refer to the documentation at +https://home-assistant.io/components/switch.rpi_gpio/ +""" +import logging +try: + import RPi.GPIO as GPIO +except ImportError: + GPIO = None +from homeassistant.const import (EVENT_HOMEASSISTANT_START, + EVENT_HOMEASSISTANT_STOP) +REQUIREMENTS = ['RPi.GPIO==0.6.1'] +DOMAIN = "rpi_gpio" +_LOGGER = logging.getLogger(__name__) + + +# pylint: disable=no-member +def setup(hass, config): + """ Sets up the Raspberry PI GPIO ports. """ + if GPIO is None: + _LOGGER.error('RPi.GPIO not available. rpi_gpio ports ignored.') + return False + + def cleanup_gpio(event): + """ Stuff to do before stop home assistant. """ + 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) + GPIO.setmode(GPIO.BCM) + return True + + +def setup_output(port): + """ Setup a GPIO as output """ + GPIO.setup(port, GPIO.OUT) + + +def setup_input(port, pull_mode): + """ Setup a GPIO as input """ + GPIO.setup(port, GPIO.IN, + GPIO.PUD_DOWN if pull_mode == 'DOWN' else GPIO.PUD_UP) + + +def write_output(port, value): + """ Write a value to a GPIO""" + GPIO.output(port, value) + + +def read_input(port): + """ Read a value from a GPIO""" + return GPIO.input(port) + + +def edge_detect(port, event_callback, bounce): + """ Adds detection for RISING and FALLING events """ + GPIO.add_event_detect( + port, + GPIO.BOTH, + callback=event_callback, + bouncetime=bounce) diff --git a/homeassistant/components/sensor/rpi_gpio.py b/homeassistant/components/sensor/rpi_gpio.py index ef7ea8c33c1..415e717a6b0 100644 --- a/homeassistant/components/sensor/rpi_gpio.py +++ b/homeassistant/components/sensor/rpi_gpio.py @@ -6,92 +6,51 @@ Allows to configure a binary state sensor using RPi GPIO. For more details about this platform, please refer to the documentation at https://home-assistant.io/components/sensor.rpi_gpio/ """ -# pylint: disable=import-error -import logging -from homeassistant.helpers.entity import Entity -from homeassistant.const import (DEVICE_DEFAULT_NAME, - EVENT_HOMEASSISTANT_START, - EVENT_HOMEASSISTANT_STOP) +import logging +from homeassistant.components.binary_sensor.rpi_gpio import RPiGPIOBinarySensor DEFAULT_PULL_MODE = "UP" +DEFAULT_BOUNCETIME = 50 DEFAULT_VALUE_HIGH = "HIGH" DEFAULT_VALUE_LOW = "LOW" -DEFAULT_BOUNCETIME = 50 -REQUIREMENTS = ['RPi.GPIO==0.5.11'] +DEPENDENCIES = ['rpi_gpio'] _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. """ - import RPi.GPIO as GPIO - GPIO.setmode(GPIO.BCM) - sensors = [] pull_mode = config.get('pull_mode', DEFAULT_PULL_MODE) + bouncetime = config.get('bouncetime', DEFAULT_BOUNCETIME) value_high = config.get('value_high', DEFAULT_VALUE_HIGH) value_low = config.get('value_low', DEFAULT_VALUE_LOW) - bouncetime = config.get('bouncetime', DEFAULT_BOUNCETIME) + + sensors = [] ports = config.get('ports') - for port_num, port_name in ports.items(): + for port, name in ports.items(): sensors.append(RPiGPIOSensor( - port_name, port_num, pull_mode, - value_high, value_low, bouncetime)) + name, port, pull_mode, bouncetime, + value_high, value_low)) 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): +class RPiGPIOSensor(RPiGPIOBinarySensor): """ 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 - import RPi.GPIO as GPIO - 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 __init__(self, name, port, pull_mode, bouncetime, + value_high, value_low): - 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 + self._value_high = value_high + self._value_low = value_low + super().__init__(name, port, pull_mode, bouncetime, False) @property def state(self): """ Returns the state of the entity. """ - return self._state + if self._state != self._invert_logic: + return self._value_high + else: + return self._value_low diff --git a/homeassistant/components/switch/rpi_gpio.py b/homeassistant/components/switch/rpi_gpio.py index 1c36aa262f4..3a3256e5591 100644 --- a/homeassistant/components/switch/rpi_gpio.py +++ b/homeassistant/components/switch/rpi_gpio.py @@ -7,59 +7,38 @@ For more details about this platform, please refer to the documentation at https://home-assistant.io/components/switch.rpi_gpio/ """ import logging -try: - import RPi.GPIO as GPIO -except ImportError: - GPIO = None +import homeassistant.components.rpi_gpio as rpi_gpio from homeassistant.helpers.entity import ToggleEntity -from homeassistant.const import (DEVICE_DEFAULT_NAME, - EVENT_HOMEASSISTANT_START, - EVENT_HOMEASSISTANT_STOP) +from homeassistant.const import (DEVICE_DEFAULT_NAME) DEFAULT_INVERT_LOGIC = False -REQUIREMENTS = ['RPi.GPIO==0.5.11'] +DEPENDENCIES = ['rpi_gpio'] _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) + + invert_logic = config.get('invert_logic', DEFAULT_INVERT_LOGIC) 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, invert_logic)) + for port, name in ports.items(): + switches.append(RPiGPIOSwitch(name, port, invert_logic)) add_devices(switches) - 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) - class RPiGPIOSwitch(ToggleEntity): """ Represents a port that can be toggled using Raspberry Pi GPIO. """ - def __init__(self, name, gpio, invert_logic): + def __init__(self, name, port, invert_logic): self._name = name or DEVICE_DEFAULT_NAME - self._gpio = gpio - self._active_state = not invert_logic - self._state = not self._active_state - # pylint: disable=no-member - GPIO.setup(gpio, GPIO.OUT) + self._port = port + self._invert_logic = invert_logic + self._state = False + rpi_gpio.setup_output(self._port) @property def name(self): @@ -76,41 +55,14 @@ class RPiGPIOSwitch(ToggleEntity): """ True if device is on. """ return self._state - def turn_on(self, **kwargs): + def turn_on(self): """ Turn the device on. """ - if self._switch(self._active_state): - self._state = True + rpi_gpio.write_output(self._port, 0 if self._invert_logic else 1) + self._state = True self.update_ha_state() - def turn_off(self, **kwargs): + def turn_off(self): """ Turn the device off. """ - if self._switch(not self._active_state): - self._state = False + rpi_gpio.write_output(self._port, 1 if self._invert_logic else 0) + self._state = False self.update_ha_state() - - def _switch(self, new_state): - """ Change the output value to Raspberry Pi GPIO port. """ - _LOGGER.info('Setting GPIO %s to %s', self._gpio, new_state) - # pylint: disable=bare-except - try: - # pylint: disable=no-member - GPIO.output(self._gpio, 1 if new_state else 0) - except: - _LOGGER.error('GPIO "%s" output failed', self._gpio) - return False - return True - - # pylint: disable=no-self-use - @property - def device_state_attributes(self): - """ Returns device specific state attributes. """ - return None - - @property - def state_attributes(self): - """ Returns optional state attributes. """ - data = {} - device_attr = self.device_state_attributes - if device_attr is not None: - data.update(device_attr) - return data diff --git a/requirements_all.txt b/requirements_all.txt index 4d38ada0daf..a11e42e5b60 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -146,9 +146,10 @@ https://github.com/HydrelioxGitHub/netatmo-api-python/archive/43ff238a0122b0939a # homeassistant.components.sensor.openweathermap pyowm==2.3.0 +# homeassistant.components.binary_sensor.rpi_gpio # homeassistant.components.sensor.rpi_gpio # homeassistant.components.switch.rpi_gpio -# RPi.GPIO==0.5.11 +# RPi.GPIO==0.6.1 # homeassistant.components.sensor.sabnzbd https://github.com/jamespcole/home-assistant-nzb-clients/archive/616cad59154092599278661af17e2a9f2cf5e2a9.zip#python-sabnzbd==0.1 From 7c925ac295830459954d3aa1663b6a0525734949 Mon Sep 17 00:00:00 2001 From: sfam Date: Fri, 15 Jan 2016 12:35:06 +0000 Subject: [PATCH 09/23] update comments --- .../components/binary_sensor/rpi_gpio.py | 6 +++--- homeassistant/components/rpi_gpio.py | 15 ++++++++------- homeassistant/components/sensor/rpi_gpio.py | 6 +++--- homeassistant/components/switch/rpi_gpio.py | 10 +++++----- 4 files changed, 19 insertions(+), 18 deletions(-) diff --git a/homeassistant/components/binary_sensor/rpi_gpio.py b/homeassistant/components/binary_sensor/rpi_gpio.py index b6fb43a8372..972c319d958 100644 --- a/homeassistant/components/binary_sensor/rpi_gpio.py +++ b/homeassistant/components/binary_sensor/rpi_gpio.py @@ -1,7 +1,7 @@ """ homeassistant.components.binary_sensor.rpi_gpio ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Allows to configure a binary_sensor state sensor using RPi GPIO. +Allows to configure a binary_sensor using RPi GPIO. For more details about this platform, please refer to the documentation at https://home-assistant.io/components/binary_sensor.rpi_gpio/ @@ -22,7 +22,7 @@ _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. """ + """ Sets up the Raspberry PI GPIO devices. """ pull_mode = config.get('pull_mode', DEFAULT_PULL_MODE) bouncetime = config.get('bouncetime', DEFAULT_BOUNCETIME) @@ -38,7 +38,7 @@ def setup_platform(hass, config, add_devices, discovery_info=None): # pylint: disable=too-many-arguments, too-many-instance-attributes class RPiGPIOBinarySensor(Entity): - """ Sets up the Raspberry PI GPIO ports. """ + """ Represents a binary sensor that uses Raspberry Pi GPIO. """ def __init__(self, name, port, pull_mode, bouncetime, invert_logic): # pylint: disable=no-member diff --git a/homeassistant/components/rpi_gpio.py b/homeassistant/components/rpi_gpio.py index cb81fecfdc0..86800a36dbe 100644 --- a/homeassistant/components/rpi_gpio.py +++ b/homeassistant/components/rpi_gpio.py @@ -4,8 +4,9 @@ homeassistant.components.switch.rpi_gpio Allows to control the GPIO pins of a Raspberry Pi. For more details about this platform, please refer to the documentation at -https://home-assistant.io/components/switch.rpi_gpio/ +https://home-assistant.io/components/rpi_gpio/ """ + import logging try: import RPi.GPIO as GPIO @@ -20,7 +21,7 @@ _LOGGER = logging.getLogger(__name__) # pylint: disable=no-member def setup(hass, config): - """ Sets up the Raspberry PI GPIO ports. """ + """ Sets up the Raspberry PI GPIO component. """ if GPIO is None: _LOGGER.error('RPi.GPIO not available. rpi_gpio ports ignored.') return False @@ -39,28 +40,28 @@ def setup(hass, config): def setup_output(port): - """ Setup a GPIO as output """ + """ Setup a GPIO as output. """ GPIO.setup(port, GPIO.OUT) def setup_input(port, pull_mode): - """ Setup a GPIO as input """ + """ Setup a GPIO as input. """ GPIO.setup(port, GPIO.IN, GPIO.PUD_DOWN if pull_mode == 'DOWN' else GPIO.PUD_UP) def write_output(port, value): - """ Write a value to a GPIO""" + """ Write a value to a GPIO. """ GPIO.output(port, value) def read_input(port): - """ Read a value from a GPIO""" + """ Read a value from a GPIO. """ return GPIO.input(port) def edge_detect(port, event_callback, bounce): - """ Adds detection for RISING and FALLING events """ + """ Adds detection for RISING and FALLING events. """ GPIO.add_event_detect( port, GPIO.BOTH, diff --git a/homeassistant/components/sensor/rpi_gpio.py b/homeassistant/components/sensor/rpi_gpio.py index 415e717a6b0..d07375f9e31 100644 --- a/homeassistant/components/sensor/rpi_gpio.py +++ b/homeassistant/components/sensor/rpi_gpio.py @@ -1,7 +1,7 @@ """ homeassistant.components.sensor.rpi_gpio ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Allows to configure a binary state sensor using RPi GPIO. +Allows to configure a sensor using RPi GPIO. For more details about this platform, please refer to the documentation at https://home-assistant.io/components/sensor.rpi_gpio/ @@ -21,7 +21,7 @@ _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. """ + """ Sets up the Raspberry PI GPIO devices. """ pull_mode = config.get('pull_mode', DEFAULT_PULL_MODE) bouncetime = config.get('bouncetime', DEFAULT_BOUNCETIME) @@ -39,7 +39,7 @@ def setup_platform(hass, config, add_devices, discovery_info=None): # pylint: disable=too-many-arguments, too-many-instance-attributes class RPiGPIOSensor(RPiGPIOBinarySensor): - """ Sets up the Raspberry PI GPIO ports. """ + """ Represents a sensor that uses Raspberry Pi GPIO. """ def __init__(self, name, port, pull_mode, bouncetime, value_high, value_low): diff --git a/homeassistant/components/switch/rpi_gpio.py b/homeassistant/components/switch/rpi_gpio.py index 3a3256e5591..dffa4682279 100644 --- a/homeassistant/components/switch/rpi_gpio.py +++ b/homeassistant/components/switch/rpi_gpio.py @@ -1,11 +1,12 @@ """ homeassistant.components.switch.rpi_gpio ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Allows to control the GPIO pins of a Raspberry Pi. +Allows to configure a switch using RPi GPIO. For more details about this platform, please refer to the documentation at https://home-assistant.io/components/switch.rpi_gpio/ """ + import logging import homeassistant.components.rpi_gpio as rpi_gpio from homeassistant.helpers.entity import ToggleEntity @@ -19,7 +20,7 @@ _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. """ + """ Sets up the Raspberry PI GPIO devices. """ invert_logic = config.get('invert_logic', DEFAULT_INVERT_LOGIC) @@ -31,8 +32,7 @@ def setup_platform(hass, config, add_devices, discovery_info=None): class RPiGPIOSwitch(ToggleEntity): - """ Represents a port that can be toggled using Raspberry Pi GPIO. """ - + """ Represents a switch that can be toggled using Raspberry Pi GPIO. """ def __init__(self, name, port, invert_logic): self._name = name or DEVICE_DEFAULT_NAME self._port = port @@ -42,7 +42,7 @@ class RPiGPIOSwitch(ToggleEntity): @property def name(self): - """ The name of the port. """ + """ The name of the switch. """ return self._name @property From 127488004c3698e2ec280bac7f4c87d55f331c99 Mon Sep 17 00:00:00 2001 From: sfam Date: Fri, 15 Jan 2016 17:16:02 +0000 Subject: [PATCH 10/23] update coveragerc and requirements_all --- .coveragerc | 6 +++--- requirements_all.txt | 23 +++++------------------ 2 files changed, 8 insertions(+), 21 deletions(-) diff --git a/.coveragerc b/.coveragerc index 8f83575342c..adb3c59765e 100644 --- a/.coveragerc +++ b/.coveragerc @@ -41,9 +41,11 @@ omit = homeassistant/components/mysensors.py homeassistant/components/*/mysensors.py + homeassistant/components/rpi_gpio.py + homeassistant/components/*/rpi_gpio.py + homeassistant/components/binary_sensor/arest.py homeassistant/components/binary_sensor/rest.py - homeassistant/components/binary_sensor/rpi_gpio.py homeassistant/components/browser.py homeassistant/components/camera/* homeassistant/components/device_tracker/actiontec.py @@ -102,7 +104,6 @@ omit = homeassistant/components/sensor/netatmo.py homeassistant/components/sensor/openweathermap.py homeassistant/components/sensor/rest.py - homeassistant/components/sensor/rpi_gpio.py homeassistant/components/sensor/sabnzbd.py homeassistant/components/sensor/swiss_public_transport.py homeassistant/components/sensor/systemmonitor.py @@ -118,7 +119,6 @@ omit = homeassistant/components/switch/mystrom.py homeassistant/components/switch/orvibo.py homeassistant/components/switch/rest.py - homeassistant/components/switch/rpi_gpio.py homeassistant/components/switch/transmission.py homeassistant/components/switch/wemo.py homeassistant/components/thermostat/heatmiser.py diff --git a/requirements_all.txt b/requirements_all.txt index a11e42e5b60..f320408f138 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -6,9 +6,6 @@ pip>=7.0.0 vincenty==0.1.3 jinja2>=2.8 -# homeassistant.components.alarm_control_panel.alarmdotcom -https://github.com/Xorso/pyalarmdotcom/archive/0.0.7.zip#pyalarmdotcom==0.0.7 - # homeassistant.components.arduino PyMata==2.07a @@ -62,14 +59,14 @@ tellcore-py==1.1.2 # homeassistant.components.light.vera # homeassistant.components.sensor.vera # homeassistant.components.switch.vera -pyvera==0.2.5 +pyvera==0.2.3 # homeassistant.components.wink # homeassistant.components.light.wink # homeassistant.components.lock.wink # homeassistant.components.sensor.wink # homeassistant.components.switch.wink -python-wink==0.4.1 +python-wink==0.3.1 # homeassistant.components.media_player.cast pychromecast==0.6.14 @@ -92,12 +89,6 @@ https://github.com/bashwork/pymodbus/archive/d7fc4f1cc975631e0a9011390e8017f64b6 # homeassistant.components.mqtt paho-mqtt==1.1 -# homeassistant.components.mysensors -https://github.com/theolind/pymysensors/archive/005bff4c5ca7a56acd30e816bc3bcdb5cb2d46fd.zip#pymysensors==0.4 - -# homeassistant.components.notify.free_mobile -freesms==0.1.0 - # homeassistant.components.notify.pushbullet pushbullet.py==0.9.0 @@ -140,16 +131,15 @@ eliqonline==1.0.11 # homeassistant.components.sensor.forecast python-forecastio==1.3.3 -# homeassistant.components.sensor.netatmo -https://github.com/HydrelioxGitHub/netatmo-api-python/archive/43ff238a0122b0939a0dc4e8836b6782913fb6e2.zip#lnetatmo==0.4.0 +# homeassistant.components.sensor.mysensors +https://github.com/theolind/pymysensors/archive/d4b809c2167650691058d1e29bfd2c4b1792b4b0.zip#pymysensors==0.3 # homeassistant.components.sensor.openweathermap pyowm==2.3.0 -# homeassistant.components.binary_sensor.rpi_gpio # homeassistant.components.sensor.rpi_gpio # homeassistant.components.switch.rpi_gpio -# RPi.GPIO==0.6.1 +# RPi.GPIO==0.5.11 # homeassistant.components.sensor.sabnzbd https://github.com/jamespcole/home-assistant-nzb-clients/archive/616cad59154092599278661af17e2a9f2cf5e2a9.zip#python-sabnzbd==0.1 @@ -197,9 +187,6 @@ evohomeclient==0.2.4 # homeassistant.components.thermostat.nest python-nest==2.6.0 -# homeassistant.components.thermostat.proliphix -proliphix==0.1.0 - # homeassistant.components.thermostat.radiotherm radiotherm==1.2 From 702dddbb2fa476cec7d8d6d42a90562ae23dc943 Mon Sep 17 00:00:00 2001 From: sfam Date: Fri, 15 Jan 2016 17:28:32 +0000 Subject: [PATCH 11/23] update requirements_all --- requirements_all.txt | 27 +++++++++++++++++++-------- 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/requirements_all.txt b/requirements_all.txt index f320408f138..268ead4d814 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -6,6 +6,9 @@ pip>=7.0.0 vincenty==0.1.3 jinja2>=2.8 +# homeassistant.components.alarm_control_panel.alarmdotcom +https://github.com/Xorso/pyalarmdotcom/archive/0.0.7.zip#pyalarmdotcom==0.0.7 + # homeassistant.components.arduino PyMata==2.07a @@ -59,14 +62,14 @@ tellcore-py==1.1.2 # homeassistant.components.light.vera # homeassistant.components.sensor.vera # homeassistant.components.switch.vera -pyvera==0.2.3 +pyvera==0.2.5 # homeassistant.components.wink # homeassistant.components.light.wink # homeassistant.components.lock.wink # homeassistant.components.sensor.wink # homeassistant.components.switch.wink -python-wink==0.3.1 +python-wink==0.4.1 # homeassistant.components.media_player.cast pychromecast==0.6.14 @@ -89,6 +92,12 @@ https://github.com/bashwork/pymodbus/archive/d7fc4f1cc975631e0a9011390e8017f64b6 # homeassistant.components.mqtt paho-mqtt==1.1 +# homeassistant.components.mysensors +https://github.com/theolind/pymysensors/archive/005bff4c5ca7a56acd30e816bc3bcdb5cb2d46fd.zip#pymysensors==0.4 + +# homeassistant.components.notify.free_mobile +freesms==0.1.0 + # homeassistant.components.notify.pushbullet pushbullet.py==0.9.0 @@ -113,6 +122,9 @@ dnspython3==1.12.0 # homeassistant.components.rfxtrx https://github.com/Danielhiversen/pyRFXtrx/archive/0.2.zip#RFXtrx==0.2 +# homeassistant.components.rpi_gpio +# RPi.GPIO==0.6.1 + # homeassistant.components.sensor.bitcoin blockchain==1.1.2 @@ -131,16 +143,12 @@ eliqonline==1.0.11 # homeassistant.components.sensor.forecast python-forecastio==1.3.3 -# homeassistant.components.sensor.mysensors -https://github.com/theolind/pymysensors/archive/d4b809c2167650691058d1e29bfd2c4b1792b4b0.zip#pymysensors==0.3 +# homeassistant.components.sensor.netatmo +https://github.com/HydrelioxGitHub/netatmo-api-python/archive/43ff238a0122b0939a0dc4e8836b6782913fb6e2.zip#lnetatmo==0.4.0 # homeassistant.components.sensor.openweathermap pyowm==2.3.0 -# homeassistant.components.sensor.rpi_gpio -# homeassistant.components.switch.rpi_gpio -# RPi.GPIO==0.5.11 - # homeassistant.components.sensor.sabnzbd https://github.com/jamespcole/home-assistant-nzb-clients/archive/616cad59154092599278661af17e2a9f2cf5e2a9.zip#python-sabnzbd==0.1 @@ -187,6 +195,9 @@ evohomeclient==0.2.4 # homeassistant.components.thermostat.nest python-nest==2.6.0 +# homeassistant.components.thermostat.proliphix +proliphix==0.1.0 + # homeassistant.components.thermostat.radiotherm radiotherm==1.2 From d8d59d9a663bdd5b010de363d2b9823284ba82bb Mon Sep 17 00:00:00 2001 From: sfam Date: Fri, 15 Jan 2016 18:05:48 +0000 Subject: [PATCH 12/23] remove rpi_gpio sensor --- .../components/binary_sensor/rpi_gpio.py | 8 +-- homeassistant/components/rpi_gpio.py | 2 +- homeassistant/components/sensor/rpi_gpio.py | 56 ------------------- 3 files changed, 5 insertions(+), 61 deletions(-) delete mode 100644 homeassistant/components/sensor/rpi_gpio.py diff --git a/homeassistant/components/binary_sensor/rpi_gpio.py b/homeassistant/components/binary_sensor/rpi_gpio.py index 972c319d958..39a7edecb79 100644 --- a/homeassistant/components/binary_sensor/rpi_gpio.py +++ b/homeassistant/components/binary_sensor/rpi_gpio.py @@ -10,7 +10,7 @@ https://home-assistant.io/components/binary_sensor.rpi_gpio/ import logging import homeassistant.components.rpi_gpio as rpi_gpio from homeassistant.helpers.entity import Entity -from homeassistant.const import (STATE_ON, STATE_OFF, DEVICE_DEFAULT_NAME) +from homeassistant.const import (DEVICE_DEFAULT_NAME) DEFAULT_PULL_MODE = "UP" DEFAULT_BOUNCETIME = 50 @@ -37,7 +37,7 @@ def setup_platform(hass, config, add_devices, discovery_info=None): # pylint: disable=too-many-arguments, too-many-instance-attributes -class RPiGPIOBinarySensor(Entity): +class RPiGPIOBinarySensor(BinarySensorDevice): """ Represents a binary sensor that uses Raspberry Pi GPIO. """ def __init__(self, name, port, pull_mode, bouncetime, invert_logic): # pylint: disable=no-member @@ -68,6 +68,6 @@ class RPiGPIOBinarySensor(Entity): return self._name @property - def state(self): + def is_on(self): """ Returns the state of the entity. """ - return STATE_ON if self._state != self._invert_logic else STATE_OFF + return self._state != self._invert_logic diff --git a/homeassistant/components/rpi_gpio.py b/homeassistant/components/rpi_gpio.py index 86800a36dbe..3d0a068f8ca 100644 --- a/homeassistant/components/rpi_gpio.py +++ b/homeassistant/components/rpi_gpio.py @@ -1,5 +1,5 @@ """ -homeassistant.components.switch.rpi_gpio +homeassistant.components.rpi_gpio ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Allows to control the GPIO pins of a Raspberry Pi. diff --git a/homeassistant/components/sensor/rpi_gpio.py b/homeassistant/components/sensor/rpi_gpio.py deleted file mode 100644 index d07375f9e31..00000000000 --- a/homeassistant/components/sensor/rpi_gpio.py +++ /dev/null @@ -1,56 +0,0 @@ -""" -homeassistant.components.sensor.rpi_gpio -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Allows to configure a sensor using RPi GPIO. - -For more details about this platform, please refer to the documentation at -https://home-assistant.io/components/sensor.rpi_gpio/ -""" - -import logging -from homeassistant.components.binary_sensor.rpi_gpio import RPiGPIOBinarySensor - -DEFAULT_PULL_MODE = "UP" -DEFAULT_BOUNCETIME = 50 -DEFAULT_VALUE_HIGH = "HIGH" -DEFAULT_VALUE_LOW = "LOW" - -DEPENDENCIES = ['rpi_gpio'] -_LOGGER = logging.getLogger(__name__) - - -# pylint: disable=unused-argument -def setup_platform(hass, config, add_devices, discovery_info=None): - """ Sets up the Raspberry PI GPIO devices. """ - - pull_mode = config.get('pull_mode', DEFAULT_PULL_MODE) - bouncetime = config.get('bouncetime', DEFAULT_BOUNCETIME) - value_high = config.get('value_high', DEFAULT_VALUE_HIGH) - value_low = config.get('value_low', DEFAULT_VALUE_LOW) - - sensors = [] - ports = config.get('ports') - for port, name in ports.items(): - sensors.append(RPiGPIOSensor( - name, port, pull_mode, bouncetime, - value_high, value_low)) - add_devices(sensors) - - -# pylint: disable=too-many-arguments, too-many-instance-attributes -class RPiGPIOSensor(RPiGPIOBinarySensor): - """ Represents a sensor that uses Raspberry Pi GPIO. """ - def __init__(self, name, port, pull_mode, bouncetime, - value_high, value_low): - - self._value_high = value_high - self._value_low = value_low - super().__init__(name, port, pull_mode, bouncetime, False) - - @property - def state(self): - """ Returns the state of the entity. """ - if self._state != self._invert_logic: - return self._value_high - else: - return self._value_low From 48b6c5b5cb237d27ca1f1a192ab45d9fe9933c47 Mon Sep 17 00:00:00 2001 From: sfam Date: Fri, 15 Jan 2016 18:14:46 +0000 Subject: [PATCH 13/23] fix import BinarySensorDevice --- homeassistant/components/binary_sensor/rpi_gpio.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/homeassistant/components/binary_sensor/rpi_gpio.py b/homeassistant/components/binary_sensor/rpi_gpio.py index 39a7edecb79..2bb50fec766 100644 --- a/homeassistant/components/binary_sensor/rpi_gpio.py +++ b/homeassistant/components/binary_sensor/rpi_gpio.py @@ -9,7 +9,7 @@ https://home-assistant.io/components/binary_sensor.rpi_gpio/ import logging import homeassistant.components.rpi_gpio as rpi_gpio -from homeassistant.helpers.entity import Entity +from homeassistant.components.binary_sensor import BinarySensorDevice from homeassistant.const import (DEVICE_DEFAULT_NAME) DEFAULT_PULL_MODE = "UP" From f96c5aa62f91ba6301e45adbeec55db4fde1870d Mon Sep 17 00:00:00 2001 From: Philip Lundrigan Date: Fri, 15 Jan 2016 13:07:26 -0700 Subject: [PATCH 14/23] Fix bug in locative logic --- .../components/device_tracker/locative.py | 5 ++--- .../components/device_tracker/test_locative.py | 18 ++++++++++++++++++ 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/device_tracker/locative.py b/homeassistant/components/device_tracker/locative.py index e7532d1075d..11884829600 100644 --- a/homeassistant/components/device_tracker/locative.py +++ b/homeassistant/components/device_tracker/locative.py @@ -49,10 +49,9 @@ def _handle_get_api_locative(hass, see, handler, path_match, data): handler.write_text("Setting location to {}".format(location_name)) elif direction == 'exit': - current_state = hass.states.get( - "{}.{}".format(DOMAIN, device)).state + current_state = hass.states.get("{}.{}".format(DOMAIN, device)) - if current_state == location_name: + if current_state is None or current_state.state == location_name: see(dev_id=device, location_name=STATE_NOT_HOME) handler.write_text("Setting location to not home") else: diff --git a/tests/components/device_tracker/test_locative.py b/tests/components/device_tracker/test_locative.py index 619fe929ac7..cd02380d324 100644 --- a/tests/components/device_tracker/test_locative.py +++ b/tests/components/device_tracker/test_locative.py @@ -203,3 +203,21 @@ class TestLocative(unittest.TestCase): state = hass.states.get('{}.{}'.format('device_tracker', data['device'])) self.assertEqual(state.state, 'work') + + def test_exit_first(self, update_config): + """ Test when an exit message is sent first on a new device """ + + data = { + 'latitude': 40.7855, + 'longitude': -111.7367, + 'device': 'new_device', + 'id': 'Home', + 'trigger': 'exit' + } + + # Exit Home + req = requests.get(_url(data)) + self.assertEqual(200, req.status_code) + + state = hass.states.get('{}.{}'.format('device_tracker', data['device'])) + self.assertEqual(state.state, 'not_home') From fdbb40933131b1e8310024d71767cb6cae64ce86 Mon Sep 17 00:00:00 2001 From: Philip Lundrigan Date: Fri, 15 Jan 2016 13:39:54 -0700 Subject: [PATCH 15/23] Increase security of using SSL --- homeassistant/components/http.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/homeassistant/components/http.py b/homeassistant/components/http.py index 35c215a8630..073604e3b2c 100644 --- a/homeassistant/components/http.py +++ b/homeassistant/components/http.py @@ -112,10 +112,10 @@ class HomeAssistantHTTPServer(ThreadingMixIn, HTTPServer): _LOGGER.info("running http in development mode") if ssl_certificate is not None: - wrap_kwargs = {'certfile': ssl_certificate} - if ssl_key is not None: - wrap_kwargs['keyfile'] = ssl_key - self.socket = ssl.wrap_socket(self.socket, **wrap_kwargs) + context = ssl.create_default_context( + purpose=ssl.Purpose.CLIENT_AUTH) + context.load_cert_chain(ssl_certificate, keyfile=ssl_key) + self.socket = context.wrap_socket(self.socket, server_side=True) def start(self): """ Starts the HTTP server. """ From 541b2687214c76a4e9269bb1c94840da2dac4398 Mon Sep 17 00:00:00 2001 From: pavoni Date: Fri, 15 Jan 2016 21:30:58 +0000 Subject: [PATCH 16/23] Update to use refactored pyvera, fixes subscription issues - esp sensors. --- homeassistant/components/light/vera.py | 4 ++-- homeassistant/components/sensor/vera.py | 19 ++++++++++--------- homeassistant/components/switch/vera.py | 23 +++++++++++++---------- requirements_all.txt | 2 +- 4 files changed, 26 insertions(+), 22 deletions(-) diff --git a/homeassistant/components/light/vera.py b/homeassistant/components/light/vera.py index 5b2e74f3ac8..99f32afbc08 100644 --- a/homeassistant/components/light/vera.py +++ b/homeassistant/components/light/vera.py @@ -15,7 +15,7 @@ from homeassistant.components.light import ATTR_BRIGHTNESS from homeassistant.const import EVENT_HOMEASSISTANT_STOP, STATE_ON -REQUIREMENTS = ['pyvera==0.2.5'] +REQUIREMENTS = ['pyvera==0.2.6'] _LOGGER = logging.getLogger(__name__) @@ -86,4 +86,4 @@ class VeraLight(VeraSwitch): self.vera_device.switch_on() self._state = STATE_ON - self.update_ha_state() + self.update_ha_state(True) diff --git a/homeassistant/components/sensor/vera.py b/homeassistant/components/sensor/vera.py index 9bf1c071450..f8a6ddf24ff 100644 --- a/homeassistant/components/sensor/vera.py +++ b/homeassistant/components/sensor/vera.py @@ -15,7 +15,7 @@ from homeassistant.const import ( ATTR_BATTERY_LEVEL, ATTR_TRIPPED, ATTR_ARMED, ATTR_LAST_TRIP_TIME, TEMP_CELCIUS, TEMP_FAHRENHEIT, EVENT_HOMEASSISTANT_STOP) -REQUIREMENTS = ['pyvera==0.2.5'] +REQUIREMENTS = ['pyvera==0.2.6'] _LOGGER = logging.getLogger(__name__) @@ -89,6 +89,7 @@ class VeraSensor(Entity): self._temperature_units = None self.controller.register(vera_device, self._update_callback) + self.update() def _update_callback(self, _device): """ Called by the vera device callback to update state. """ @@ -123,18 +124,18 @@ class VeraSensor(Entity): attr[ATTR_BATTERY_LEVEL] = self.vera_device.battery_level + '%' if self.vera_device.is_armable: - armed = self.vera_device.get_value('Armed') + armed = self.vera_device.is_armed attr[ATTR_ARMED] = 'True' if armed == '1' else 'False' if self.vera_device.is_trippable: - last_tripped = self.vera_device.get_value('LastTrip') + last_tripped = self.vera_device.last_trip if last_tripped is not None: utc_time = dt_util.utc_from_timestamp(int(last_tripped)) attr[ATTR_LAST_TRIP_TIME] = dt_util.datetime_to_str( utc_time) else: attr[ATTR_LAST_TRIP_TIME] = None - tripped = self.vera_device.get_value('Tripped') + tripped = self.vera_device.is_tripped attr[ATTR_TRIPPED] = 'True' if tripped == '1' else 'False' attr['Vera Device Id'] = self.vera_device.vera_device_id @@ -147,7 +148,7 @@ class VeraSensor(Entity): def update(self): if self.vera_device.category == "Temperature Sensor": - current_temp = self.vera_device.get_value('CurrentTemperature') + current_temp = self.vera_device.temperature vera_temp_units = ( self.vera_device.vera_controller.temperature_units) @@ -165,11 +166,11 @@ class VeraSensor(Entity): self.current_value = current_temp elif self.vera_device.category == "Light Sensor": - self.current_value = self.vera_device.get_value('CurrentLevel') + self.current_value = self.vera_device.light elif self.vera_device.category == "Humidity Sensor": - self.current_value = self.vera_device.get_value('CurrentLevel') + self.current_value = self.vera_device.humidity elif self.vera_device.category == "Sensor": - tripped = self.vera_device.get_value('Tripped') - self.current_value = 'Tripped' if tripped == '1' else 'Not Tripped' + tripped = self.vera_device.is_tripped + self.current_value = 'Tripped' if tripped else 'Not Tripped' else: self.current_value = 'Unknown' diff --git a/homeassistant/components/switch/vera.py b/homeassistant/components/switch/vera.py index ec7f7395e26..6835521b907 100644 --- a/homeassistant/components/switch/vera.py +++ b/homeassistant/components/switch/vera.py @@ -21,7 +21,7 @@ from homeassistant.const import ( STATE_ON, STATE_OFF) -REQUIREMENTS = ['pyvera==0.2.5'] +REQUIREMENTS = ['pyvera==0.2.6'] _LOGGER = logging.getLogger(__name__) @@ -91,14 +91,10 @@ class VeraSwitch(SwitchDevice): self._state = STATE_OFF self.controller.register(vera_device, self._update_callback) + self.update() def _update_callback(self, _device): - """ Called by the vera device callback to update state. """ - if self.vera_device.is_switched_on(): - self._state = STATE_ON - else: - self._state = STATE_OFF - self.update_ha_state() + self.update_ha_state(True) @property def name(self): @@ -113,18 +109,18 @@ class VeraSwitch(SwitchDevice): attr[ATTR_BATTERY_LEVEL] = self.vera_device.battery_level + '%' if self.vera_device.is_armable: - armed = self.vera_device.get_value('Armed') + armed = self.vera_device.is_armed attr[ATTR_ARMED] = 'True' if armed == '1' else 'False' if self.vera_device.is_trippable: - last_tripped = self.vera_device.get_value('LastTrip') + last_tripped = self.vera_device.last_trip if last_tripped is not None: utc_time = dt_util.utc_from_timestamp(int(last_tripped)) attr[ATTR_LAST_TRIP_TIME] = dt_util.datetime_to_str( utc_time) else: attr[ATTR_LAST_TRIP_TIME] = None - tripped = self.vera_device.get_value('Tripped') + tripped = self.vera_device.is_tripped attr[ATTR_TRIPPED] = 'True' if tripped == '1' else 'False' attr['Vera Device Id'] = self.vera_device.vera_device_id @@ -150,3 +146,10 @@ class VeraSwitch(SwitchDevice): def is_on(self): """ True if device is on. """ return self._state == STATE_ON + + def update(self): + """ Called by the vera device callback to update state. """ + if self.vera_device.is_switched_on(): + self._state = STATE_ON + else: + self._state = STATE_OFF diff --git a/requirements_all.txt b/requirements_all.txt index 4d38ada0daf..1ff898de31e 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -62,7 +62,7 @@ tellcore-py==1.1.2 # homeassistant.components.light.vera # homeassistant.components.sensor.vera # homeassistant.components.switch.vera -pyvera==0.2.5 +pyvera==0.2.6 # homeassistant.components.wink # homeassistant.components.light.wink From c2f5eb3073e6b293d08cdc952434be4d34bd20d3 Mon Sep 17 00:00:00 2001 From: pavoni Date: Fri, 15 Jan 2016 21:42:51 +0000 Subject: [PATCH 17/23] Missed change. --- homeassistant/components/sensor/vera.py | 4 ++-- homeassistant/components/switch/vera.py | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/homeassistant/components/sensor/vera.py b/homeassistant/components/sensor/vera.py index f8a6ddf24ff..c77d462502a 100644 --- a/homeassistant/components/sensor/vera.py +++ b/homeassistant/components/sensor/vera.py @@ -125,7 +125,7 @@ class VeraSensor(Entity): if self.vera_device.is_armable: armed = self.vera_device.is_armed - attr[ATTR_ARMED] = 'True' if armed == '1' else 'False' + attr[ATTR_ARMED] = 'True' if armed else 'False' if self.vera_device.is_trippable: last_tripped = self.vera_device.last_trip @@ -136,7 +136,7 @@ class VeraSensor(Entity): else: attr[ATTR_LAST_TRIP_TIME] = None tripped = self.vera_device.is_tripped - attr[ATTR_TRIPPED] = 'True' if tripped == '1' else 'False' + attr[ATTR_TRIPPED] = 'True' if tripped else 'False' attr['Vera Device Id'] = self.vera_device.vera_device_id return attr diff --git a/homeassistant/components/switch/vera.py b/homeassistant/components/switch/vera.py index 6835521b907..a5c93224a69 100644 --- a/homeassistant/components/switch/vera.py +++ b/homeassistant/components/switch/vera.py @@ -110,7 +110,7 @@ class VeraSwitch(SwitchDevice): if self.vera_device.is_armable: armed = self.vera_device.is_armed - attr[ATTR_ARMED] = 'True' if armed == '1' else 'False' + attr[ATTR_ARMED] = 'True' if armed else 'False' if self.vera_device.is_trippable: last_tripped = self.vera_device.last_trip @@ -121,7 +121,7 @@ class VeraSwitch(SwitchDevice): else: attr[ATTR_LAST_TRIP_TIME] = None tripped = self.vera_device.is_tripped - attr[ATTR_TRIPPED] = 'True' if tripped == '1' else 'False' + attr[ATTR_TRIPPED] = 'True' if tripped else 'False' attr['Vera Device Id'] = self.vera_device.vera_device_id From edb24add6ba3100a1727b035e53beb5211ba7641 Mon Sep 17 00:00:00 2001 From: Daren Lord Date: Fri, 15 Jan 2016 22:15:31 -0700 Subject: [PATCH 18/23] Fixed but when alarm is trying to change state the state gets updated and changes the page. --- .../alarm_control_panel/alarmdotcom.py | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/homeassistant/components/alarm_control_panel/alarmdotcom.py b/homeassistant/components/alarm_control_panel/alarmdotcom.py index d10afc429e6..f53f7bc3227 100644 --- a/homeassistant/components/alarm_control_panel/alarmdotcom.py +++ b/homeassistant/components/alarm_control_panel/alarmdotcom.py @@ -51,6 +51,8 @@ class AlarmDotCom(alarm.AlarmControlPanel): self._hass = hass self._name = name self._code = str(code) if code else None + self._username = username + self._password = password @property def should_poll(self): @@ -79,19 +81,28 @@ class AlarmDotCom(alarm.AlarmControlPanel): def alarm_disarm(self, code=None): if not self._validate_code(code, 'arming home'): return - self._alarm.disarm() + from pyalarmdotcom.pyalarmdotcom import Alarmdotcom + # Open another session to alarm.com to fire off the command + _alarm = Alarmdotcom(self._username, self._password, timeout=10) + _alarm.disarm() self.update_ha_state() def alarm_arm_home(self, code=None): if not self._validate_code(code, 'arming home'): return - self._alarm.arm_stay() + from pyalarmdotcom.pyalarmdotcom import Alarmdotcom + # Open another session to alarm.com to fire off the command + _alarm = Alarmdotcom(self._username, self._password, timeout=10) + _alarm.arm_stay() self.update_ha_state() def alarm_arm_away(self, code=None): if not self._validate_code(code, 'arming home'): return - self._alarm.arm_away() + from pyalarmdotcom.pyalarmdotcom import Alarmdotcom + # Open another session to alarm.com to fire off the command + _alarm = Alarmdotcom(self._username, self._password, timeout=10) + _alarm.arm_away() self.update_ha_state() def _validate_code(self, code, state): From be23c6c86d239a00e5ea5cae3d960d3aae6844c2 Mon Sep 17 00:00:00 2001 From: pavoni Date: Sat, 16 Jan 2016 11:35:17 +0000 Subject: [PATCH 19/23] Bump pywemo version. --- homeassistant/components/light/vera.py | 2 +- homeassistant/components/sensor/vera.py | 2 +- homeassistant/components/switch/vera.py | 2 +- requirements_all.txt | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/homeassistant/components/light/vera.py b/homeassistant/components/light/vera.py index 99f32afbc08..46b4e7c7da8 100644 --- a/homeassistant/components/light/vera.py +++ b/homeassistant/components/light/vera.py @@ -15,7 +15,7 @@ from homeassistant.components.light import ATTR_BRIGHTNESS from homeassistant.const import EVENT_HOMEASSISTANT_STOP, STATE_ON -REQUIREMENTS = ['pyvera==0.2.6'] +REQUIREMENTS = ['pyvera==0.2.7'] _LOGGER = logging.getLogger(__name__) diff --git a/homeassistant/components/sensor/vera.py b/homeassistant/components/sensor/vera.py index c77d462502a..c587764ae2e 100644 --- a/homeassistant/components/sensor/vera.py +++ b/homeassistant/components/sensor/vera.py @@ -15,7 +15,7 @@ from homeassistant.const import ( ATTR_BATTERY_LEVEL, ATTR_TRIPPED, ATTR_ARMED, ATTR_LAST_TRIP_TIME, TEMP_CELCIUS, TEMP_FAHRENHEIT, EVENT_HOMEASSISTANT_STOP) -REQUIREMENTS = ['pyvera==0.2.6'] +REQUIREMENTS = ['pyvera==0.2.7'] _LOGGER = logging.getLogger(__name__) diff --git a/homeassistant/components/switch/vera.py b/homeassistant/components/switch/vera.py index a5c93224a69..3626175c03c 100644 --- a/homeassistant/components/switch/vera.py +++ b/homeassistant/components/switch/vera.py @@ -21,7 +21,7 @@ from homeassistant.const import ( STATE_ON, STATE_OFF) -REQUIREMENTS = ['pyvera==0.2.6'] +REQUIREMENTS = ['pyvera==0.2.7'] _LOGGER = logging.getLogger(__name__) diff --git a/requirements_all.txt b/requirements_all.txt index 6b886b2e368..205dca38209 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -62,7 +62,7 @@ tellcore-py==1.1.2 # homeassistant.components.light.vera # homeassistant.components.sensor.vera # homeassistant.components.switch.vera -pyvera==0.2.6 +pyvera==0.2.7 # homeassistant.components.wink # homeassistant.components.light.wink From 78742c016b666f07b3b2cfe0c1cd4a5e301e3181 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Per=20Sandstr=C3=B6m?= Date: Sat, 16 Jan 2016 15:12:54 +0100 Subject: [PATCH 20/23] code digits settings --- homeassistant/components/alarm_control_panel/verisure.py | 2 +- homeassistant/components/verisure.py | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/homeassistant/components/alarm_control_panel/verisure.py b/homeassistant/components/alarm_control_panel/verisure.py index ea48209a0fd..ecedd163d0b 100644 --- a/homeassistant/components/alarm_control_panel/verisure.py +++ b/homeassistant/components/alarm_control_panel/verisure.py @@ -57,7 +57,7 @@ class VerisureAlarm(alarm.AlarmControlPanel): @property def code_format(self): """ Four digit code required. """ - return '^\\d{4}$' + return '^\\d{%s}$' % verisure.CODE_DIGITS def update(self): """ Update alarm status """ diff --git a/homeassistant/components/verisure.py b/homeassistant/components/verisure.py index 164835f07c7..2fdfb6eb8be 100644 --- a/homeassistant/components/verisure.py +++ b/homeassistant/components/verisure.py @@ -44,6 +44,7 @@ SHOW_THERMOMETERS = True SHOW_HYGROMETERS = True SHOW_ALARM = True SHOW_SMARTPLUGS = True +CODE_DIGITS = 4 # if wrong password was given don't try again WRONG_PASSWORD_GIVEN = False @@ -61,11 +62,13 @@ def setup(hass, config): from verisure import MyPages, LoginError, Error - global SHOW_THERMOMETERS, SHOW_HYGROMETERS, SHOW_ALARM, SHOW_SMARTPLUGS + global SHOW_THERMOMETERS, SHOW_HYGROMETERS,\ + SHOW_ALARM, SHOW_SMARTPLUGS, CODE_DIGITS SHOW_THERMOMETERS = int(config[DOMAIN].get('thermometers', '1')) SHOW_HYGROMETERS = int(config[DOMAIN].get('hygrometers', '1')) SHOW_ALARM = int(config[DOMAIN].get('alarm', '1')) SHOW_SMARTPLUGS = int(config[DOMAIN].get('smartplugs', '1')) + CODE_DIGITS = int(config[DOMAIN].get('code_digits', '4')) global MY_PAGES MY_PAGES = MyPages( From 4bf185c86889474d6a0b04804d4b3a868c859777 Mon Sep 17 00:00:00 2001 From: Ryan Kraus Date: Sat, 16 Jan 2016 10:17:26 -0500 Subject: [PATCH 21/23] Added nginx sample configuration Added a sample nginx configuration with instructions detailing how to setup a very secure HTTPS server for HA that servers over standard ports without requiring HA to run as root. --- script/nginx-hass | 113 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 113 insertions(+) create mode 100644 script/nginx-hass diff --git a/script/nginx-hass b/script/nginx-hass new file mode 100644 index 00000000000..9fc1725f043 --- /dev/null +++ b/script/nginx-hass @@ -0,0 +1,113 @@ +## +# +# Home Assistant - nginx Configuration File +# +# Using nginx as a proxy for Home Assistant allows you to serve Home Assisatnt +# securely over standard ports. This configuration file and instructions will +# walk you through setting up Home Assistant over a secure connection. +# +# 1) Get a domain name forwarded to your IP. +# Chances are, you have a dynamic IP Address (your ISP changes your address +# periodically). If this is true, you can use a Dynamic DNS service to obtain +# a domain and set it up to update with you IP. If you purchase your own +# domain name, you will be able to easily get a trusted SSL certificate +# later. +# +# +# 2) Install nginx on your server. +# This will vary depending on your OS. Check out Google for this. After +# installing, ensure that nginx is not running. +# +# +# 3) Obtain an SSL certificate. +# +# 3a) Using Let's Encrypt +# If you purchased your own domain, you can use https://letsencrypt.org/ to +# obtain a free, publicly trusted SSL certificate. This will allow you to +# work with services like IFTTT. Download and install per the instructions +# online and get a certificate using the following command. +# +# ./letsencrypt-auto certonly --standalone -d example.com -d www.example.com +# +# Instead of example.com, use your domain. You will need to renew this +# certificate every 90 days. +# +# 3b) Using openssl +# If you do not own your own domain, you may generate a self-signed +# certificate. This will not work with IFTTT, but it will encrypt all of your +# Home Assistant traffic. +# +# openssl req -x509 -newkey rsa:2048 -keyout key.pem -out cert.pem -days 9999 +# sudo cp key.pem cert.pem /etc/nginx/ssl +# sudo chmod 600 /etc/nginx/ssl/key.pem /etc/nginx/ssl/cert.pem +# sudo chown root:root /etc/nginx/ssl/key.pem /etc/nginx/ssl/cert.pem +# +# +# 4) Create dhparams file +# As a fair warning, this file will take a while to generate. +# +# cd /etc/nginx/ssl +# sudo openssl dhparam -out dhparams.pem 2048 +# +# +# 5) Install this configuration file in nginx. +# +# cp nginx-hass /etc/nginx/sites-available/hass +# cd /etc/nginx/sites-enabled +# sudo unlink default +# sudo ln ../sites-available/hass default +# +# +# 6) Double check this configuration to ensure all settings are correct and +# start nginx. +# +# +# 7) Forward ports 443 and 80 to your server on your router. Do not forward +# port 8123. +# +## + +server { + # Update this line to be your domain + server_name example.com; + + + # These shouldn't need to be changed + listen 80 default_server; + listen [::]:80 default_server ipv6only=on; + return 301 https://$host$request_uri; +} + + +server { + # Update this line to be your domain + server_name example.com; + + # Ensure these lines point to your SSL certificate and key + ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem; + # Use these lines instead if you created a self-signed certificate + # ssl_certificate /etc/nginx/ssl/cert.pem; + # ssl_certificate_key /etc/nginx/ssl/key.pem; + + # Ensure this line points to your dhparams file + ssl_dhparam /etc/nginx/ssl/dhparams.pem; + + + # These shouldn't need to be changed + listen 443 default_server; + add_header Strict-Transport-Security "max-age=31536000; includeSubdomains"; + ssl on; + ssl_protocols TLSv1 TLSv1.1 TLSv1.2; + ssl_ciphers "EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH:!aNULL:!eNULL:!EXPORT:!DES:!MD5:!PSK:!RC4"; + ssl_prefer_server_ciphers on; + ssl_session_cache shared:SSL:10m; + + proxy_buffering off; + + location / { + proxy_pass http://localhost:8123; + proxy_set_header Host $host; + proxy_redirect http:// https://; + } +} From c5b69a0ee415070d6cd3fb8c5ca93e0aa303aba6 Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Sat, 16 Jan 2016 11:20:02 -0800 Subject: [PATCH 22/23] Update version to 0.11 --- homeassistant/const.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/homeassistant/const.py b/homeassistant/const.py index 97e26f8d33a..7a0d0dff9be 100644 --- a/homeassistant/const.py +++ b/homeassistant/const.py @@ -1,7 +1,7 @@ # coding: utf-8 """ Constants used by Home Assistant components. """ -__version__ = "0.11.0.dev0" +__version__ = "0.11.0" # Can be used to specify a catch all when registering state or event listeners. MATCH_ALL = '*' From 9f61369156c6bef4904d7f56b07f33f2e596865f Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Sat, 16 Jan 2016 11:23:55 -0800 Subject: [PATCH 23/23] Version bump to 0.12.0.dev0 --- homeassistant/const.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/homeassistant/const.py b/homeassistant/const.py index 7a0d0dff9be..cb367af362a 100644 --- a/homeassistant/const.py +++ b/homeassistant/const.py @@ -1,7 +1,7 @@ # coding: utf-8 """ Constants used by Home Assistant components. """ -__version__ = "0.11.0" +__version__ = "0.12.0.dev0" # Can be used to specify a catch all when registering state or event listeners. MATCH_ALL = '*'