Initial version input_boolean

pull/897/head
Paulus Schoutsen 2016-01-14 22:51:28 -08:00
parent 40c75f0a51
commit 475b631d9c
2 changed files with 219 additions and 0 deletions

View File

@ -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()

View File

@ -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))