mirror of
https://github.com/home-assistant/core.git
synced 2025-07-27 07:07:28 +00:00
commit
33cba4da85
@ -4,8 +4,13 @@ trigger:
|
|||||||
batch: true
|
batch: true
|
||||||
branches:
|
branches:
|
||||||
include:
|
include:
|
||||||
|
- rc
|
||||||
- dev
|
- dev
|
||||||
pr: none
|
- master
|
||||||
|
pr:
|
||||||
|
- rc
|
||||||
|
- dev
|
||||||
|
- master
|
||||||
|
|
||||||
resources:
|
resources:
|
||||||
containers:
|
containers:
|
||||||
@ -20,6 +25,7 @@ variables:
|
|||||||
value: '2df3ae11-3bf6-49bc-a809-ba0d340d6a6d'
|
value: '2df3ae11-3bf6-49bc-a809-ba0d340d6a6d'
|
||||||
- name: PythonMain
|
- name: PythonMain
|
||||||
value: '35'
|
value: '35'
|
||||||
|
- group: codecov
|
||||||
|
|
||||||
stages:
|
stages:
|
||||||
|
|
||||||
@ -80,7 +86,7 @@ stages:
|
|||||||
steps:
|
steps:
|
||||||
- script: |
|
- script: |
|
||||||
python --version > .cache
|
python --version > .cache
|
||||||
displayName: 'Set python $(python.version) for requirement cache'
|
displayName: 'Set python $(python.container) for requirement cache'
|
||||||
- task: 1ESLighthouseEng.PipelineArtifactCaching.RestoreCacheV1.RestoreCache@1
|
- task: 1ESLighthouseEng.PipelineArtifactCaching.RestoreCacheV1.RestoreCache@1
|
||||||
displayName: 'Restore artifacts based on Requirements'
|
displayName: 'Restore artifacts based on Requirements'
|
||||||
inputs:
|
inputs:
|
||||||
@ -97,38 +103,55 @@ stages:
|
|||||||
pip install pytest-azurepipelines -c homeassistant/package_constraints.txt
|
pip install pytest-azurepipelines -c homeassistant/package_constraints.txt
|
||||||
displayName: 'Create Virtual Environment & Install Requirements'
|
displayName: 'Create Virtual Environment & Install Requirements'
|
||||||
condition: and(succeeded(), ne(variables['CacheRestored'], 'true'))
|
condition: and(succeeded(), ne(variables['CacheRestored'], 'true'))
|
||||||
- task: 1ESLighthouseEng.PipelineArtifactCaching.SaveCacheV1.SaveCache@1
|
# Explicit Cache Save (instead of using RestoreAndSaveCache)
|
||||||
displayName: 'Save artifacts based on Requirements'
|
# Dont wait with cache save for all the other task in this job to complete (±30 minutes), other parallel jobs might utilize this
|
||||||
inputs:
|
- task: 1ESLighthouseEng.PipelineArtifactCaching.SaveCacheV1.SaveCache@1
|
||||||
keyfile: 'requirements_test_all.txt, .cache'
|
displayName: 'Save artifacts based on Requirements'
|
||||||
targetfolder: './venv'
|
inputs:
|
||||||
|
keyfile: 'requirements_test_all.txt, .cache'
|
||||||
|
targetfolder: './venv'
|
||||||
vstsFeed: '$(ArtifactFeed)'
|
vstsFeed: '$(ArtifactFeed)'
|
||||||
- script: |
|
- script: |
|
||||||
. venv/bin/activate
|
. venv/bin/activate
|
||||||
pip install -e .
|
pip install -e .
|
||||||
displayName: 'Install Home Assistant for python $(python.version)'
|
displayName: 'Install Home Assistant for python $(python.container)'
|
||||||
- script: |
|
- script: |
|
||||||
. venv/bin/activate
|
. venv/bin/activate
|
||||||
pytest --timeout=9 --durations=10 --junitxml=junit/test-results.xml -qq -o console_output_style=count -p no:sugar tests
|
pytest --timeout=9 --durations=10 --junitxml=test-results.xml -qq -o console_output_style=count -p no:sugar tests
|
||||||
displayName: 'Run pytest for python $(python.version)'
|
displayName: 'Run pytest for python $(python.container)'
|
||||||
|
condition: and(succeeded(), ne(variables['python.container'], variables['PythonMain']))
|
||||||
|
- script: |
|
||||||
|
. venv/bin/activate
|
||||||
|
pytest --timeout=9 --durations=10 --junitxml=test-results.xml --cov --cov-report=xml -qq -o console_output_style=count -p no:sugar tests
|
||||||
|
codecov
|
||||||
|
displayName: 'Run pytest for python $(python.container) / coverage'
|
||||||
|
env:
|
||||||
|
CODECOV_TOKEN: '$(codecovToken)'
|
||||||
|
condition: and(succeeded(), eq(variables['python.container'], variables['PythonMain']))
|
||||||
- task: PublishTestResults@2
|
- task: PublishTestResults@2
|
||||||
condition: succeededOrFailed()
|
condition: succeededOrFailed()
|
||||||
inputs:
|
inputs:
|
||||||
testResultsFiles: '**/test-*.xml'
|
testResultsFiles: 'test-results.xml'
|
||||||
testRunTitle: 'Publish test results for Python $(python.version)'
|
testRunTitle: 'Publish test results for Python $(python.container)'
|
||||||
|
- task: PublishCodeCoverageResults@1
|
||||||
|
inputs:
|
||||||
|
codeCoverageTool: cobertura
|
||||||
|
summaryFileLocation: coverage.xml
|
||||||
|
displayName: 'publish coverage artifact'
|
||||||
|
condition: and(succeeded(), eq(variables['python.container'], variables['PythonMain']))
|
||||||
|
|
||||||
- stage: 'FullCheck'
|
- stage: 'FullCheck'
|
||||||
dependsOn:
|
dependsOn:
|
||||||
- 'Overview'
|
- 'Overview'
|
||||||
jobs:
|
jobs:
|
||||||
- job: 'Pytlint'
|
- job: 'Pylint'
|
||||||
pool:
|
pool:
|
||||||
vmImage: 'ubuntu-latest'
|
vmImage: 'ubuntu-latest'
|
||||||
container: $[ variables['PythonMain'] ]
|
container: $[ variables['PythonMain'] ]
|
||||||
steps:
|
steps:
|
||||||
- script: |
|
- script: |
|
||||||
python --version > .cache
|
python --version > .cache
|
||||||
displayName: 'Set python $(python.version) for requirement cache'
|
displayName: 'Set python $(PythonMain) for requirement cache'
|
||||||
- task: 1ESLighthouseEng.PipelineArtifactCaching.RestoreCacheV1.RestoreCache@1
|
- task: 1ESLighthouseEng.PipelineArtifactCaching.RestoreCacheV1.RestoreCache@1
|
||||||
displayName: 'Restore artifacts based on Requirements'
|
displayName: 'Restore artifacts based on Requirements'
|
||||||
inputs:
|
inputs:
|
||||||
@ -154,7 +177,7 @@ stages:
|
|||||||
- script: |
|
- script: |
|
||||||
. venv/bin/activate
|
. venv/bin/activate
|
||||||
pip install -e .
|
pip install -e .
|
||||||
displayName: 'Install Home Assistant for python $(python.version)'
|
displayName: 'Install Home Assistant for python $(PythonMain)'
|
||||||
- script: |
|
- script: |
|
||||||
. venv/bin/activate
|
. venv/bin/activate
|
||||||
pylint homeassistant
|
pylint homeassistant
|
||||||
|
@ -15,7 +15,7 @@ from homeassistant.components.climate.const import (
|
|||||||
CURRENT_HVAC_COOL, SUPPORT_PRESET_MODE
|
CURRENT_HVAC_COOL, SUPPORT_PRESET_MODE
|
||||||
)
|
)
|
||||||
from homeassistant.const import (
|
from homeassistant.const import (
|
||||||
ATTR_ENTITY_ID, STATE_ON, ATTR_TEMPERATURE, TEMP_FAHRENHEIT, TEMP_CELSIUS)
|
ATTR_ENTITY_ID, STATE_ON, ATTR_TEMPERATURE, TEMP_FAHRENHEIT)
|
||||||
import homeassistant.helpers.config_validation as cv
|
import homeassistant.helpers.config_validation as cv
|
||||||
|
|
||||||
_CONFIGURING = {}
|
_CONFIGURING = {}
|
||||||
@ -31,6 +31,8 @@ PRESET_AUX_HEAT_ONLY = 'aux_heat_only'
|
|||||||
PRESET_HOLD_NEXT_TRANSITION = 'next_transition'
|
PRESET_HOLD_NEXT_TRANSITION = 'next_transition'
|
||||||
PRESET_HOLD_INDEFINITE = 'indefinite'
|
PRESET_HOLD_INDEFINITE = 'indefinite'
|
||||||
AWAY_MODE = 'awayMode'
|
AWAY_MODE = 'awayMode'
|
||||||
|
PRESET_HOME = 'home'
|
||||||
|
PRESET_SLEEP = 'sleep'
|
||||||
|
|
||||||
# Order matters, because for reverse mapping we don't want to map HEAT to AUX
|
# Order matters, because for reverse mapping we don't want to map HEAT to AUX
|
||||||
ECOBEE_HVAC_TO_HASS = collections.OrderedDict([
|
ECOBEE_HVAC_TO_HASS = collections.OrderedDict([
|
||||||
@ -48,9 +50,8 @@ PRESET_TO_ECOBEE_HOLD = {
|
|||||||
|
|
||||||
PRESET_MODES = [
|
PRESET_MODES = [
|
||||||
PRESET_AWAY,
|
PRESET_AWAY,
|
||||||
PRESET_TEMPERATURE,
|
PRESET_HOME,
|
||||||
PRESET_HOLD_NEXT_TRANSITION,
|
PRESET_SLEEP
|
||||||
PRESET_HOLD_INDEFINITE
|
|
||||||
]
|
]
|
||||||
|
|
||||||
SERVICE_SET_FAN_MIN_ON_TIME = 'ecobee_set_fan_min_on_time'
|
SERVICE_SET_FAN_MIN_ON_TIME = 'ecobee_set_fan_min_on_time'
|
||||||
@ -168,9 +169,6 @@ class Thermostat(ClimateDevice):
|
|||||||
@property
|
@property
|
||||||
def temperature_unit(self):
|
def temperature_unit(self):
|
||||||
"""Return the unit of measurement."""
|
"""Return the unit of measurement."""
|
||||||
if self.thermostat['settings']['useCelsius']:
|
|
||||||
return TEMP_CELSIUS
|
|
||||||
|
|
||||||
return TEMP_FAHRENHEIT
|
return TEMP_FAHRENHEIT
|
||||||
|
|
||||||
@property
|
@property
|
||||||
@ -308,9 +306,9 @@ class Thermostat(ClimateDevice):
|
|||||||
"""Return true if aux heater."""
|
"""Return true if aux heater."""
|
||||||
return 'auxHeat' in self.thermostat['equipmentStatus']
|
return 'auxHeat' in self.thermostat['equipmentStatus']
|
||||||
|
|
||||||
def set_preset(self, preset):
|
def set_preset_mode(self, preset_mode):
|
||||||
"""Activate a preset."""
|
"""Activate a preset."""
|
||||||
if preset == self.preset_mode:
|
if preset_mode == self.preset_mode:
|
||||||
return
|
return
|
||||||
|
|
||||||
self.update_without_throttle = True
|
self.update_without_throttle = True
|
||||||
@ -320,23 +318,26 @@ class Thermostat(ClimateDevice):
|
|||||||
self.data.ecobee.delete_vacation(
|
self.data.ecobee.delete_vacation(
|
||||||
self.thermostat_index, self.vacation)
|
self.thermostat_index, self.vacation)
|
||||||
|
|
||||||
if preset == PRESET_AWAY:
|
if preset_mode == PRESET_AWAY:
|
||||||
self.data.ecobee.set_climate_hold(self.thermostat_index, 'away',
|
self.data.ecobee.set_climate_hold(self.thermostat_index, 'away',
|
||||||
'indefinite')
|
'indefinite')
|
||||||
|
|
||||||
elif preset == PRESET_TEMPERATURE:
|
elif preset_mode == PRESET_TEMPERATURE:
|
||||||
self.set_temp_hold(self.current_temperature)
|
self.set_temp_hold(self.current_temperature)
|
||||||
|
|
||||||
elif preset in (PRESET_HOLD_NEXT_TRANSITION, PRESET_HOLD_INDEFINITE):
|
elif preset_mode in (
|
||||||
|
PRESET_HOLD_NEXT_TRANSITION, PRESET_HOLD_INDEFINITE):
|
||||||
self.data.ecobee.set_climate_hold(
|
self.data.ecobee.set_climate_hold(
|
||||||
self.thermostat_index, PRESET_TO_ECOBEE_HOLD[preset],
|
self.thermostat_index, PRESET_TO_ECOBEE_HOLD[preset_mode],
|
||||||
self.hold_preference())
|
self.hold_preference())
|
||||||
|
|
||||||
elif preset is None:
|
elif preset_mode is None:
|
||||||
self.data.ecobee.resume_program(self.thermostat_index)
|
self.data.ecobee.resume_program(self.thermostat_index)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
_LOGGER.warning("Received invalid preset: %s", preset)
|
self.data.ecobee.set_climate_hold(
|
||||||
|
self.thermostat_index, preset_mode, self.hold_preference())
|
||||||
|
self.update_without_throttle = True
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def preset_modes(self):
|
def preset_modes(self):
|
||||||
|
@ -66,9 +66,9 @@ def setup_platform(hass, config, add_entities, discovery_info=None):
|
|||||||
|
|
||||||
for name, device_cfg in config[CONF_DEVICES].items():
|
for name, device_cfg in config[CONF_DEVICES].items():
|
||||||
mac = device_cfg[CONF_MAC]
|
mac = device_cfg[CONF_MAC]
|
||||||
devices.append(EQ3BTSmartThermostat(mac, name), True)
|
devices.append(EQ3BTSmartThermostat(mac, name))
|
||||||
|
|
||||||
add_entities(devices)
|
add_entities(devices, True)
|
||||||
|
|
||||||
|
|
||||||
class EQ3BTSmartThermostat(ClimateDevice):
|
class EQ3BTSmartThermostat(ClimateDevice):
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
"name": "Home Assistant Frontend",
|
"name": "Home Assistant Frontend",
|
||||||
"documentation": "https://www.home-assistant.io/components/frontend",
|
"documentation": "https://www.home-assistant.io/components/frontend",
|
||||||
"requirements": [
|
"requirements": [
|
||||||
"home-assistant-frontend==20190717.1"
|
"home-assistant-frontend==20190718.0"
|
||||||
],
|
],
|
||||||
"dependencies": [
|
"dependencies": [
|
||||||
"api",
|
"api",
|
||||||
|
@ -66,6 +66,8 @@ class HMThermostat(HMDevice, ClimateDevice):
|
|||||||
|
|
||||||
Need to be one of HVAC_MODE_*.
|
Need to be one of HVAC_MODE_*.
|
||||||
"""
|
"""
|
||||||
|
if self.current_temperature <= self._hmdevice.OFF_VALUE + 0.5:
|
||||||
|
return HVAC_MODE_OFF
|
||||||
if "MANU_MODE" in self._hmdevice.ACTIONNODE:
|
if "MANU_MODE" in self._hmdevice.ACTIONNODE:
|
||||||
if self._hm_controll_mode == self._hmdevice.MANU_MODE:
|
if self._hm_controll_mode == self._hmdevice.MANU_MODE:
|
||||||
return HVAC_MODE_HEAT
|
return HVAC_MODE_HEAT
|
||||||
@ -157,12 +159,12 @@ class HMThermostat(HMDevice, ClimateDevice):
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def min_temp(self):
|
def min_temp(self):
|
||||||
"""Return the minimum temperature - 4.5 means off."""
|
"""Return the minimum temperature."""
|
||||||
return 4.5
|
return 4.5
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def max_temp(self):
|
def max_temp(self):
|
||||||
"""Return the maximum temperature - 30.5 means on."""
|
"""Return the maximum temperature."""
|
||||||
return 30.5
|
return 30.5
|
||||||
|
|
||||||
@property
|
@property
|
||||||
|
@ -23,8 +23,8 @@ from .const import DATA_NETATMO_AUTH
|
|||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
PRESET_FROST_GUARD = 'frost guard'
|
PRESET_FROST_GUARD = 'Frost Guard'
|
||||||
PRESET_SCHEDULE = 'schedule'
|
PRESET_SCHEDULE = 'Schedule'
|
||||||
|
|
||||||
SUPPORT_FLAGS = (SUPPORT_TARGET_TEMPERATURE | SUPPORT_PRESET_MODE)
|
SUPPORT_FLAGS = (SUPPORT_TARGET_TEMPERATURE | SUPPORT_PRESET_MODE)
|
||||||
SUPPORT_HVAC = [HVAC_MODE_HEAT, HVAC_MODE_AUTO, HVAC_MODE_OFF]
|
SUPPORT_HVAC = [HVAC_MODE_HEAT, HVAC_MODE_AUTO, HVAC_MODE_OFF]
|
||||||
@ -48,9 +48,19 @@ PRESET_MAP_NETATMO = {
|
|||||||
STATE_NETATMO_OFF: STATE_NETATMO_OFF
|
STATE_NETATMO_OFF: STATE_NETATMO_OFF
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NETATMO_MAP_PRESET = {
|
||||||
|
STATE_NETATMO_HG: PRESET_FROST_GUARD,
|
||||||
|
STATE_NETATMO_MAX: PRESET_BOOST,
|
||||||
|
STATE_NETATMO_SCHEDULE: PRESET_SCHEDULE,
|
||||||
|
STATE_NETATMO_AWAY: PRESET_AWAY,
|
||||||
|
STATE_NETATMO_OFF: STATE_NETATMO_OFF,
|
||||||
|
STATE_NETATMO_MANUAL: 'Manual',
|
||||||
|
}
|
||||||
|
|
||||||
HVAC_MAP_NETATMO = {
|
HVAC_MAP_NETATMO = {
|
||||||
STATE_NETATMO_SCHEDULE: HVAC_MODE_AUTO,
|
STATE_NETATMO_SCHEDULE: HVAC_MODE_AUTO,
|
||||||
STATE_NETATMO_HG: HVAC_MODE_AUTO,
|
STATE_NETATMO_HG: HVAC_MODE_AUTO,
|
||||||
|
PRESET_FROST_GUARD: HVAC_MODE_AUTO,
|
||||||
STATE_NETATMO_MAX: HVAC_MODE_HEAT,
|
STATE_NETATMO_MAX: HVAC_MODE_HEAT,
|
||||||
STATE_NETATMO_OFF: HVAC_MODE_OFF,
|
STATE_NETATMO_OFF: HVAC_MODE_OFF,
|
||||||
STATE_NETATMO_MANUAL: HVAC_MODE_AUTO,
|
STATE_NETATMO_MANUAL: HVAC_MODE_AUTO,
|
||||||
@ -294,8 +304,9 @@ class NetatmoThermostat(ClimateDevice):
|
|||||||
self._data.room_status[self._room_id]['current_temperature']
|
self._data.room_status[self._room_id]['current_temperature']
|
||||||
self._target_temperature = \
|
self._target_temperature = \
|
||||||
self._data.room_status[self._room_id]['target_temperature']
|
self._data.room_status[self._room_id]['target_temperature']
|
||||||
self._preset = \
|
self._preset = NETATMO_MAP_PRESET[
|
||||||
self._data.room_status[self._room_id]["setpoint_mode"]
|
self._data.room_status[self._room_id]["setpoint_mode"]
|
||||||
|
]
|
||||||
self._hvac_mode = HVAC_MAP_NETATMO[self._preset]
|
self._hvac_mode = HVAC_MAP_NETATMO[self._preset]
|
||||||
except KeyError:
|
except KeyError:
|
||||||
_LOGGER.error(
|
_LOGGER.error(
|
||||||
|
@ -130,9 +130,14 @@ class OpenThermClimate(ClimateDevice):
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def hvac_mode(self):
|
def hvac_mode(self):
|
||||||
"""Return current operation ie. heat, cool, idle."""
|
"""Return current HVAC mode."""
|
||||||
return self._current_operation
|
return self._current_operation
|
||||||
|
|
||||||
|
@property
|
||||||
|
def hvac_modes(self):
|
||||||
|
"""Return available HVAC modes."""
|
||||||
|
return []
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def current_temperature(self):
|
def current_temperature(self):
|
||||||
"""Return the current temperature."""
|
"""Return the current temperature."""
|
||||||
|
@ -224,13 +224,12 @@ class RadioThermostat(ClimateDevice):
|
|||||||
|
|
||||||
if self._is_model_ct80:
|
if self._is_model_ct80:
|
||||||
try:
|
try:
|
||||||
humiditydata = self.device.tstat.humidity['raw']
|
humiditydata = self.device.humidity['raw']
|
||||||
except radiotherm.validate.RadiothermTstatError:
|
except radiotherm.validate.RadiothermTstatError:
|
||||||
_LOGGER.warning('%s (%s) was busy (invalid value returned)',
|
_LOGGER.warning('%s (%s) was busy (invalid value returned)',
|
||||||
self._name, self.device.host)
|
self._name, self.device.host)
|
||||||
return
|
return
|
||||||
current_humidity = humiditydata['humidity']
|
self._current_humidity = humiditydata
|
||||||
self._current_humidity = current_humidity
|
|
||||||
|
|
||||||
# Map thermostat values into various STATE_ flags.
|
# Map thermostat values into various STATE_ flags.
|
||||||
self._current_temperature = current_temp
|
self._current_temperature = current_temp
|
||||||
|
@ -323,6 +323,9 @@ class SmartThingsAirConditioner(SmartThingsEntity, ClimateDevice):
|
|||||||
|
|
||||||
async def async_set_hvac_mode(self, hvac_mode):
|
async def async_set_hvac_mode(self, hvac_mode):
|
||||||
"""Set new target operation mode."""
|
"""Set new target operation mode."""
|
||||||
|
if hvac_mode == HVAC_MODE_OFF:
|
||||||
|
await self.async_turn_off()
|
||||||
|
return
|
||||||
await self._device.set_air_conditioner_mode(
|
await self._device.set_air_conditioner_mode(
|
||||||
STATE_TO_AC_MODE[hvac_mode], set_status=True)
|
STATE_TO_AC_MODE[hvac_mode], set_status=True)
|
||||||
# State is set optimistically in the command above, therefore update
|
# State is set optimistically in the command above, therefore update
|
||||||
@ -344,18 +347,32 @@ class SmartThingsAirConditioner(SmartThingsEntity, ClimateDevice):
|
|||||||
# the entity state ahead of receiving the confirming push updates
|
# the entity state ahead of receiving the confirming push updates
|
||||||
self.async_schedule_update_ha_state()
|
self.async_schedule_update_ha_state()
|
||||||
|
|
||||||
|
async def async_turn_on(self):
|
||||||
|
"""Turn device on."""
|
||||||
|
await self._device.switch_on(set_status=True)
|
||||||
|
# State is set optimistically in the command above, therefore update
|
||||||
|
# the entity state ahead of receiving the confirming push updates
|
||||||
|
self.async_schedule_update_ha_state()
|
||||||
|
|
||||||
|
async def async_turn_off(self):
|
||||||
|
"""Turn device off."""
|
||||||
|
await self._device.switch_off(set_status=True)
|
||||||
|
# State is set optimistically in the command above, therefore update
|
||||||
|
# the entity state ahead of receiving the confirming push updates
|
||||||
|
self.async_schedule_update_ha_state()
|
||||||
|
|
||||||
async def async_update(self):
|
async def async_update(self):
|
||||||
"""Update the calculated fields of the AC."""
|
"""Update the calculated fields of the AC."""
|
||||||
operations = set()
|
modes = {HVAC_MODE_OFF}
|
||||||
for mode in self._device.status.supported_ac_modes:
|
for mode in self._device.status.supported_ac_modes:
|
||||||
state = AC_MODE_TO_STATE.get(mode)
|
state = AC_MODE_TO_STATE.get(mode)
|
||||||
if state is not None:
|
if state is not None:
|
||||||
operations.add(state)
|
modes.add(state)
|
||||||
else:
|
else:
|
||||||
_LOGGER.debug('Device %s (%s) returned an invalid supported '
|
_LOGGER.debug('Device %s (%s) returned an invalid supported '
|
||||||
'AC mode: %s', self._device.label,
|
'AC mode: %s', self._device.label,
|
||||||
self._device.device_id, mode)
|
self._device.device_id, mode)
|
||||||
self._hvac_modes = operations
|
self._hvac_modes = modes
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def current_temperature(self):
|
def current_temperature(self):
|
||||||
@ -400,6 +417,8 @@ class SmartThingsAirConditioner(SmartThingsEntity, ClimateDevice):
|
|||||||
@property
|
@property
|
||||||
def hvac_mode(self):
|
def hvac_mode(self):
|
||||||
"""Return current operation ie. heat, cool, idle."""
|
"""Return current operation ie. heat, cool, idle."""
|
||||||
|
if not self._device.status.switch:
|
||||||
|
return HVAC_MODE_OFF
|
||||||
return AC_MODE_TO_STATE.get(self._device.status.air_conditioner_mode)
|
return AC_MODE_TO_STATE.get(self._device.status.air_conditioner_mode)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
|
@ -4,8 +4,9 @@ import logging
|
|||||||
|
|
||||||
from homeassistant.components.climate import ClimateDevice
|
from homeassistant.components.climate import ClimateDevice
|
||||||
from homeassistant.components.climate.const import (
|
from homeassistant.components.climate.const import (
|
||||||
CURRENT_HVAC_COOL, CURRENT_HVAC_HEAT, CURRENT_HVAC_IDLE, CURRENT_HVAC_OFF,
|
CURRENT_HVAC_COOL, CURRENT_HVAC_FAN, CURRENT_HVAC_HEAT, CURRENT_HVAC_IDLE,
|
||||||
DOMAIN, HVAC_MODE_COOL, HVAC_MODE_HEAT, HVAC_MODE_HEAT_COOL, HVAC_MODE_OFF,
|
CURRENT_HVAC_OFF, DOMAIN, HVAC_MODE_COOL, HVAC_MODE_HEAT,
|
||||||
|
HVAC_MODE_HEAT_COOL, HVAC_MODE_DRY, HVAC_MODE_FAN_ONLY, HVAC_MODE_OFF,
|
||||||
SUPPORT_FAN_MODE, SUPPORT_SWING_MODE, SUPPORT_TARGET_TEMPERATURE)
|
SUPPORT_FAN_MODE, SUPPORT_SWING_MODE, SUPPORT_TARGET_TEMPERATURE)
|
||||||
from homeassistant.const import ATTR_TEMPERATURE, TEMP_CELSIUS, TEMP_FAHRENHEIT
|
from homeassistant.const import ATTR_TEMPERATURE, TEMP_CELSIUS, TEMP_FAHRENHEIT
|
||||||
from homeassistant.core import callback
|
from homeassistant.core import callback
|
||||||
@ -35,6 +36,11 @@ HVAC_STATE_MAPPINGS = {
|
|||||||
'Heat': HVAC_MODE_HEAT,
|
'Heat': HVAC_MODE_HEAT,
|
||||||
'Heat Mode': HVAC_MODE_HEAT,
|
'Heat Mode': HVAC_MODE_HEAT,
|
||||||
'Heat (Default)': HVAC_MODE_HEAT,
|
'Heat (Default)': HVAC_MODE_HEAT,
|
||||||
|
'Aux Heat': HVAC_MODE_HEAT,
|
||||||
|
'Furnace': HVAC_MODE_HEAT,
|
||||||
|
'Fan Only': HVAC_MODE_FAN_ONLY,
|
||||||
|
'Dry Air': HVAC_MODE_DRY,
|
||||||
|
'Moist Air': HVAC_MODE_DRY,
|
||||||
'Cool': HVAC_MODE_COOL,
|
'Cool': HVAC_MODE_COOL,
|
||||||
'Auto': HVAC_MODE_HEAT_COOL,
|
'Auto': HVAC_MODE_HEAT_COOL,
|
||||||
}
|
}
|
||||||
@ -43,7 +49,13 @@ HVAC_STATE_MAPPINGS = {
|
|||||||
HVAC_CURRENT_MAPPINGS = {
|
HVAC_CURRENT_MAPPINGS = {
|
||||||
"Idle": CURRENT_HVAC_IDLE,
|
"Idle": CURRENT_HVAC_IDLE,
|
||||||
"Heat": CURRENT_HVAC_HEAT,
|
"Heat": CURRENT_HVAC_HEAT,
|
||||||
|
"Pending Heat": CURRENT_HVAC_HEAT,
|
||||||
|
"Heating": CURRENT_HVAC_HEAT,
|
||||||
"Cool": CURRENT_HVAC_COOL,
|
"Cool": CURRENT_HVAC_COOL,
|
||||||
|
"Pending Cool": CURRENT_HVAC_COOL,
|
||||||
|
"Cooling": CURRENT_HVAC_COOL,
|
||||||
|
"Fan Only": CURRENT_HVAC_FAN,
|
||||||
|
"Vent / Economiser": CURRENT_HVAC_FAN,
|
||||||
"Off": CURRENT_HVAC_OFF,
|
"Off": CURRENT_HVAC_OFF,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
"""Constants used by Home Assistant components."""
|
"""Constants used by Home Assistant components."""
|
||||||
MAJOR_VERSION = 0
|
MAJOR_VERSION = 0
|
||||||
MINOR_VERSION = 96
|
MINOR_VERSION = 96
|
||||||
PATCH_VERSION = '0'
|
PATCH_VERSION = '1'
|
||||||
__short_version__ = '{}.{}'.format(MAJOR_VERSION, MINOR_VERSION)
|
__short_version__ = '{}.{}'.format(MAJOR_VERSION, MINOR_VERSION)
|
||||||
__version__ = '{}.{}'.format(__short_version__, PATCH_VERSION)
|
__version__ = '{}.{}'.format(__short_version__, PATCH_VERSION)
|
||||||
REQUIRED_PYTHON_VER = (3, 5, 3)
|
REQUIRED_PYTHON_VER = (3, 5, 3)
|
||||||
|
@ -10,7 +10,7 @@ certifi>=2019.6.16
|
|||||||
cryptography==2.7
|
cryptography==2.7
|
||||||
distro==1.4.0
|
distro==1.4.0
|
||||||
hass-nabucasa==0.15
|
hass-nabucasa==0.15
|
||||||
home-assistant-frontend==20190717.1
|
home-assistant-frontend==20190718.0
|
||||||
importlib-metadata==0.18
|
importlib-metadata==0.18
|
||||||
jinja2>=2.10.1
|
jinja2>=2.10.1
|
||||||
netdisco==2.6.0
|
netdisco==2.6.0
|
||||||
|
@ -610,7 +610,7 @@ hole==0.3.0
|
|||||||
holidays==0.9.10
|
holidays==0.9.10
|
||||||
|
|
||||||
# homeassistant.components.frontend
|
# homeassistant.components.frontend
|
||||||
home-assistant-frontend==20190717.1
|
home-assistant-frontend==20190718.0
|
||||||
|
|
||||||
# homeassistant.components.zwave
|
# homeassistant.components.zwave
|
||||||
homeassistant-pyozw==0.1.4
|
homeassistant-pyozw==0.1.4
|
||||||
|
@ -165,7 +165,7 @@ hdate==0.8.8
|
|||||||
holidays==0.9.10
|
holidays==0.9.10
|
||||||
|
|
||||||
# homeassistant.components.frontend
|
# homeassistant.components.frontend
|
||||||
home-assistant-frontend==20190717.1
|
home-assistant-frontend==20190718.0
|
||||||
|
|
||||||
# homeassistant.components.homekit_controller
|
# homeassistant.components.homekit_controller
|
||||||
homekit[IP]==0.14.0
|
homekit[IP]==0.14.0
|
||||||
|
@ -13,15 +13,15 @@ from homeassistant.components.climate.const import (
|
|||||||
ATTR_FAN_MODES, ATTR_HVAC_ACTIONS, ATTR_HVAC_MODE, ATTR_HVAC_MODES,
|
ATTR_FAN_MODES, ATTR_HVAC_ACTIONS, ATTR_HVAC_MODE, ATTR_HVAC_MODES,
|
||||||
ATTR_TARGET_TEMP_HIGH, ATTR_TARGET_TEMP_LOW, CURRENT_HVAC_IDLE,
|
ATTR_TARGET_TEMP_HIGH, ATTR_TARGET_TEMP_LOW, CURRENT_HVAC_IDLE,
|
||||||
DOMAIN as CLIMATE_DOMAIN, HVAC_MODE_AUTO, HVAC_MODE_COOL, HVAC_MODE_DRY,
|
DOMAIN as CLIMATE_DOMAIN, HVAC_MODE_AUTO, HVAC_MODE_COOL, HVAC_MODE_DRY,
|
||||||
HVAC_MODE_FAN_ONLY, HVAC_MODE_HEAT, HVAC_MODE_HEAT_COOL,
|
HVAC_MODE_FAN_ONLY, HVAC_MODE_HEAT, HVAC_MODE_HEAT_COOL, HVAC_MODE_OFF,
|
||||||
SERVICE_SET_FAN_MODE, SERVICE_SET_HVAC_MODE, SERVICE_SET_TEMPERATURE,
|
SERVICE_SET_FAN_MODE, SERVICE_SET_HVAC_MODE, SERVICE_SET_TEMPERATURE,
|
||||||
SUPPORT_FAN_MODE, SUPPORT_TARGET_TEMPERATURE,
|
SUPPORT_FAN_MODE, SUPPORT_TARGET_TEMPERATURE,
|
||||||
SUPPORT_TARGET_TEMPERATURE_RANGE)
|
SUPPORT_TARGET_TEMPERATURE_RANGE)
|
||||||
from homeassistant.components.smartthings import climate
|
from homeassistant.components.smartthings import climate
|
||||||
from homeassistant.components.smartthings.const import DOMAIN
|
from homeassistant.components.smartthings.const import DOMAIN
|
||||||
from homeassistant.const import (
|
from homeassistant.const import (
|
||||||
ATTR_ENTITY_ID, ATTR_SUPPORTED_FEATURES, ATTR_TEMPERATURE, STATE_OFF,
|
ATTR_ENTITY_ID, ATTR_SUPPORTED_FEATURES, ATTR_TEMPERATURE,
|
||||||
STATE_UNKNOWN)
|
SERVICE_TURN_OFF, SERVICE_TURN_ON, STATE_UNKNOWN)
|
||||||
|
|
||||||
from .conftest import setup_platform
|
from .conftest import setup_platform
|
||||||
|
|
||||||
@ -172,7 +172,7 @@ async def test_legacy_thermostat_entity_state(hass, legacy_thermostat):
|
|||||||
assert state.attributes[ATTR_HVAC_ACTIONS] == 'idle'
|
assert state.attributes[ATTR_HVAC_ACTIONS] == 'idle'
|
||||||
assert state.attributes[ATTR_HVAC_MODES] == {
|
assert state.attributes[ATTR_HVAC_MODES] == {
|
||||||
HVAC_MODE_AUTO, HVAC_MODE_COOL, HVAC_MODE_HEAT_COOL, HVAC_MODE_HEAT,
|
HVAC_MODE_AUTO, HVAC_MODE_COOL, HVAC_MODE_HEAT_COOL, HVAC_MODE_HEAT,
|
||||||
STATE_OFF}
|
HVAC_MODE_OFF}
|
||||||
assert state.attributes[ATTR_FAN_MODE] == 'auto'
|
assert state.attributes[ATTR_FAN_MODE] == 'auto'
|
||||||
assert state.attributes[ATTR_FAN_MODES] == ['auto', 'on']
|
assert state.attributes[ATTR_FAN_MODES] == ['auto', 'on']
|
||||||
assert state.attributes[ATTR_TARGET_TEMP_LOW] == 20 # celsius
|
assert state.attributes[ATTR_TARGET_TEMP_LOW] == 20 # celsius
|
||||||
@ -184,12 +184,12 @@ async def test_basic_thermostat_entity_state(hass, basic_thermostat):
|
|||||||
"""Tests the state attributes properly match the thermostat type."""
|
"""Tests the state attributes properly match the thermostat type."""
|
||||||
await setup_platform(hass, CLIMATE_DOMAIN, devices=[basic_thermostat])
|
await setup_platform(hass, CLIMATE_DOMAIN, devices=[basic_thermostat])
|
||||||
state = hass.states.get('climate.basic_thermostat')
|
state = hass.states.get('climate.basic_thermostat')
|
||||||
assert state.state == STATE_OFF
|
assert state.state == HVAC_MODE_OFF
|
||||||
assert state.attributes[ATTR_SUPPORTED_FEATURES] == \
|
assert state.attributes[ATTR_SUPPORTED_FEATURES] == \
|
||||||
SUPPORT_TARGET_TEMPERATURE_RANGE | SUPPORT_TARGET_TEMPERATURE
|
SUPPORT_TARGET_TEMPERATURE_RANGE | SUPPORT_TARGET_TEMPERATURE
|
||||||
assert ATTR_HVAC_ACTIONS not in state.attributes
|
assert ATTR_HVAC_ACTIONS not in state.attributes
|
||||||
assert state.attributes[ATTR_HVAC_MODES] == {
|
assert state.attributes[ATTR_HVAC_MODES] == {
|
||||||
STATE_OFF, HVAC_MODE_HEAT_COOL, HVAC_MODE_HEAT, HVAC_MODE_COOL}
|
HVAC_MODE_OFF, HVAC_MODE_HEAT_COOL, HVAC_MODE_HEAT, HVAC_MODE_COOL}
|
||||||
assert state.attributes[ATTR_CURRENT_TEMPERATURE] == 21.1 # celsius
|
assert state.attributes[ATTR_CURRENT_TEMPERATURE] == 21.1 # celsius
|
||||||
|
|
||||||
|
|
||||||
@ -205,7 +205,7 @@ async def test_thermostat_entity_state(hass, thermostat):
|
|||||||
assert state.attributes[ATTR_HVAC_ACTIONS] == CURRENT_HVAC_IDLE
|
assert state.attributes[ATTR_HVAC_ACTIONS] == CURRENT_HVAC_IDLE
|
||||||
assert state.attributes[ATTR_HVAC_MODES] == {
|
assert state.attributes[ATTR_HVAC_MODES] == {
|
||||||
HVAC_MODE_AUTO, HVAC_MODE_COOL, HVAC_MODE_HEAT, HVAC_MODE_HEAT_COOL,
|
HVAC_MODE_AUTO, HVAC_MODE_COOL, HVAC_MODE_HEAT, HVAC_MODE_HEAT_COOL,
|
||||||
STATE_OFF}
|
HVAC_MODE_OFF}
|
||||||
assert state.attributes[ATTR_FAN_MODE] == 'on'
|
assert state.attributes[ATTR_FAN_MODE] == 'on'
|
||||||
assert state.attributes[ATTR_FAN_MODES] == ['auto', 'on']
|
assert state.attributes[ATTR_FAN_MODES] == ['auto', 'on']
|
||||||
assert state.attributes[ATTR_TEMPERATURE] == 20 # celsius
|
assert state.attributes[ATTR_TEMPERATURE] == 20 # celsius
|
||||||
@ -245,7 +245,7 @@ async def test_air_conditioner_entity_state(hass, air_conditioner):
|
|||||||
SUPPORT_TARGET_TEMPERATURE
|
SUPPORT_TARGET_TEMPERATURE
|
||||||
assert sorted(state.attributes[ATTR_HVAC_MODES]) == [
|
assert sorted(state.attributes[ATTR_HVAC_MODES]) == [
|
||||||
HVAC_MODE_COOL, HVAC_MODE_DRY, HVAC_MODE_FAN_ONLY, HVAC_MODE_HEAT,
|
HVAC_MODE_COOL, HVAC_MODE_DRY, HVAC_MODE_FAN_ONLY, HVAC_MODE_HEAT,
|
||||||
HVAC_MODE_HEAT_COOL]
|
HVAC_MODE_HEAT_COOL, HVAC_MODE_OFF]
|
||||||
assert state.attributes[ATTR_FAN_MODE] == 'medium'
|
assert state.attributes[ATTR_FAN_MODE] == 'medium'
|
||||||
assert sorted(state.attributes[ATTR_FAN_MODES]) == \
|
assert sorted(state.attributes[ATTR_FAN_MODES]) == \
|
||||||
['auto', 'high', 'low', 'medium', 'turbo']
|
['auto', 'high', 'low', 'medium', 'turbo']
|
||||||
@ -277,8 +277,8 @@ async def test_set_fan_mode(hass, thermostat, air_conditioner):
|
|||||||
assert state.attributes[ATTR_FAN_MODE] == 'auto', entity_id
|
assert state.attributes[ATTR_FAN_MODE] == 'auto', entity_id
|
||||||
|
|
||||||
|
|
||||||
async def test_set_operation_mode(hass, thermostat, air_conditioner):
|
async def test_set_hvac_mode(hass, thermostat, air_conditioner):
|
||||||
"""Test the operation mode is set successfully."""
|
"""Test the hvac mode is set successfully."""
|
||||||
await setup_platform(hass, CLIMATE_DOMAIN,
|
await setup_platform(hass, CLIMATE_DOMAIN,
|
||||||
devices=[thermostat, air_conditioner])
|
devices=[thermostat, air_conditioner])
|
||||||
entity_ids = ['climate.thermostat', 'climate.air_conditioner']
|
entity_ids = ['climate.thermostat', 'climate.air_conditioner']
|
||||||
@ -293,6 +293,20 @@ async def test_set_operation_mode(hass, thermostat, air_conditioner):
|
|||||||
assert state.state == HVAC_MODE_COOL, entity_id
|
assert state.state == HVAC_MODE_COOL, entity_id
|
||||||
|
|
||||||
|
|
||||||
|
async def test_ac_set_hvac_mode_off(hass, air_conditioner):
|
||||||
|
"""Test the AC HVAC mode can be turned off set successfully."""
|
||||||
|
await setup_platform(hass, CLIMATE_DOMAIN, devices=[air_conditioner])
|
||||||
|
state = hass.states.get('climate.air_conditioner')
|
||||||
|
assert state.state != HVAC_MODE_OFF
|
||||||
|
await hass.services.async_call(
|
||||||
|
CLIMATE_DOMAIN, SERVICE_SET_HVAC_MODE, {
|
||||||
|
ATTR_ENTITY_ID: 'climate.air_conditioner',
|
||||||
|
ATTR_HVAC_MODE: HVAC_MODE_OFF},
|
||||||
|
blocking=True)
|
||||||
|
state = hass.states.get('climate.air_conditioner')
|
||||||
|
assert state.state == HVAC_MODE_OFF
|
||||||
|
|
||||||
|
|
||||||
async def test_set_temperature_heat_mode(hass, thermostat):
|
async def test_set_temperature_heat_mode(hass, thermostat):
|
||||||
"""Test the temperature is set successfully when in heat mode."""
|
"""Test the temperature is set successfully when in heat mode."""
|
||||||
thermostat.status.thermostat_mode = 'heat'
|
thermostat.status.thermostat_mode = 'heat'
|
||||||
@ -378,6 +392,31 @@ async def test_set_temperature_with_mode(hass, thermostat):
|
|||||||
assert state.state == HVAC_MODE_HEAT_COOL
|
assert state.state == HVAC_MODE_HEAT_COOL
|
||||||
|
|
||||||
|
|
||||||
|
async def test_set_turn_off(hass, air_conditioner):
|
||||||
|
"""Test the a/c is turned off successfully."""
|
||||||
|
await setup_platform(hass, CLIMATE_DOMAIN, devices=[air_conditioner])
|
||||||
|
state = hass.states.get('climate.air_conditioner')
|
||||||
|
assert state.state == HVAC_MODE_HEAT_COOL
|
||||||
|
await hass.services.async_call(
|
||||||
|
CLIMATE_DOMAIN, SERVICE_TURN_OFF,
|
||||||
|
blocking=True)
|
||||||
|
state = hass.states.get('climate.air_conditioner')
|
||||||
|
assert state.state == HVAC_MODE_OFF
|
||||||
|
|
||||||
|
|
||||||
|
async def test_set_turn_on(hass, air_conditioner):
|
||||||
|
"""Test the a/c is turned on successfully."""
|
||||||
|
air_conditioner.status.update_attribute_value(Attribute.switch, 'off')
|
||||||
|
await setup_platform(hass, CLIMATE_DOMAIN, devices=[air_conditioner])
|
||||||
|
state = hass.states.get('climate.air_conditioner')
|
||||||
|
assert state.state == HVAC_MODE_OFF
|
||||||
|
await hass.services.async_call(
|
||||||
|
CLIMATE_DOMAIN, SERVICE_TURN_ON,
|
||||||
|
blocking=True)
|
||||||
|
state = hass.states.get('climate.air_conditioner')
|
||||||
|
assert state.state == HVAC_MODE_HEAT_COOL
|
||||||
|
|
||||||
|
|
||||||
async def test_entity_and_device_attributes(hass, thermostat):
|
async def test_entity_and_device_attributes(hass, thermostat):
|
||||||
"""Test the attributes of the entries are correct."""
|
"""Test the attributes of the entries are correct."""
|
||||||
await setup_platform(hass, CLIMATE_DOMAIN, devices=[thermostat])
|
await setup_platform(hass, CLIMATE_DOMAIN, devices=[thermostat])
|
||||||
|
Loading…
x
Reference in New Issue
Block a user