Skip to content

Commit

Permalink
Merge pull request home-assistant#1594 from balloob/dev
Browse files Browse the repository at this point in the history
0.16
  • Loading branch information
balloob committed Mar 26, 2016
2 parents 6797365 + e53adf0 commit 763a9ce
Show file tree
Hide file tree
Showing 108 changed files with 4,173 additions and 2,740 deletions.
11 changes: 8 additions & 3 deletions .coveragerc
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,13 @@ omit =
homeassistant/components/modbus.py
homeassistant/components/*/modbus.py

homeassistant/components/tellstick.py
homeassistant/components/*/tellstick.py

homeassistant/components/tellduslive.py
homeassistant/components/*/tellduslive.py

homeassistant/components/vera.py
homeassistant/components/*/vera.py

homeassistant/components/ecobee.py
Expand All @@ -57,9 +59,6 @@ omit =
homeassistant/components/nest.py
homeassistant/components/*/nest.py

homeassistant/components/rfxtrx.py
homeassistant/components/*/rfxtrx.py

homeassistant/components/rpi_gpio.py
homeassistant/components/*/rpi_gpio.py

Expand Down Expand Up @@ -108,9 +107,12 @@ omit =
homeassistant/components/media_player/snapcast.py
homeassistant/components/media_player/sonos.py
homeassistant/components/media_player/squeezebox.py
homeassistant/components/media_player/yamaha.py
homeassistant/components/notify/free_mobile.py
homeassistant/components/notify/googlevoice.py
homeassistant/components/notify/gntp.py
homeassistant/components/notify/instapush.py
homeassistant/components/notify/message_bird.py
homeassistant/components/notify/nma.py
homeassistant/components/notify/pushbullet.py
homeassistant/components/notify/pushetta.py
Expand Down Expand Up @@ -149,15 +151,18 @@ omit =
homeassistant/components/sensor/torque.py
homeassistant/components/sensor/transmission.py
homeassistant/components/sensor/twitch.py
homeassistant/components/sensor/uber.py
homeassistant/components/sensor/worldclock.py
homeassistant/components/switch/arest.py
homeassistant/components/switch/dlink.py
homeassistant/components/switch/edimax.py
homeassistant/components/switch/hikvisioncam.py
homeassistant/components/switch/mystrom.py
homeassistant/components/switch/orvibo.py
homeassistant/components/switch/pulseaudio_loopback.py
homeassistant/components/switch/rest.py
homeassistant/components/switch/transmission.py
homeassistant/components/switch/wake_on_lan.py
homeassistant/components/thermostat/heatmiser.py
homeassistant/components/thermostat/homematic.py
homeassistant/components/thermostat/proliphix.py
Expand Down
11 changes: 5 additions & 6 deletions .github/PULL_REQUEST_TEMPLATE.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,15 @@

**Checklist:**

- [ ] Local tests with `tox` run successfully.
- [ ] TravisCI does not fail. **Your PR cannot be merged unless CI is green!**
- [ ] [Fork is up to date][fork] and was rebased on the `dev` branch before creating the PR.
- [ ] Commits have been [squashed][squash].
- If code communicates with devices:
If code communicates with devices:
- [ ] Local tests with `tox` run successfully. **Your PR cannot be merged unless tests pass**
- [ ] New dependencies have been added to the `REQUIREMENTS` variable ([example][ex-requir]).
- [ ] New dependencies are only imported inside functions that use them ([example][ex-import]).
- [ ] New dependencies have been added to `requirements_all.txt` by running `script/gen_requirements_all.py`.
- [ ] New files were added to `.coveragerc`.
- If the code does not interact with devices:

If the code does not interact with devices:
- [ ] Local tests with `tox` run successfully. **Your PR cannot be merged unless tests pass**
- [ ] Tests have been added to verify that the new code works.

[fork]: http://stackoverflow.com/a/7244456
Expand Down
2 changes: 2 additions & 0 deletions homeassistant/components/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,11 +83,13 @@ def setup(hass, config):
hass.http.register_path(
'GET', URL_API_COMPONENTS, _handle_get_api_components)

# /error_log
hass.http.register_path('GET', URL_API_ERROR_LOG,
_handle_get_api_error_log)

hass.http.register_path('POST', URL_API_LOG_OUT, _handle_post_api_log_out)

# /template
hass.http.register_path('POST', URL_API_TEMPLATE,
_handle_post_api_template)

Expand Down
68 changes: 11 additions & 57 deletions homeassistant/components/automation/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,9 @@
from homeassistant.bootstrap import prepare_setup_platform
from homeassistant.const import CONF_PLATFORM
from homeassistant.components import logbook
from homeassistant.helpers.service import call_from_config
from homeassistant.helpers.service import validate_service_call
from homeassistant.helpers import extract_domain_configs
from homeassistant.helpers.service import (call_from_config,
validate_service_call)


DOMAIN = 'automation'
Expand All @@ -35,29 +36,16 @@

def setup(hass, config):
"""Setup the automation."""
config_key = DOMAIN
found = 1

while config_key in config:
# Check for one block syntax
if isinstance(config[config_key], dict):
config_block = _migrate_old_config(config[config_key])
name = config_block.get(CONF_ALIAS, config_key)
_setup_automation(hass, config_block, name, config)

# Check for multiple block syntax
elif isinstance(config[config_key], list):
for list_no, config_block in enumerate(config[config_key]):
name = config_block.get(CONF_ALIAS,
"{}, {}".format(config_key, list_no))
_setup_automation(hass, config_block, name, config)
for config_key in extract_domain_configs(config, DOMAIN):
conf = config[config_key]

# Any scalar value is incorrect
else:
_LOGGER.error('Error in config in section %s.', config_key)
if not isinstance(conf, list):
conf = [conf]

found += 1
config_key = "{} {}".format(DOMAIN, found)
for list_no, config_block in enumerate(conf):
name = config_block.get(CONF_ALIAS, "{}, {}".format(config_key,
list_no))
_setup_automation(hass, config_block, name, config)

return True

Expand Down Expand Up @@ -97,40 +85,6 @@ def action():
return action


def _migrate_old_config(config):
"""Migrate old configuration to new."""
if CONF_PLATFORM not in config:
return config

_LOGGER.warning(
'You are using an old configuration format. Please upgrade: '
'https://home-assistant.io/components/automation/')

new_conf = {
CONF_TRIGGER: dict(config),
CONF_CONDITION: config.get('if', []),
CONF_ACTION: dict(config),
}

for cat, key, new_key in (('trigger', 'mqtt_topic', 'topic'),
('trigger', 'mqtt_payload', 'payload'),
('trigger', 'state_entity_id', 'entity_id'),
('trigger', 'state_before', 'before'),
('trigger', 'state_after', 'after'),
('trigger', 'state_to', 'to'),
('trigger', 'state_from', 'from'),
('trigger', 'state_hours', 'hours'),
('trigger', 'state_minutes', 'minutes'),
('trigger', 'state_seconds', 'seconds'),
('action', 'execute_service', 'service'),
('action', 'service_entity_id', 'entity_id'),
('action', 'service_data', 'data')):
if key in new_conf[cat]:
new_conf[cat][new_key] = new_conf[cat].pop(key)

return new_conf


def _process_if(hass, config, p_config, action):
"""Process if checks."""
cond_type = p_config.get(CONF_CONDITION_TYPE,
Expand Down
9 changes: 7 additions & 2 deletions homeassistant/components/automation/template.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,13 @@ def _check_template(hass, value_template):
"""Check if result of template is true."""
try:
value = template.render(hass, value_template, {})
except TemplateError:
_LOGGER.exception('Error parsing template')
except TemplateError as ex:
if ex.args and ex.args[0].startswith(
"UndefinedError: 'None' has no attribute"):
# Common during HA startup - so just a warning
_LOGGER.warning(ex)
else:
_LOGGER.error(ex)
return False

return value.lower() == 'true'
4 changes: 3 additions & 1 deletion homeassistant/components/binary_sensor/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@
from homeassistant.helpers.entity_component import EntityComponent
from homeassistant.helpers.entity import Entity
from homeassistant.const import (STATE_ON, STATE_OFF)
from homeassistant.components import (bloomsky, mysensors, zwave, wemo, wink)
from homeassistant.components import (
bloomsky, mysensors, zwave, vera, wemo, wink)

DOMAIN = 'binary_sensor'
SCAN_INTERVAL = 30
Expand Down Expand Up @@ -37,6 +38,7 @@
bloomsky.DISCOVER_BINARY_SENSORS: 'bloomsky',
mysensors.DISCOVER_BINARY_SENSORS: 'mysensors',
zwave.DISCOVER_BINARY_SENSORS: 'zwave',
vera.DISCOVER_BINARY_SENSORS: 'vera',
wemo.DISCOVER_BINARY_SENSORS: 'wemo',
wink.DISCOVER_BINARY_SENSORS: 'wink'
}
Expand Down
25 changes: 20 additions & 5 deletions homeassistant/components/binary_sensor/rest.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@
"""
import logging

from homeassistant.components.binary_sensor import BinarySensorDevice
from homeassistant.components.binary_sensor import (BinarySensorDevice,
SENSOR_CLASSES)
from homeassistant.components.sensor.rest import RestData
from homeassistant.const import CONF_VALUE_TEMPLATE
from homeassistant.helpers import template
Expand All @@ -19,12 +20,17 @@

# pylint: disable=unused-variable
def setup_platform(hass, config, add_devices, discovery_info=None):
"""Setup REST binary sensors."""
"""Setup the REST binary sensor."""
resource = config.get('resource', None)
method = config.get('method', DEFAULT_METHOD)
payload = config.get('payload', None)
verify_ssl = config.get('verify_ssl', True)

sensor_class = config.get('sensor_class')
if sensor_class not in SENSOR_CLASSES:
_LOGGER.warning('Unknown sensor class: %s', sensor_class)
sensor_class = None

rest = RestData(method, resource, payload, verify_ssl)
rest.update()

Expand All @@ -33,19 +39,23 @@ def setup_platform(hass, config, add_devices, discovery_info=None):
return False

add_devices([RestBinarySensor(
hass, rest, config.get('name', DEFAULT_NAME),
hass,
rest,
config.get('name', DEFAULT_NAME),
sensor_class,
config.get(CONF_VALUE_TEMPLATE))])


# pylint: disable=too-many-arguments
class RestBinarySensor(BinarySensorDevice):
"""A REST binary sensor."""
"""Representation of a REST binary sensor."""

def __init__(self, hass, rest, name, value_template):
def __init__(self, hass, rest, name, sensor_class, value_template):
"""Initialize a REST binary sensor."""
self._hass = hass
self.rest = rest
self._name = name
self._sensor_class = sensor_class
self._state = False
self._value_template = value_template
self.update()
Expand All @@ -55,6 +65,11 @@ def name(self):
"""Return the name of the binary sensor."""
return self._name

@property
def sensor_class(self):
"""Return the class of this sensor."""
return self._sensor_class

@property
def is_on(self):
"""Return true if the binary sensor is on."""
Expand Down
49 changes: 23 additions & 26 deletions homeassistant/components/binary_sensor/template.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
import logging

from homeassistant.components.binary_sensor import (BinarySensorDevice,
DOMAIN,
ENTITY_ID_FORMAT,
SENSOR_CLASSES)
from homeassistant.const import ATTR_FRIENDLY_NAME, CONF_VALUE_TEMPLATE
from homeassistant.core import EVENT_STATE_CHANGED
Expand All @@ -16,7 +16,6 @@
from homeassistant.helpers import template
from homeassistant.util import slugify

ENTITY_ID_FORMAT = DOMAIN + '.{}'
CONF_SENSORS = 'sensors'
_LOGGER = logging.getLogger(__name__)

Expand Down Expand Up @@ -76,34 +75,22 @@ class BinarySensorTemplate(BinarySensorDevice):
def __init__(self, hass, device, friendly_name, sensor_class,
value_template):
"""Initialize the Template binary sensor."""
self._hass = hass
self._device = device
self.hass = hass
self.entity_id = generate_entity_id(ENTITY_ID_FORMAT, device,
hass=hass)
self._name = friendly_name
self._sensor_class = sensor_class
self._template = value_template
self._state = None

self.entity_id = generate_entity_id(
ENTITY_ID_FORMAT, device,
hass=hass)
self.update()

_LOGGER.info('Started template sensor %s', device)
hass.bus.listen(EVENT_STATE_CHANGED, self._event_listener)
def template_bsensor_event_listener(event):
"""Called when the target device changes state."""
self.update_ha_state(True)

def _event_listener(self, event):
if not hasattr(self, 'hass'):
return
self.update_ha_state(True)

@property
def should_poll(self):
"""No polling needed."""
return False

@property
def sensor_class(self):
"""Return the sensor class of the sensor."""
return self._sensor_class
hass.bus.listen(EVENT_STATE_CHANGED,
template_bsensor_event_listener)

@property
def name(self):
Expand All @@ -115,16 +102,26 @@ def is_on(self):
"""Return true if sensor is on."""
return self._state

@property
def sensor_class(self):
"""Return the sensor class of the sensor."""
return self._sensor_class

@property
def should_poll(self):
"""No polling needed."""
return False

def update(self):
"""Get the latest data and update the state."""
try:
value = template.render(self._hass, self._template)
self._state = template.render(self.hass,
self._template).lower() == 'true'
except TemplateError as ex:
if ex.args and ex.args[0].startswith(
"UndefinedError: 'None' has no attribute"):
# Common during HA startup - so just a warning
_LOGGER.warning(ex)
return
_LOGGER.error(ex)
value = 'false'
self._state = value.lower() == 'true'
self._state = False
Loading

0 comments on commit 763a9ce

Please sign in to comment.