Migrate to voluptuous (#3298)
This commit is contained in:
parent
3f4d30c8da
commit
78313c793c
2 changed files with 97 additions and 77 deletions
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Add table
Reference in a new issue