* Climate 1.0 / part 1/2/3 * fix flake * Lint * Update Google Assistant * ambiclimate to climate 1.0 (#24911) * Fix Alexa * Lint * Migrate zhong_hong * Migrate tuya * Migrate honeywell to new climate schema (#24257) * Update one * Fix model climate v2 * Cleanup p4 * Add comfort hold mode * Fix old code * Update homeassistant/components/climate/__init__.py Co-Authored-By: Paulus Schoutsen <paulus@home-assistant.io> * Update homeassistant/components/climate/const.py Co-Authored-By: Paulus Schoutsen <paulus@home-assistant.io> * First renaming * Rename operation to hvac for paulus * Rename hold mode to preset mode * Cleanup & update comments * Remove on/off * Fix supported feature count * Update services * Update demo * Fix tests & use current_hvac * Update comment * Fix tests & add typing * Add more typing * Update modes * Fix tests * Cleanup low/high with range * Update homematic part 1 * Finish homematic * Fix lint * fix hm mapping * Support simple devices * convert lcn * migrate oem * Fix xs1 * update hive * update mil * Update toon * migrate deconz * cleanup * update tesla * Fix lint * Fix vera * Migrate zwave * Migrate velbus * Cleanup humity feature * Cleanup * Migrate wink * migrate dyson * Fix current hvac * Renaming * Fix lint * Migrate tfiac * migrate tado * Fix PRESET can be None * apply PR#23913 from dev * remove EU component, etc. * remove EU component, etc. * ready to test now * de-linted * some tweaks * de-lint * better handling of edge cases * delint * fix set_mode typos * apply PR#23913 from dev * remove EU component, etc. * ready to test now * de-linted * some tweaks * de-lint * better handling of edge cases * delint * fix set_mode typos * delint, move debug code * away preset now working * code tidy-up * code tidy-up 2 * code tidy-up 3 * address issues #18932, #15063 * address issues #18932, #15063 - 2/2 * refactor MODE_AUTO to MODE_HEAT_COOL and use F not C * add low/high to set_temp * add low/high to set_temp 2 * add low/high to set_temp - delint * run HA scripts * port changes from PR #24402 * manual rebase * manual rebase 2 * delint * minor change * remove SUPPORT_HVAC_ACTION * Migrate radiotherm * Convert touchline * Migrate flexit * Migrate nuheat * Migrate maxcube * Fix names maxcube const * Migrate proliphix * Migrate heatmiser * Migrate fritzbox * Migrate opentherm_gw * Migrate venstar * Migrate daikin * Migrate modbus * Fix elif * Migrate Homematic IP Cloud to climate-1.0 (#24913) * hmip climate fix * Update hvac_mode and preset_mode * fix lint * Fix lint * Migrate generic_thermostat * Migrate incomfort to new climate schema (#24915) * initial commit * Update climate.py * Migrate eq3btsmart * Lint * cleanup PRESET_MANUAL * Migrate ecobee * No conditional features * KNX: Migrate climate component to new climate platform (#24931) * Migrate climate component * Remove unused code * Corrected line length * Lint * Lint * fix tests * Fix value * Migrate geniushub to new climate schema (#24191) * Update one * Fix model climate v2 * Cleanup p4 * Add comfort hold mode * Fix old code * Update homeassistant/components/climate/__init__.py Co-Authored-By: Paulus Schoutsen <paulus@home-assistant.io> * Update homeassistant/components/climate/const.py Co-Authored-By: Paulus Schoutsen <paulus@home-assistant.io> * First renaming * Rename operation to hvac for paulus * Rename hold mode to preset mode * Cleanup & update comments * Remove on/off * Fix supported feature count * Update services * Update demo * Fix tests & use current_hvac * Update comment * Fix tests & add typing * Add more typing * Update modes * Fix tests * Cleanup low/high with range * Update homematic part 1 * Finish homematic * Fix lint * fix hm mapping * Support simple devices * convert lcn * migrate oem * Fix xs1 * update hive * update mil * Update toon * migrate deconz * cleanup * update tesla * Fix lint * Fix vera * Migrate zwave * Migrate velbus * Cleanup humity feature * Cleanup * Migrate wink * migrate dyson * Fix current hvac * Renaming * Fix lint * Migrate tfiac * migrate tado * delinted * delinted * use latest client * clean up mappings * clean up mappings * add duration to set_temperature * add duration to set_temperature * manual rebase * tweak * fix regression * small fix * fix rebase mixup * address comments * finish refactor * fix regression * tweak type hints * delint * manual rebase * WIP: Fixes for honeywell migration to climate-1.0 (#24938) * add type hints * code tidy-up * Fixes for incomfort migration to climate-1.0 (#24936) * delint type hints * no async unless await * revert: no async unless await * revert: no async unless await 2 * delint * fix typo * Fix homekit_controller on climate-1.0 (#24948) * Fix tests on climate-1.0 branch * As part of climate-1.0, make state return the heating-cooling.current characteristic * Fixes from review * lint * Fix imports * Migrate stibel_eltron * Fix lint * Migrate coolmaster to climate 1.0 (#24967) * Migrate coolmaster to climate 1.0 * fix lint errors * More lint fixes * Fix demo to work with UI * Migrate spider * Demo update * Updated frontend to 20190705.0 * Fix boost mode (#24980) * Prepare Netatmo for climate 1.0 (#24973) * Migration Netatmo * Address comments * Update climate.py * Migrate ephember * Migrate Sensibo * Implemented review comments (#24942) * Migrate ESPHome * Migrate MQTT * Migrate Nest * Migrate melissa * Initial/partial migration of ST * Migrate ST * Remove Away mode (#24995) * Migrate evohome, cache access tokens (#24491) * add water_heater, add storage - initial commit * add water_heater, add storage - initial commit delint add missing code desiderata update honeywell client library & CODEOWNER add auth_tokens code, refactor & delint refactor for broker delint * Add Broker, Water Heater & Refactor add missing code desiderata * update honeywell client library & CODEOWNER add auth_tokens code, refactor & delint refactor for broker * bugfix - loc_idx may not be 0 more refactor - ensure pure async more refactoring appears all r/o attributes are working tweak precsion, DHW & delint remove unused code remove unused code 2 remove unused code, refactor _save_auth_tokens() * support RoundThermostat bugfix opmode, switch to util.dt, add until=1h revert breaking change * store at_expires as naive UTC remove debug code delint tidy up exception handling delint add water_heater, add storage - initial commit delint add missing code desiderata update honeywell client library & CODEOWNER add auth_tokens code, refactor & delint refactor for broker add water_heater, add storage - initial commit delint add missing code desiderata update honeywell client library & CODEOWNER add auth_tokens code, refactor & delint refactor for broker delint bugfix - loc_idx may not be 0 more refactor - ensure pure async more refactoring appears all r/o attributes are working tweak precsion, DHW & delint remove unused code remove unused code 2 remove unused code, refactor _save_auth_tokens() support RoundThermostat bugfix opmode, switch to util.dt, add until=1h revert breaking change store at_expires as naive UTC remove debug code delint tidy up exception handling delint * update CODEOWNERS * fix regression * fix requirements * migrate to climate-1.0 * tweaking * de-lint * TCS working? & delint * tweaking * TCS code finalised * remove available() logic * refactor _switchpoints() * tidy up switchpoint code * tweak * teaking device_state_attributes * some refactoring * move PRESET_CUSTOM back to evohome * move CONF_ACCESS_TOKEN_EXPIRES CONF_REFRESH_TOKEN back to evohome * refactor SP code and dt conversion * delinted * delinted * remove water_heater * fix regression * Migrate homekit * Cleanup away mode * Fix tests * add helpers * fix tests melissa * Fix nehueat * fix zwave * add more tests * fix deconz * Fix climate test emulate_hue * fix tests * fix dyson tests * fix demo with new layout * fix honeywell * Switch homekit_controller to use HVAC_MODE_HEAT_COOL instead of HVAC_MODE_AUTO (#25009) * Lint * PyLint * Pylint * fix fritzbox tests * Fix google * Fix all tests * Fix lint * Fix auto for homekit like controler * Fix lint * fix lint
271 lines
11 KiB
Python
271 lines
11 KiB
Python
"""The test for the Ecobee thermostat module."""
|
|
import unittest
|
|
from unittest import mock
|
|
import homeassistant.const as const
|
|
from homeassistant.components.ecobee import climate as ecobee
|
|
from homeassistant.const import STATE_OFF
|
|
|
|
|
|
class TestEcobee(unittest.TestCase):
|
|
"""Tests for Ecobee climate."""
|
|
|
|
def setUp(self):
|
|
"""Set up test variables."""
|
|
vals = {'name': 'Ecobee',
|
|
'program': {'climates': [{'name': 'Climate1',
|
|
'climateRef': 'c1'},
|
|
{'name': 'Climate2',
|
|
'climateRef': 'c2'}],
|
|
'currentClimateRef': 'c1'},
|
|
'runtime': {'actualTemperature': 300,
|
|
'actualHumidity': 15,
|
|
'desiredHeat': 400,
|
|
'desiredCool': 200,
|
|
'desiredFanMode': 'on'},
|
|
'settings': {'hvacMode': 'auto',
|
|
'fanMinOnTime': 10,
|
|
'heatCoolMinDelta': 50,
|
|
'holdAction': 'nextTransition'},
|
|
'equipmentStatus': 'fan',
|
|
'events': [{'name': 'Event1',
|
|
'running': True,
|
|
'type': 'hold',
|
|
'holdClimateRef': 'away',
|
|
'endDate': '2017-01-01 10:00:00',
|
|
'startDate': '2017-02-02 11:00:00'}]}
|
|
|
|
self.ecobee = mock.Mock()
|
|
self.ecobee.__getitem__ = mock.Mock(side_effect=vals.__getitem__)
|
|
self.ecobee.__setitem__ = mock.Mock(side_effect=vals.__setitem__)
|
|
|
|
self.data = mock.Mock()
|
|
self.data.ecobee.get_thermostat.return_value = self.ecobee
|
|
self.thermostat = ecobee.Thermostat(self.data, 1, False)
|
|
|
|
def test_name(self):
|
|
"""Test name property."""
|
|
assert 'Ecobee' == self.thermostat.name
|
|
|
|
def test_current_temperature(self):
|
|
"""Test current temperature."""
|
|
assert 30 == self.thermostat.current_temperature
|
|
self.ecobee['runtime']['actualTemperature'] = 404
|
|
assert 40.4 == self.thermostat.current_temperature
|
|
|
|
def test_target_temperature_low(self):
|
|
"""Test target low temperature."""
|
|
assert 40 == self.thermostat.target_temperature_low
|
|
self.ecobee['runtime']['desiredHeat'] = 502
|
|
assert 50.2 == self.thermostat.target_temperature_low
|
|
|
|
def test_target_temperature_high(self):
|
|
"""Test target high temperature."""
|
|
assert 20 == self.thermostat.target_temperature_high
|
|
self.ecobee['runtime']['desiredCool'] = 103
|
|
assert 10.3 == self.thermostat.target_temperature_high
|
|
|
|
def test_target_temperature(self):
|
|
"""Test target temperature."""
|
|
assert self.thermostat.target_temperature is None
|
|
self.ecobee['settings']['hvacMode'] = 'heat'
|
|
assert 40 == self.thermostat.target_temperature
|
|
self.ecobee['settings']['hvacMode'] = 'cool'
|
|
assert 20 == self.thermostat.target_temperature
|
|
self.ecobee['settings']['hvacMode'] = 'auxHeatOnly'
|
|
assert 40 == self.thermostat.target_temperature
|
|
self.ecobee['settings']['hvacMode'] = 'off'
|
|
assert self.thermostat.target_temperature is None
|
|
|
|
def test_desired_fan_mode(self):
|
|
"""Test desired fan mode property."""
|
|
assert 'on' == self.thermostat.fan_mode
|
|
self.ecobee['runtime']['desiredFanMode'] = 'auto'
|
|
assert 'auto' == self.thermostat.fan_mode
|
|
|
|
def test_fan(self):
|
|
"""Test fan property."""
|
|
assert const.STATE_ON == self.thermostat.fan
|
|
self.ecobee['equipmentStatus'] = ''
|
|
assert STATE_OFF == self.thermostat.fan
|
|
self.ecobee['equipmentStatus'] = 'heatPump, heatPump2'
|
|
assert STATE_OFF == self.thermostat.fan
|
|
|
|
def test_hvac_mode(self):
|
|
"""Test current operation property."""
|
|
assert 'auto' == self.thermostat.hvac_mode
|
|
self.ecobee['settings']['hvacMode'] = 'heat'
|
|
assert 'heat' == self.thermostat.hvac_mode
|
|
self.ecobee['settings']['hvacMode'] = 'cool'
|
|
assert 'cool' == self.thermostat.hvac_mode
|
|
self.ecobee['settings']['hvacMode'] = 'auxHeatOnly'
|
|
assert 'heat' == self.thermostat.hvac_mode
|
|
self.ecobee['settings']['hvacMode'] = 'off'
|
|
assert 'off' == self.thermostat.hvac_mode
|
|
|
|
def test_hvac_modes(self):
|
|
"""Test operation list property."""
|
|
assert ['auto', 'heat', 'cool', 'off'] == self.thermostat.hvac_modes
|
|
|
|
def test_hvac_mode2(self):
|
|
"""Test operation mode property."""
|
|
assert 'auto' == self.thermostat.hvac_mode
|
|
self.ecobee['settings']['hvacMode'] = 'heat'
|
|
assert 'heat' == self.thermostat.hvac_mode
|
|
|
|
def test_device_state_attributes(self):
|
|
"""Test device state attributes property."""
|
|
self.ecobee['equipmentStatus'] = 'heatPump2'
|
|
assert {'climate_list': ['Climate1', 'Climate2'],
|
|
'fan': 'off',
|
|
'fan_min_on_time': 10,
|
|
'climate_mode': 'Climate1',
|
|
'equipment_running': 'heatPump2'} == \
|
|
self.thermostat.device_state_attributes
|
|
|
|
self.ecobee['equipmentStatus'] = 'auxHeat2'
|
|
assert {'climate_list': ['Climate1', 'Climate2'],
|
|
'fan': 'off',
|
|
'fan_min_on_time': 10,
|
|
'climate_mode': 'Climate1',
|
|
'equipment_running': 'auxHeat2'} == \
|
|
self.thermostat.device_state_attributes
|
|
self.ecobee['equipmentStatus'] = 'compCool1'
|
|
assert {'climate_list': ['Climate1', 'Climate2'],
|
|
'fan': 'off',
|
|
'fan_min_on_time': 10,
|
|
'climate_mode': 'Climate1',
|
|
'equipment_running': 'compCool1'} == \
|
|
self.thermostat.device_state_attributes
|
|
self.ecobee['equipmentStatus'] = ''
|
|
assert {'climate_list': ['Climate1', 'Climate2'],
|
|
'fan': 'off',
|
|
'fan_min_on_time': 10,
|
|
'climate_mode': 'Climate1',
|
|
'equipment_running': ''} == \
|
|
self.thermostat.device_state_attributes
|
|
|
|
self.ecobee['equipmentStatus'] = 'Unknown'
|
|
assert {'climate_list': ['Climate1', 'Climate2'],
|
|
'fan': 'off',
|
|
'fan_min_on_time': 10,
|
|
'climate_mode': 'Climate1',
|
|
'equipment_running': 'Unknown'} == \
|
|
self.thermostat.device_state_attributes
|
|
|
|
def test_is_aux_heat_on(self):
|
|
"""Test aux heat property."""
|
|
assert not self.thermostat.is_aux_heat
|
|
self.ecobee['equipmentStatus'] = 'fan, auxHeat'
|
|
assert self.thermostat.is_aux_heat
|
|
|
|
def test_set_temperature(self):
|
|
"""Test set temperature."""
|
|
# Auto -> Auto
|
|
self.data.reset_mock()
|
|
self.thermostat.set_temperature(target_temp_low=20,
|
|
target_temp_high=30)
|
|
self.data.ecobee.set_hold_temp.assert_has_calls(
|
|
[mock.call(1, 30, 20, 'nextTransition')])
|
|
|
|
# Auto -> Hold
|
|
self.data.reset_mock()
|
|
self.thermostat.set_temperature(temperature=20)
|
|
self.data.ecobee.set_hold_temp.assert_has_calls(
|
|
[mock.call(1, 25, 15, 'nextTransition')])
|
|
|
|
# Cool -> Hold
|
|
self.data.reset_mock()
|
|
self.ecobee['settings']['hvacMode'] = 'cool'
|
|
self.thermostat.set_temperature(temperature=20.5)
|
|
self.data.ecobee.set_hold_temp.assert_has_calls(
|
|
[mock.call(1, 20.5, 20.5, 'nextTransition')])
|
|
|
|
# Heat -> Hold
|
|
self.data.reset_mock()
|
|
self.ecobee['settings']['hvacMode'] = 'heat'
|
|
self.thermostat.set_temperature(temperature=20)
|
|
self.data.ecobee.set_hold_temp.assert_has_calls(
|
|
[mock.call(1, 20, 20, 'nextTransition')])
|
|
|
|
# Heat -> Auto
|
|
self.data.reset_mock()
|
|
self.ecobee['settings']['hvacMode'] = 'heat'
|
|
self.thermostat.set_temperature(target_temp_low=20,
|
|
target_temp_high=30)
|
|
assert not self.data.ecobee.set_hold_temp.called
|
|
|
|
def test_set_hvac_mode(self):
|
|
"""Test operation mode setter."""
|
|
self.data.reset_mock()
|
|
self.thermostat.set_hvac_mode('auto')
|
|
self.data.ecobee.set_hvac_mode.assert_has_calls(
|
|
[mock.call(1, 'auto')])
|
|
self.data.reset_mock()
|
|
self.thermostat.set_hvac_mode('heat')
|
|
self.data.ecobee.set_hvac_mode.assert_has_calls(
|
|
[mock.call(1, 'auxHeatOnly')])
|
|
|
|
def test_set_fan_min_on_time(self):
|
|
"""Test fan min on time setter."""
|
|
self.data.reset_mock()
|
|
self.thermostat.set_fan_min_on_time(15)
|
|
self.data.ecobee.set_fan_min_on_time.assert_has_calls(
|
|
[mock.call(1, 15)])
|
|
self.data.reset_mock()
|
|
self.thermostat.set_fan_min_on_time(20)
|
|
self.data.ecobee.set_fan_min_on_time.assert_has_calls(
|
|
[mock.call(1, 20)])
|
|
|
|
def test_resume_program(self):
|
|
"""Test resume program."""
|
|
# False
|
|
self.data.reset_mock()
|
|
self.thermostat.resume_program(False)
|
|
self.data.ecobee.resume_program.assert_has_calls(
|
|
[mock.call(1, 'false')])
|
|
self.data.reset_mock()
|
|
self.thermostat.resume_program(None)
|
|
self.data.ecobee.resume_program.assert_has_calls(
|
|
[mock.call(1, 'false')])
|
|
self.data.reset_mock()
|
|
self.thermostat.resume_program(0)
|
|
self.data.ecobee.resume_program.assert_has_calls(
|
|
[mock.call(1, 'false')])
|
|
|
|
# True
|
|
self.data.reset_mock()
|
|
self.thermostat.resume_program(True)
|
|
self.data.ecobee.resume_program.assert_has_calls(
|
|
[mock.call(1, 'true')])
|
|
self.data.reset_mock()
|
|
self.thermostat.resume_program(1)
|
|
self.data.ecobee.resume_program.assert_has_calls(
|
|
[mock.call(1, 'true')])
|
|
|
|
def test_hold_preference(self):
|
|
"""Test hold preference."""
|
|
assert 'nextTransition' == self.thermostat.hold_preference()
|
|
for action in ['useEndTime4hour', 'useEndTime2hour',
|
|
'nextPeriod', 'indefinite', 'askMe']:
|
|
self.ecobee['settings']['holdAction'] = action
|
|
assert 'nextTransition' == \
|
|
self.thermostat.hold_preference()
|
|
|
|
def test_climate_list(self):
|
|
"""Test climate list property."""
|
|
assert ['Climate1', 'Climate2'] == \
|
|
self.thermostat.climate_list
|
|
|
|
def test_set_fan_mode_on(self):
|
|
"""Test set fan mode to on."""
|
|
self.data.reset_mock()
|
|
self.thermostat.set_fan_mode('on')
|
|
self.data.ecobee.set_fan_mode.assert_has_calls(
|
|
[mock.call(1, 'on', 20, 40, 'nextTransition')])
|
|
|
|
def test_set_fan_mode_auto(self):
|
|
"""Test set fan mode to auto."""
|
|
self.data.reset_mock()
|
|
self.thermostat.set_fan_mode('auto')
|
|
self.data.ecobee.set_fan_mode.assert_has_calls(
|
|
[mock.call(1, 'auto', 20, 40, 'nextTransition')])
|