mirror of
https://github.com/home-assistant/core.git
synced 2025-07-18 18:57:06 +00:00
Add temperature sensor support to google smarthome thermostat device (#24264)
* Add temperature sensor support to google smarthome thermostat device * fix lint for trait_test * Reset temperature unit in tests * Address comment
This commit is contained in:
parent
9ed5b70d01
commit
5085ce8ab1
@ -12,6 +12,7 @@ from homeassistant.components import (
|
|||||||
media_player,
|
media_player,
|
||||||
scene,
|
scene,
|
||||||
script,
|
script,
|
||||||
|
sensor,
|
||||||
switch,
|
switch,
|
||||||
vacuum,
|
vacuum,
|
||||||
)
|
)
|
||||||
@ -108,6 +109,7 @@ DEVICE_CLASS_TO_GOOGLE_TYPES = {
|
|||||||
(binary_sensor.DOMAIN, binary_sensor.DEVICE_CLASS_WINDOW): TYPE_SENSOR,
|
(binary_sensor.DOMAIN, binary_sensor.DEVICE_CLASS_WINDOW): TYPE_SENSOR,
|
||||||
(media_player.DOMAIN, media_player.DEVICE_CLASS_TV): TYPE_TV,
|
(media_player.DOMAIN, media_player.DEVICE_CLASS_TV): TYPE_TV,
|
||||||
(media_player.DOMAIN, media_player.DEVICE_CLASS_SPEAKER): TYPE_SPEAKER,
|
(media_player.DOMAIN, media_player.DEVICE_CLASS_SPEAKER): TYPE_SPEAKER,
|
||||||
|
(sensor.DOMAIN, sensor.DEVICE_CLASS_TEMPERATURE): TYPE_SENSOR,
|
||||||
}
|
}
|
||||||
|
|
||||||
CHALLENGE_ACK_NEEDED = 'ackNeeded'
|
CHALLENGE_ACK_NEEDED = 'ackNeeded'
|
||||||
|
@ -13,6 +13,7 @@ from homeassistant.components import (
|
|||||||
lock,
|
lock,
|
||||||
scene,
|
scene,
|
||||||
script,
|
script,
|
||||||
|
sensor,
|
||||||
switch,
|
switch,
|
||||||
vacuum,
|
vacuum,
|
||||||
)
|
)
|
||||||
@ -550,56 +551,81 @@ class TemperatureSettingTrait(_Trait):
|
|||||||
@staticmethod
|
@staticmethod
|
||||||
def supported(domain, features, device_class):
|
def supported(domain, features, device_class):
|
||||||
"""Test if state is supported."""
|
"""Test if state is supported."""
|
||||||
if domain != climate.DOMAIN:
|
if domain == climate.DOMAIN:
|
||||||
return False
|
|
||||||
|
|
||||||
return features & climate.SUPPORT_OPERATION_MODE
|
return features & climate.SUPPORT_OPERATION_MODE
|
||||||
|
|
||||||
|
return (domain == sensor.DOMAIN
|
||||||
|
and device_class == sensor.DEVICE_CLASS_TEMPERATURE)
|
||||||
|
|
||||||
def sync_attributes(self):
|
def sync_attributes(self):
|
||||||
"""Return temperature point and modes attributes for a sync request."""
|
"""Return temperature point and modes attributes for a sync request."""
|
||||||
|
response = {}
|
||||||
|
attrs = self.state.attributes
|
||||||
|
domain = self.state.domain
|
||||||
|
response['thermostatTemperatureUnit'] = _google_temp_unit(
|
||||||
|
self.hass.config.units.temperature_unit)
|
||||||
|
|
||||||
|
if domain == sensor.DOMAIN:
|
||||||
|
device_class = attrs.get(ATTR_DEVICE_CLASS)
|
||||||
|
if device_class == sensor.DEVICE_CLASS_TEMPERATURE:
|
||||||
|
response["queryOnlyTemperatureSetting"] = True
|
||||||
|
|
||||||
|
elif domain == climate.DOMAIN:
|
||||||
modes = []
|
modes = []
|
||||||
supported = self.state.attributes.get(ATTR_SUPPORTED_FEATURES)
|
supported = attrs.get(ATTR_SUPPORTED_FEATURES)
|
||||||
|
|
||||||
if supported & climate.SUPPORT_ON_OFF != 0:
|
if supported & climate.SUPPORT_ON_OFF != 0:
|
||||||
modes.append(STATE_OFF)
|
modes.append(STATE_OFF)
|
||||||
modes.append(STATE_ON)
|
modes.append(STATE_ON)
|
||||||
|
|
||||||
if supported & climate.SUPPORT_OPERATION_MODE != 0:
|
if supported & climate.SUPPORT_OPERATION_MODE != 0:
|
||||||
for mode in self.state.attributes.get(climate.ATTR_OPERATION_LIST,
|
for mode in attrs.get(climate.ATTR_OPERATION_LIST, []):
|
||||||
[]):
|
|
||||||
google_mode = self.hass_to_google.get(mode)
|
google_mode = self.hass_to_google.get(mode)
|
||||||
if google_mode and google_mode not in modes:
|
if google_mode and google_mode not in modes:
|
||||||
modes.append(google_mode)
|
modes.append(google_mode)
|
||||||
|
response['availableThermostatModes'] = ','.join(modes)
|
||||||
|
|
||||||
return {
|
return response
|
||||||
'availableThermostatModes': ','.join(modes),
|
|
||||||
'thermostatTemperatureUnit': _google_temp_unit(
|
|
||||||
self.hass.config.units.temperature_unit)
|
|
||||||
}
|
|
||||||
|
|
||||||
def query_attributes(self):
|
def query_attributes(self):
|
||||||
"""Return temperature point and modes query attributes."""
|
"""Return temperature point and modes query attributes."""
|
||||||
attrs = self.state.attributes
|
|
||||||
response = {}
|
response = {}
|
||||||
|
attrs = self.state.attributes
|
||||||
|
domain = self.state.domain
|
||||||
|
unit = self.hass.config.units.temperature_unit
|
||||||
|
if domain == sensor.DOMAIN:
|
||||||
|
device_class = attrs.get(ATTR_DEVICE_CLASS)
|
||||||
|
if device_class == sensor.DEVICE_CLASS_TEMPERATURE:
|
||||||
|
current_temp = self.state.state
|
||||||
|
if current_temp is not None:
|
||||||
|
response['thermostatTemperatureAmbient'] = \
|
||||||
|
round(temp_util.convert(
|
||||||
|
float(current_temp),
|
||||||
|
unit,
|
||||||
|
TEMP_CELSIUS
|
||||||
|
), 1)
|
||||||
|
|
||||||
|
elif domain == climate.DOMAIN:
|
||||||
operation = attrs.get(climate.ATTR_OPERATION_MODE)
|
operation = attrs.get(climate.ATTR_OPERATION_MODE)
|
||||||
supported = self.state.attributes.get(ATTR_SUPPORTED_FEATURES)
|
supported = attrs.get(ATTR_SUPPORTED_FEATURES)
|
||||||
|
|
||||||
if (supported & climate.SUPPORT_ON_OFF
|
if (supported & climate.SUPPORT_ON_OFF
|
||||||
and self.state.state == STATE_OFF):
|
and self.state.state == STATE_OFF):
|
||||||
response['thermostatMode'] = 'off'
|
response['thermostatMode'] = 'off'
|
||||||
elif (supported & climate.SUPPORT_OPERATION_MODE and
|
elif (supported & climate.SUPPORT_OPERATION_MODE
|
||||||
operation in self.hass_to_google):
|
and operation in self.hass_to_google):
|
||||||
response['thermostatMode'] = self.hass_to_google[operation]
|
response['thermostatMode'] = self.hass_to_google[operation]
|
||||||
elif supported & climate.SUPPORT_ON_OFF:
|
elif supported & climate.SUPPORT_ON_OFF:
|
||||||
response['thermostatMode'] = 'on'
|
response['thermostatMode'] = 'on'
|
||||||
|
|
||||||
unit = self.hass.config.units.temperature_unit
|
|
||||||
|
|
||||||
current_temp = attrs.get(climate.ATTR_CURRENT_TEMPERATURE)
|
current_temp = attrs.get(climate.ATTR_CURRENT_TEMPERATURE)
|
||||||
if current_temp is not None:
|
if current_temp is not None:
|
||||||
response['thermostatTemperatureAmbient'] = \
|
response['thermostatTemperatureAmbient'] = \
|
||||||
round(temp_util.convert(current_temp, unit, TEMP_CELSIUS), 1)
|
round(temp_util.convert(
|
||||||
|
current_temp,
|
||||||
|
unit,
|
||||||
|
TEMP_CELSIUS
|
||||||
|
), 1)
|
||||||
|
|
||||||
current_humidity = attrs.get(climate.ATTR_CURRENT_HUMIDITY)
|
current_humidity = attrs.get(climate.ATTR_CURRENT_HUMIDITY)
|
||||||
if current_humidity is not None:
|
if current_humidity is not None:
|
||||||
@ -620,9 +646,15 @@ class TemperatureSettingTrait(_Trait):
|
|||||||
target_temp = attrs.get(ATTR_TEMPERATURE)
|
target_temp = attrs.get(ATTR_TEMPERATURE)
|
||||||
if target_temp is not None:
|
if target_temp is not None:
|
||||||
target_temp = round(
|
target_temp = round(
|
||||||
temp_util.convert(target_temp, unit, TEMP_CELSIUS), 1)
|
temp_util.convert(
|
||||||
response['thermostatTemperatureSetpointHigh'] = target_temp
|
target_temp,
|
||||||
response['thermostatTemperatureSetpointLow'] = target_temp
|
unit,
|
||||||
|
TEMP_CELSIUS
|
||||||
|
), 1)
|
||||||
|
response['thermostatTemperatureSetpointHigh'] = \
|
||||||
|
target_temp
|
||||||
|
response['thermostatTemperatureSetpointLow'] = \
|
||||||
|
target_temp
|
||||||
else:
|
else:
|
||||||
target_temp = attrs.get(ATTR_TEMPERATURE)
|
target_temp = attrs.get(ATTR_TEMPERATURE)
|
||||||
if target_temp is not None:
|
if target_temp is not None:
|
||||||
@ -633,6 +665,12 @@ class TemperatureSettingTrait(_Trait):
|
|||||||
|
|
||||||
async def execute(self, command, data, params, challenge):
|
async def execute(self, command, data, params, challenge):
|
||||||
"""Execute a temperature point or mode command."""
|
"""Execute a temperature point or mode command."""
|
||||||
|
domain = self.state.domain
|
||||||
|
if domain == sensor.DOMAIN:
|
||||||
|
raise SmartHomeError(
|
||||||
|
ERR_NOT_SUPPORTED,
|
||||||
|
'Execute is not supported by sensor')
|
||||||
|
|
||||||
# All sent in temperatures are always in Celsius
|
# All sent in temperatures are always in Celsius
|
||||||
unit = self.hass.config.units.temperature_unit
|
unit = self.hass.config.units.temperature_unit
|
||||||
min_temp = self.state.attributes[climate.ATTR_MIN_TEMP]
|
min_temp = self.state.attributes[climate.ATTR_MIN_TEMP]
|
||||||
@ -687,8 +725,8 @@ class TemperatureSettingTrait(_Trait):
|
|||||||
ATTR_ENTITY_ID: self.state.entity_id,
|
ATTR_ENTITY_ID: self.state.entity_id,
|
||||||
}
|
}
|
||||||
|
|
||||||
if(supported & climate.SUPPORT_TARGET_TEMPERATURE_HIGH and
|
if(supported & climate.SUPPORT_TARGET_TEMPERATURE_HIGH
|
||||||
supported & climate.SUPPORT_TARGET_TEMPERATURE_LOW):
|
and supported & climate.SUPPORT_TARGET_TEMPERATURE_LOW):
|
||||||
svc_data[climate.ATTR_TARGET_TEMP_HIGH] = temp_high
|
svc_data[climate.ATTR_TARGET_TEMP_HIGH] = temp_high
|
||||||
svc_data[climate.ATTR_TARGET_TEMP_LOW] = temp_low
|
svc_data[climate.ATTR_TARGET_TEMP_LOW] = temp_low
|
||||||
else:
|
else:
|
||||||
|
@ -14,6 +14,7 @@ from homeassistant.components import (
|
|||||||
media_player,
|
media_player,
|
||||||
scene,
|
scene,
|
||||||
script,
|
script,
|
||||||
|
sensor,
|
||||||
switch,
|
switch,
|
||||||
vacuum,
|
vacuum,
|
||||||
group,
|
group,
|
||||||
@ -1380,3 +1381,35 @@ async def test_volume_media_player_relative(hass):
|
|||||||
ATTR_ENTITY_ID: 'media_player.bla',
|
ATTR_ENTITY_ID: 'media_player.bla',
|
||||||
media_player.ATTR_MEDIA_VOLUME_LEVEL: .5
|
media_player.ATTR_MEDIA_VOLUME_LEVEL: .5
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
async def test_temperature_setting_sensor(hass):
|
||||||
|
"""Test TemperatureSetting trait support for temperature sensor."""
|
||||||
|
assert helpers.get_google_type(sensor.DOMAIN,
|
||||||
|
sensor.DEVICE_CLASS_TEMPERATURE) is not None
|
||||||
|
assert not trait.TemperatureSettingTrait.supported(
|
||||||
|
sensor.DOMAIN,
|
||||||
|
0,
|
||||||
|
sensor.DEVICE_CLASS_HUMIDITY
|
||||||
|
)
|
||||||
|
assert trait.TemperatureSettingTrait.supported(
|
||||||
|
sensor.DOMAIN,
|
||||||
|
0,
|
||||||
|
sensor.DEVICE_CLASS_TEMPERATURE
|
||||||
|
)
|
||||||
|
|
||||||
|
hass.config.units.temperature_unit = TEMP_FAHRENHEIT
|
||||||
|
|
||||||
|
trt = trait.TemperatureSettingTrait(hass, State('sensor.test', "70", {
|
||||||
|
ATTR_DEVICE_CLASS: sensor.DEVICE_CLASS_TEMPERATURE,
|
||||||
|
}), BASIC_CONFIG)
|
||||||
|
|
||||||
|
assert trt.sync_attributes() == {
|
||||||
|
'queryOnlyTemperatureSetting': True,
|
||||||
|
'thermostatTemperatureUnit': 'F',
|
||||||
|
}
|
||||||
|
|
||||||
|
assert trt.query_attributes() == {
|
||||||
|
'thermostatTemperatureAmbient': 21.1
|
||||||
|
}
|
||||||
|
hass.config.units.temperature_unit = TEMP_CELSIUS
|
||||||
|
Loading…
x
Reference in New Issue
Block a user