Merge pull request #3359 from home-assistant/hotfix-0-28-2

0.28.2
pull/3471/head^2 0.28.2
Paulus Schoutsen 2016-09-12 21:28:57 -07:00 committed by GitHub
commit db3bfad0b5
8 changed files with 50 additions and 65 deletions

View File

@ -116,9 +116,6 @@ class Thermostat(ClimateDevice):
return self.target_temperature_low
elif self.operation_mode == 'cool':
return self.target_temperature_high
else:
return (self.target_temperature_low +
self.target_temperature_high) / 2
@property
def target_temperature_low(self):
@ -223,19 +220,27 @@ class Thermostat(ClimateDevice):
"""Set new target temperature."""
if kwargs.get(ATTR_TEMPERATURE) is not None:
temperature = kwargs.get(ATTR_TEMPERATURE)
low_temp = temperature - 1
high_temp = temperature + 1
low_temp = int(temperature)
high_temp = int(temperature)
if kwargs.get(ATTR_TARGET_TEMP_LOW) is not None and \
kwargs.get(ATTR_TARGET_TEMP_HIGH) is not None:
low_temp = kwargs.get(ATTR_TARGET_TEMP_LOW)
high_temp = kwargs.get(ATTR_TARGET_TEMP_HIGH)
high_temp = int(kwargs.get(ATTR_TARGET_TEMP_LOW))
low_temp = int(kwargs.get(ATTR_TARGET_TEMP_HIGH))
if self.hold_temp:
self.data.ecobee.set_hold_temp(self.thermostat_index, low_temp,
high_temp, "indefinite")
_LOGGER.debug("Setting ecobee hold_temp to: low=%s, is=%s, "
"high=%s, is=%s", low_temp, isinstance(
low_temp, (int, float)), high_temp,
isinstance(high_temp, (int, float)))
else:
self.data.ecobee.set_hold_temp(self.thermostat_index, low_temp,
high_temp)
_LOGGER.debug("Setting ecobee temp to: low=%s, is=%s, "
"high=%s, is=%s", low_temp, isinstance(
low_temp, (int, float)), high_temp,
isinstance(high_temp, (int, float)))
def set_operation_mode(self, operation_mode):
"""Set HVAC mode (auto, auxHeatOnly, cool, heat, off)."""

View File

@ -28,8 +28,10 @@ def setup_platform(hass, config, add_devices, discovery_info=None):
pywink.set_bearer_token(token)
add_devices(WinkCoverDevice(shade) for shade, door in
add_devices(WinkCoverDevice(shade) for shade in
pywink.get_shades())
add_devices(WinkCoverDevice(door) for door in
pywink.get_garage_doors())
class WinkCoverDevice(WinkDevice, CoverDevice):

View File

@ -15,12 +15,11 @@ from homeassistant.components.device_tracker import (PLATFORM_SCHEMA,
ATTR_ATTRIBUTES)
from homeassistant.const import CONF_USERNAME, CONF_PASSWORD
import homeassistant.helpers.config_validation as cv
from homeassistant.util import Throttle, datetime as dt_util
from homeassistant.helpers.event import track_utc_time_change
from homeassistant.util import datetime as dt_util
_LOGGER = logging.getLogger(__name__)
MIN_TIME_BETWEEN_SCANS = timedelta(seconds=30)
CONF_CLIENT_ID = 'client_id'
CONF_SECRET = 'secret'
CONF_DEVICES = 'devices'
@ -53,7 +52,7 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
def setup_scanner(hass, config: dict, see):
"""Validate the configuration and return an Automatic scanner."""
try:
AutomaticDeviceScanner(config, see)
AutomaticDeviceScanner(hass, config, see)
except requests.HTTPError as err:
_LOGGER.error(str(err))
return False
@ -61,11 +60,14 @@ def setup_scanner(hass, config: dict, see):
return True
# pylint: disable=too-many-instance-attributes
# pylint: disable=too-few-public-methods
class AutomaticDeviceScanner(object):
"""A class representing an Automatic device."""
def __init__(self, config: dict, see) -> None:
def __init__(self, hass, config: dict, see) -> None:
"""Initialize the automatic device scanner."""
self.hass = hass
self._devices = config.get(CONF_DEVICES, None)
self._access_token_payload = {
'username': config.get(CONF_USERNAME),
@ -81,20 +83,10 @@ class AutomaticDeviceScanner(object):
self.last_trips = {}
self.see = see
self.scan_devices()
def scan_devices(self):
"""Scan for new devices and return a list with found device IDs."""
self._update_info()
return [item['id'] for item in self.last_results]
def get_device_name(self, device):
"""Get the device name from id."""
vehicle = [item['display_name'] for item in self.last_results
if item['id'] == device]
return vehicle[0]
track_utc_time_change(self.hass, self._update_info,
second=range(0, 60, 30))
def _update_headers(self):
"""Get the access token from automatic."""
@ -114,10 +106,9 @@ class AutomaticDeviceScanner(object):
'Authorization': 'Bearer {}'.format(access_token)
}
@Throttle(MIN_TIME_BETWEEN_SCANS)
def _update_info(self) -> None:
def _update_info(self, now=None) -> None:
"""Update the device info."""
_LOGGER.info('Updating devices')
_LOGGER.debug('Updating devices %s', now)
self._update_headers()
response = requests.get(URL_VEHICLES, headers=self._headers)

View File

@ -10,7 +10,6 @@ import socket
import voluptuous as vol
import homeassistant.helpers.config_validation as cv
from homeassistant.helpers.config_validation import ensure_list
from homeassistant.const import (
EVENT_HOMEASSISTANT_START, EVENT_HOMEASSISTANT_STOP, CONF_HOST, CONF_PORT,
CONF_WHITELIST)
@ -29,7 +28,10 @@ EVENT = 'pilight_received'
# The pilight code schema depends on the protocol
# Thus only require to have the protocol information
RF_CODE_SCHEMA = vol.Schema({vol.Required(ATTR_PROTOCOL): cv.string},
# Ensure that protocol is in a list otherwise segfault in pilight-daemon
# https://github.com/pilight/pilight/issues/296
RF_CODE_SCHEMA = vol.Schema({vol.Required(ATTR_PROTOCOL):
vol.All(cv.ensure_list, [cv.string])},
extra=vol.ALLOW_EXTRA)
SERVICE_NAME = 'send'
@ -71,12 +73,9 @@ def setup(hass, config):
def send_code(call):
"""Send RF code to the pilight-daemon."""
message_data = call.data
# Patch data because of bug:
# https://github.com/pilight/pilight/issues/296
# Protocol has to be in a list otherwise segfault in pilight-daemon
message_data['protocol'] = ensure_list(message_data['protocol'])
# Change type to dict from mappingproxy
# since data has to be JSON serializable
message_data = dict(call.data)
try:
pilight_client.send_code(message_data)

View File

@ -20,6 +20,7 @@ from homeassistant.core import HomeAssistant
from homeassistant.const import (EVENT_HOMEASSISTANT_START,
EVENT_HOMEASSISTANT_STOP, EVENT_STATE_CHANGED,
EVENT_TIME_CHANGED, MATCH_ALL)
import homeassistant.helpers.config_validation as cv
from homeassistant.helpers.event import track_point_in_utc_time
from homeassistant.helpers.typing import ConfigType, QueryType
import homeassistant.util.dt as dt_util
@ -40,10 +41,9 @@ QUERY_RETRY_WAIT = 0.1
CONFIG_SCHEMA = vol.Schema({
DOMAIN: vol.Schema({
vol.Optional(CONF_PURGE_DAYS): vol.All(vol.Coerce(int),
vol.Range(min=1)),
# pylint: disable=no-value-for-parameter
vol.Optional(CONF_DB_URL): vol.Url(),
vol.Optional(CONF_PURGE_DAYS):
vol.All(vol.Coerce(int), vol.Range(min=1)),
vol.Optional(CONF_DB_URL): cv.string,
})
}, extra=vol.ALLOW_EXTRA)

View File

@ -2,7 +2,7 @@
"""Constants used by Home Assistant components."""
MAJOR_VERSION = 0
MINOR_VERSION = 28
PATCH_VERSION = '1'
PATCH_VERSION = '2'
__short_version__ = '{}.{}'.format(MAJOR_VERSION, MINOR_VERSION)
__version__ = '{}.{}'.format(__short_version__, PATCH_VERSION)
REQUIRED_PYTHON_VER = (3, 4)

View File

@ -29,10 +29,10 @@ from homeassistant.const import (
SERVICE_CLOSE, SERVICE_LOCK, SERVICE_MEDIA_PAUSE, SERVICE_MEDIA_PLAY,
SERVICE_MEDIA_SEEK, SERVICE_MOVE_DOWN, SERVICE_MOVE_UP, SERVICE_OPEN,
SERVICE_TURN_OFF, SERVICE_TURN_ON, SERVICE_UNLOCK, SERVICE_VOLUME_MUTE,
SERVICE_VOLUME_SET, STATE_ALARM_ARMED_AWAY, STATE_ALARM_ARMED_HOME,
STATE_ALARM_DISARMED, STATE_ALARM_TRIGGERED, STATE_CLOSED, STATE_LOCKED,
STATE_OFF, STATE_ON, STATE_OPEN, STATE_PAUSED, STATE_PLAYING,
STATE_UNKNOWN, STATE_UNLOCKED)
SERVICE_VOLUME_SET, SERVICE_OPEN_COVER, SERVICE_CLOSE_COVER,
STATE_ALARM_ARMED_AWAY, STATE_ALARM_ARMED_HOME, STATE_ALARM_DISARMED,
STATE_ALARM_TRIGGERED, STATE_CLOSED, STATE_LOCKED, STATE_OFF, STATE_ON,
STATE_OPEN, STATE_PAUSED, STATE_PLAYING, STATE_UNKNOWN, STATE_UNLOCKED)
from homeassistant.core import State
_LOGGER = logging.getLogger(__name__)
@ -77,6 +77,8 @@ SERVICE_TO_STATE = {
SERVICE_OPEN: STATE_OPEN,
SERVICE_MOVE_UP: STATE_OPEN,
SERVICE_MOVE_DOWN: STATE_CLOSED,
SERVICE_OPEN_COVER: STATE_OPEN,
SERVICE_CLOSE_COVER: STATE_CLOSED
}

View File

@ -6,8 +6,9 @@ import unittest
from unittest.mock import patch
from homeassistant.components.device_tracker.automatic import (
URL_AUTHORIZE, URL_VEHICLES, URL_TRIPS, setup_scanner,
AutomaticDeviceScanner)
URL_AUTHORIZE, URL_VEHICLES, URL_TRIPS, setup_scanner)
from tests.common import get_test_home_assistant
_LOGGER = logging.getLogger(__name__)
@ -205,6 +206,7 @@ class TestAutomatic(unittest.TestCase):
def setUp(self):
"""Set up test data."""
self.hass = get_test_home_assistant()
def tearDown(self):
"""Tear down test data."""
@ -221,7 +223,7 @@ class TestAutomatic(unittest.TestCase):
'secret': CLIENT_SECRET
}
self.assertFalse(setup_scanner(None, config, self.see_mock))
self.assertFalse(setup_scanner(self.hass, config, self.see_mock))
@patch('requests.get', side_effect=mocked_requests)
@patch('requests.post', side_effect=mocked_requests)
@ -235,20 +237,4 @@ class TestAutomatic(unittest.TestCase):
'secret': CLIENT_SECRET
}
self.assertTrue(setup_scanner(None, config, self.see_mock))
@patch('requests.get', side_effect=mocked_requests)
@patch('requests.post', side_effect=mocked_requests)
def test_device_attributes(self, mock_get, mock_post):
"""Test device attributes are set on load."""
config = {
'platform': 'automatic',
'username': VALID_USERNAME,
'password': PASSWORD,
'client_id': CLIENT_ID,
'secret': CLIENT_SECRET
}
scanner = AutomaticDeviceScanner(config, self.see_mock)
self.assertEqual(DISPLAY_NAME, scanner.get_device_name('vid'))
self.assertTrue(setup_scanner(self.hass, config, self.see_mock))