Migrate to voluptuous (#3298)

This commit is contained in:
Fabian Affolter 2016-09-11 09:21:16 +02:00 committed by GitHub
parent 3f4d30c8da
commit 78313c793c
2 changed files with 97 additions and 77 deletions

View file

@ -7,44 +7,67 @@ https://home-assistant.io/components/climate.honeywell/
import logging
import socket
from homeassistant.components.climate import ClimateDevice
import voluptuous as vol
from homeassistant.components.climate import (ClimateDevice, PLATFORM_SCHEMA)
from homeassistant.const import (
CONF_PASSWORD, CONF_USERNAME, TEMP_CELSIUS, TEMP_FAHRENHEIT,
ATTR_TEMPERATURE)
import homeassistant.helpers.config_validation as cv
REQUIREMENTS = ['evohomeclient==0.2.5',
'somecomfort==0.2.1']
_LOGGER = logging.getLogger(__name__)
CONF_AWAY_TEMP = "away_temperature"
DEFAULT_AWAY_TEMP = 16
ATTR_FAN = 'fan'
ATTR_FANMODE = 'fanmode'
ATTR_SYSTEM_MODE = 'system_mode'
CONF_AWAY_TEMPERATURE = 'away_temperature'
CONF_REGION = 'region'
DEFAULT_AWAY_TEMPERATURE = 16
DEFAULT_REGION = 'eu'
REGIONS = ['eu', 'us']
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
vol.Required(CONF_USERNAME): cv.string,
vol.Required(CONF_PASSWORD): cv.string,
vol.Optional(CONF_AWAY_TEMPERATURE, default=DEFAULT_AWAY_TEMPERATURE):
vol.Coerce(float),
vol.Optional(CONF_REGION, default=DEFAULT_REGION): vol.In(REGIONS),
})
def setup_platform(hass, config, add_devices, discovery_info=None):
"""Setup the HoneywelL thermostat."""
username = config.get(CONF_USERNAME)
password = config.get(CONF_PASSWORD)
region = config.get(CONF_REGION)
if region == 'us':
return _setup_us(username, password, config, add_devices)
else:
return _setup_round(username, password, config, add_devices)
def _setup_round(username, password, config, add_devices):
"""Setup rounding function."""
from evohomeclient import EvohomeClient
try:
away_temp = float(config.get(CONF_AWAY_TEMP, DEFAULT_AWAY_TEMP))
except ValueError:
_LOGGER.error("value entered for item %s should convert to a number",
CONF_AWAY_TEMP)
return False
away_temp = config.get(CONF_AWAY_TEMPERATURE)
evo_api = EvohomeClient(username, password)
try:
zones = evo_api.temperatures(force_refresh=True)
for i, zone in enumerate(zones):
add_devices([RoundThermostat(evo_api,
zone['id'],
i == 0,
away_temp)])
add_devices(
[RoundThermostat(evo_api, zone['id'], i == 0, away_temp)]
)
except socket.error:
_LOGGER.error(
"Connection error logging into the honeywell evohome web service"
)
"Connection error logging into the honeywell evohome web service")
return False
return True
@ -74,26 +97,6 @@ def _setup_us(username, password, config, add_devices):
return True
def setup_platform(hass, config, add_devices, discovery_info=None):
"""Setup the honeywel thermostat."""
username = config.get(CONF_USERNAME)
password = config.get(CONF_PASSWORD)
region = config.get('region', 'eu').lower()
if username is None or password is None:
_LOGGER.error("Missing required configuration items %s or %s",
CONF_USERNAME, CONF_PASSWORD)
return False
if region not in ('us', 'eu'):
_LOGGER.error('Region `%s` is invalid (use either us or eu)', region)
return False
if region == 'us':
return _setup_us(username, password, config, add_devices)
else:
return _setup_round(username, password, config, add_devices)
class RoundThermostat(ClimateDevice):
"""Representation of a Honeywell Round Connected thermostat."""
@ -103,7 +106,7 @@ class RoundThermostat(ClimateDevice):
self.device = device
self._current_temperature = None
self._target_temperature = None
self._name = "round connected"
self._name = 'round connected'
self._id = zone_id
self._master = master
self._is_dhw = False
@ -143,7 +146,7 @@ class RoundThermostat(ClimateDevice):
@property
def current_operation(self: ClimateDevice) -> str:
"""Get the current operation of the system."""
return getattr(self.device, 'system_mode', None)
return getattr(self.device, ATTR_SYSTEM_MODE, None)
@property
def is_away_mode_on(self):
@ -152,7 +155,7 @@ class RoundThermostat(ClimateDevice):
def set_operation_mode(self: ClimateDevice, operation_mode: str) -> None:
"""Set the HVAC mode for the thermostat."""
if hasattr(self.device, 'system_mode'):
if hasattr(self.device, ATTR_SYSTEM_MODE):
self.device.system_mode = operation_mode
def turn_away_mode_on(self):
@ -186,8 +189,8 @@ class RoundThermostat(ClimateDevice):
self._current_temperature = data['temp']
self._target_temperature = data['setpoint']
if data['thermostat'] == "DOMESTIC_HOT_WATER":
self._name = "Hot Water"
if data['thermostat'] == 'DOMESTIC_HOT_WATER':
self._name = 'Hot Water'
self._is_dhw = True
else:
self._name = data['name']
@ -236,7 +239,7 @@ class HoneywellUSThermostat(ClimateDevice):
@property
def current_operation(self: ClimateDevice) -> str:
"""Return current operation ie. heat, cool, idle."""
return getattr(self._device, 'system_mode', None)
return getattr(self._device, ATTR_SYSTEM_MODE, None)
def set_temperature(self, **kwargs):
"""Set target temperature."""
@ -255,9 +258,11 @@ class HoneywellUSThermostat(ClimateDevice):
@property
def device_state_attributes(self):
"""Return the device specific state attributes."""
return {'fan': (self.is_fan_on and 'running' or 'idle'),
'fanmode': self._device.fan_mode,
'system_mode': self._device.system_mode}
return {
ATTR_FAN: (self.is_fan_on and 'running' or 'idle'),
ATTR_FANMODE: self._device.fan_mode,
ATTR_SYSTEM_MODE: self._device.system_mode,
}
def turn_away_mode_on(self):
"""Turn away on."""
@ -269,5 +274,5 @@ class HoneywellUSThermostat(ClimateDevice):
def set_operation_mode(self: ClimateDevice, operation_mode: str) -> None:
"""Set the system mode (Cool, Heat, etc)."""
if hasattr(self._device, 'system_mode'):
if hasattr(self._device, ATTR_SYSTEM_MODE):
self._device.system_mode = operation_mode

View file

@ -3,10 +3,11 @@ import socket
import unittest
from unittest import mock
import voluptuous as vol
import somecomfort
from homeassistant.const import (CONF_USERNAME, CONF_PASSWORD,
TEMP_CELSIUS, TEMP_FAHRENHEIT)
from homeassistant.const import (
CONF_USERNAME, CONF_PASSWORD, TEMP_CELSIUS, TEMP_FAHRENHEIT)
import homeassistant.components.climate.honeywell as honeywell
@ -21,17 +22,30 @@ class TestHoneywell(unittest.TestCase):
config = {
CONF_USERNAME: 'user',
CONF_PASSWORD: 'pass',
'region': 'us',
honeywell.CONF_REGION: 'us',
}
bad_pass_config = {
CONF_USERNAME: 'user',
'region': 'us',
honeywell.CONF_REGION: 'us',
}
bad_region_config = {
CONF_USERNAME: 'user',
CONF_PASSWORD: 'pass',
'region': 'un',
honeywell.CONF_REGION: 'un',
}
with self.assertRaises(vol.Invalid):
honeywell.PLATFORM_SCHEMA(None)
with self.assertRaises(vol.Invalid):
honeywell.PLATFORM_SCHEMA({})
with self.assertRaises(vol.Invalid):
honeywell.PLATFORM_SCHEMA(bad_pass_config)
with self.assertRaises(vol.Invalid):
honeywell.PLATFORM_SCHEMA(bad_region_config)
hass = mock.MagicMock()
add_devices = mock.MagicMock()
@ -46,10 +60,6 @@ class TestHoneywell(unittest.TestCase):
locations[0].devices_by_id.values.return_value = devices_1
locations[1].devices_by_id.values.return_value = devices_2
result = honeywell.setup_platform(hass, bad_pass_config, add_devices)
self.assertFalse(result)
result = honeywell.setup_platform(hass, bad_region_config, add_devices)
self.assertFalse(result)
result = honeywell.setup_platform(hass, config, add_devices)
self.assertTrue(result)
mock_sc.assert_called_once_with('user', 'pass')
@ -67,7 +77,7 @@ class TestHoneywell(unittest.TestCase):
config = {
CONF_USERNAME: 'user',
CONF_PASSWORD: 'pass',
'region': 'us',
honeywell.CONF_REGION: 'us',
}
mock_sc.side_effect = somecomfort.AuthError
@ -88,7 +98,7 @@ class TestHoneywell(unittest.TestCase):
config = {
CONF_USERNAME: 'user',
CONF_PASSWORD: 'pass',
'region': 'us',
honeywell.CONF_REGION: 'us',
'location': loc,
'thermostat': dev,
}
@ -152,12 +162,12 @@ class TestHoneywell(unittest.TestCase):
@mock.patch('homeassistant.components.climate.honeywell.'
'RoundThermostat')
def test_eu_setup_full_config(self, mock_round, mock_evo):
"""Test the EU setup wwith complete configuration."""
"""Test the EU setup with complete configuration."""
config = {
CONF_USERNAME: 'user',
CONF_PASSWORD: 'pass',
honeywell.CONF_AWAY_TEMP: 20,
'region': 'eu',
honeywell.CONF_AWAY_TEMPERATURE: 20.0,
honeywell.CONF_REGION: 'eu',
}
mock_evo.return_value.temperatures.return_value = [
{'id': 'foo'}, {'id': 'bar'}]
@ -168,8 +178,8 @@ class TestHoneywell(unittest.TestCase):
mock_evo.return_value.temperatures.assert_called_once_with(
force_refresh=True)
mock_round.assert_has_calls([
mock.call(mock_evo.return_value, 'foo', True, 20),
mock.call(mock_evo.return_value, 'bar', False, 20),
mock.call(mock_evo.return_value, 'foo', True, 20.0),
mock.call(mock_evo.return_value, 'bar', False, 20.0),
])
self.assertEqual(2, add_devices.call_count)
@ -181,17 +191,20 @@ class TestHoneywell(unittest.TestCase):
config = {
CONF_USERNAME: 'user',
CONF_PASSWORD: 'pass',
'region': 'eu',
honeywell.CONF_REGION: 'eu',
}
mock_evo.return_value.temperatures.return_value = [
{'id': 'foo'}, {'id': 'bar'}]
config[honeywell.CONF_AWAY_TEMPERATURE] = \
honeywell.DEFAULT_AWAY_TEMPERATURE
hass = mock.MagicMock()
add_devices = mock.MagicMock()
self.assertTrue(honeywell.setup_platform(hass, config, add_devices))
default = honeywell.DEFAULT_AWAY_TEMP
mock_round.assert_has_calls([
mock.call(mock_evo.return_value, 'foo', True, default),
mock.call(mock_evo.return_value, 'bar', False, default),
mock.call(mock_evo.return_value, 'foo', True, 16),
mock.call(mock_evo.return_value, 'bar', False, 16),
])
@mock.patch('evohomeclient.EvohomeClient')
@ -202,10 +215,12 @@ class TestHoneywell(unittest.TestCase):
config = {
CONF_USERNAME: 'user',
CONF_PASSWORD: 'pass',
honeywell.CONF_AWAY_TEMP: 'ponies',
'region': 'eu',
honeywell.CONF_AWAY_TEMPERATURE: 'ponies',
honeywell.CONF_REGION: 'eu',
}
self.assertFalse(honeywell.setup_platform(None, config, None))
with self.assertRaises(vol.Invalid):
honeywell.PLATFORM_SCHEMA(config)
@mock.patch('evohomeclient.EvohomeClient')
@mock.patch('homeassistant.components.climate.honeywell.'
@ -215,8 +230,8 @@ class TestHoneywell(unittest.TestCase):
config = {
CONF_USERNAME: 'user',
CONF_PASSWORD: 'pass',
honeywell.CONF_AWAY_TEMP: 20,
'region': 'eu',
honeywell.CONF_AWAY_TEMPERATURE: 20,
honeywell.CONF_REGION: 'eu',
}
mock_evo.return_value.temperatures.side_effect = socket.error
add_devices = mock.MagicMock()
@ -356,9 +371,9 @@ class TestHoneywellUS(unittest.TestCase):
def test_attributes(self):
"""Test the attributes."""
expected = {
'fan': 'running',
'fanmode': 'auto',
'system_mode': 'heat',
honeywell.ATTR_FAN: 'running',
honeywell.ATTR_FANMODE: 'auto',
honeywell.ATTR_SYSTEM_MODE: 'heat',
}
self.assertEqual(expected, self.honeywell.device_state_attributes)
expected['fan'] = 'idle'
@ -370,8 +385,8 @@ class TestHoneywellUS(unittest.TestCase):
self.device.fan_running = False
self.device.fan_mode = None
expected = {
'fan': 'idle',
'fanmode': None,
'system_mode': 'heat',
honeywell.ATTR_FAN: 'idle',
honeywell.ATTR_FANMODE: None,
honeywell.ATTR_SYSTEM_MODE: 'heat',
}
self.assertEqual(expected, self.honeywell.device_state_attributes)