def test_convert_invalid_unit(): """Test exception is thrown for invalid units.""" with pytest.raises(ValueError): temperature_util.convert(5, INVALID_SYMBOL, VALID_SYMBOL) with pytest.raises(ValueError): temperature_util.convert(5, VALID_SYMBOL, INVALID_SYMBOL)
async def execute(self, command, params): """Execute a temperature point or mode command.""" # All sent in temperatures are always in Celsius unit = self.hass.config.units.temperature_unit min_temp = self.state.attributes[climate.ATTR_MIN_TEMP] max_temp = self.state.attributes[climate.ATTR_MAX_TEMP] if command == COMMAND_THERMOSTAT_TEMPERATURE_SETPOINT: temp = temp_util.convert(params['thermostatTemperatureSetpoint'], TEMP_CELSIUS, unit) if temp < min_temp or temp > max_temp: raise SmartHomeError( ERR_VALUE_OUT_OF_RANGE, "Temperature should be between {} and {}".format(min_temp, max_temp)) await self.hass.services.async_call( climate.DOMAIN, climate.SERVICE_SET_TEMPERATURE, { ATTR_ENTITY_ID: self.state.entity_id, climate.ATTR_TEMPERATURE: temp }, blocking=True) elif command == COMMAND_THERMOSTAT_TEMPERATURE_SET_RANGE: temp_high = temp_util.convert( params['thermostatTemperatureSetpointHigh'], TEMP_CELSIUS, unit) if temp_high < min_temp or temp_high > max_temp: raise SmartHomeError( ERR_VALUE_OUT_OF_RANGE, "Upper bound for temperature range should be between " "{} and {}".format(min_temp, max_temp)) temp_low = temp_util.convert( params['thermostatTemperatureSetpointLow'], TEMP_CELSIUS, unit) if temp_low < min_temp or temp_low > max_temp: raise SmartHomeError( ERR_VALUE_OUT_OF_RANGE, "Lower bound for temperature range should be between " "{} and {}".format(min_temp, max_temp)) await self.hass.services.async_call( climate.DOMAIN, climate.SERVICE_SET_TEMPERATURE, { ATTR_ENTITY_ID: self.state.entity_id, climate.ATTR_TARGET_TEMP_HIGH: temp_high, climate.ATTR_TARGET_TEMP_LOW: temp_low, }, blocking=True) elif command == COMMAND_THERMOSTAT_SET_MODE: await self.hass.services.async_call( climate.DOMAIN, climate.SERVICE_SET_OPERATION_MODE, { ATTR_ENTITY_ID: self.state.entity_id, climate.ATTR_OPERATION_MODE: self.google_to_hass[params['thermostatMode']], }, blocking=True)
def query_attributes(self): """Return temperature point and modes query attributes.""" attrs = self.state.attributes response = {} operation = attrs.get(climate.ATTR_OPERATION_MODE) supported = self.state.attributes.get(ATTR_SUPPORTED_FEATURES) if (supported & climate.SUPPORT_ON_OFF and self.state.state == STATE_OFF): response['thermostatMode'] = 'off' elif (supported & climate.SUPPORT_OPERATION_MODE and operation in self.hass_to_google): response['thermostatMode'] = self.hass_to_google[operation] elif supported & climate.SUPPORT_ON_OFF: response['thermostatMode'] = 'on' unit = self.hass.config.units.temperature_unit current_temp = attrs.get(climate.ATTR_CURRENT_TEMPERATURE) if current_temp is not None: response['thermostatTemperatureAmbient'] = \ round(temp_util.convert(current_temp, unit, TEMP_CELSIUS), 1) current_humidity = attrs.get(climate.ATTR_CURRENT_HUMIDITY) if current_humidity is not None: response['thermostatHumidityAmbient'] = current_humidity if operation == climate.STATE_AUTO: if (supported & climate.SUPPORT_TARGET_TEMPERATURE_HIGH and supported & climate.SUPPORT_TARGET_TEMPERATURE_LOW): response['thermostatTemperatureSetpointHigh'] = \ round(temp_util.convert( attrs[climate.ATTR_TARGET_TEMP_HIGH], unit, TEMP_CELSIUS), 1) response['thermostatTemperatureSetpointLow'] = \ round(temp_util.convert( attrs[climate.ATTR_TARGET_TEMP_LOW], unit, TEMP_CELSIUS), 1) else: target_temp = attrs.get(ATTR_TEMPERATURE) if target_temp is not None: target_temp = round( temp_util.convert(target_temp, unit, TEMP_CELSIUS), 1) response['thermostatTemperatureSetpointHigh'] = target_temp response['thermostatTemperatureSetpointLow'] = target_temp else: target_temp = attrs.get(ATTR_TEMPERATURE) if target_temp is not None: response['thermostatTemperatureSetpoint'] = round( temp_util.convert(target_temp, unit, TEMP_CELSIUS), 1) return response
def test_convert_from_celsius(): """Test conversion from C to other units.""" celsius = 100 assert temperature_util.convert(celsius, TEMP_CELSIUS, TEMP_FAHRENHEIT) == pytest.approx(212.0) assert temperature_util.convert(celsius, TEMP_CELSIUS, TEMP_KELVIN) == pytest.approx(373.15) # Interval assert temperature_util.convert(celsius, TEMP_CELSIUS, TEMP_FAHRENHEIT, True) == pytest.approx(180.0) assert temperature_util.convert(celsius, TEMP_CELSIUS, TEMP_KELVIN, True) == pytest.approx(100)
def test_convert_from_kelvin(): """Test conversion from K to other units.""" kelvin = 100 assert temperature_util.convert(kelvin, TEMP_KELVIN, TEMP_CELSIUS) == pytest.approx(-173.15) assert temperature_util.convert( kelvin, TEMP_KELVIN, TEMP_FAHRENHEIT) == pytest.approx(-279.66999999999996) # Interval assert temperature_util.convert(kelvin, TEMP_KELVIN, TEMP_FAHRENHEIT, True) == pytest.approx(180.0) assert temperature_util.convert(kelvin, TEMP_KELVIN, TEMP_KELVIN, True) == pytest.approx(100)
def test_convert_from_fahrenheit(): """Test conversion from F to other units.""" fahrenheit = 100 assert temperature_util.convert( fahrenheit, TEMP_FAHRENHEIT, TEMP_CELSIUS) == pytest.approx(37.77777777777778) assert temperature_util.convert( fahrenheit, TEMP_FAHRENHEIT, TEMP_KELVIN) == pytest.approx(310.92777777777775) # Interval assert temperature_util.convert(fahrenheit, TEMP_FAHRENHEIT, TEMP_CELSIUS, True) == pytest.approx(55.55555555555556) assert temperature_util.convert(fahrenheit, TEMP_FAHRENHEIT, TEMP_KELVIN, True) == pytest.approx(55.55555555555556)
def temperature(self, temperature: float, from_unit: str) -> float: """Convert the given temperature to this unit system.""" if not isinstance(temperature, Number): raise TypeError(f"{temperature!s} is not a numeric value.") return temperature_util.convert(temperature, from_unit, self.temperature_unit)
def temperature(self, temperature: float, from_unit: str) -> float: """Convert the given temperature to this unit system.""" if not isinstance(temperature, Number): raise TypeError( '{} is not a numeric value.'.format(str(temperature))) return temperature_util.convert(temperature, from_unit, self.temperature_unit)
def temperature(self: object, temperature: float, from_unit: str) -> float: """Convert the given temperature to this unit system.""" if not isinstance(temperature, Number): raise TypeError('{} is not a numeric value.'.format( str(temperature))) return temperature_util.convert(temperature, from_unit, self.temperature_unit)
def create_vacation(self, service_data): """Create a vacation with user-specified parameters.""" vacation_name = service_data[ATTR_VACATION_NAME] cool_temp = convert( service_data[ATTR_COOL_TEMP], self.hass.config.units.temperature_unit, TEMP_FAHRENHEIT, ) heat_temp = convert( service_data[ATTR_HEAT_TEMP], self.hass.config.units.temperature_unit, TEMP_FAHRENHEIT, ) start_date = service_data.get(ATTR_START_DATE) start_time = service_data.get(ATTR_START_TIME) end_date = service_data.get(ATTR_END_DATE) end_time = service_data.get(ATTR_END_TIME) fan_mode = service_data[ATTR_FAN_MODE] fan_min_on_time = service_data[ATTR_FAN_MIN_ON_TIME] kwargs = { key: value for key, value in { "start_date": start_date, "start_time": start_time, "end_date": end_date, "end_time": end_time, "fan_mode": fan_mode, "fan_min_on_time": fan_min_on_time, }.items() if value is not None } _LOGGER.debug( "Creating a vacation on thermostat %s with name %s, cool temp %s, heat temp %s, " "and the following other parameters: %s", self.name, vacation_name, cool_temp, heat_temp, kwargs, ) self.data.ecobee.create_vacation( self.thermostat_index, vacation_name, cool_temp, heat_temp, **kwargs )
def temperature(self, temperature: float, from_unit: str) -> float: """Convert the given temperature to this unit system.""" if not isinstance(temperature, Number): raise TypeError("{} is not a numeric value.".format(str(temperature))) # type ignore: https://github.com/python/mypy/issues/7207 return temperature_util.convert( # type: ignore temperature, from_unit, self.temperature_unit )
def temperature_set_service(service): """Set temperature on the target thermostats.""" target_thermostats = component.extract_from_service(service) temperature = service.data[ATTR_TEMPERATURE] for thermostat in target_thermostats: converted_temperature = convert( temperature, hass.config.units.temperature_unit, thermostat.unit_of_measurement) thermostat.set_temperature(converted_temperature) thermostat.update_ha_state(True)
def temperature_set_service(service): """Set temperature on the target thermostats.""" target_thermostats = component.extract_from_service(service) temperature = service.data[ATTR_TEMPERATURE] for thermostat in target_thermostats: converted_temperature = convert(temperature, hass.config.units.temperature_unit, thermostat.unit_of_measurement) thermostat.set_temperature(converted_temperature) thermostat.update_ha_state(True)
def query_attributes(self): """Return temperature point and modes query attributes.""" attrs = self.state.attributes response = {} operation = attrs.get(climate.ATTR_OPERATION_MODE) if operation is not None and operation in self.hass_to_google: response['thermostatMode'] = self.hass_to_google[operation] unit = self.hass.config.units.temperature_unit current_temp = attrs.get(climate.ATTR_CURRENT_TEMPERATURE) if current_temp is not None: response['thermostatTemperatureAmbient'] = \ round(temp_util.convert(current_temp, unit, TEMP_CELSIUS), 1) current_humidity = attrs.get(climate.ATTR_CURRENT_HUMIDITY) if current_humidity is not None: response['thermostatHumidityAmbient'] = current_humidity if (operation == climate.STATE_AUTO and climate.ATTR_TARGET_TEMP_HIGH in attrs and climate.ATTR_TARGET_TEMP_LOW in attrs): response['thermostatTemperatureSetpointHigh'] = \ round(temp_util.convert(attrs[climate.ATTR_TARGET_TEMP_HIGH], unit, TEMP_CELSIUS), 1) response['thermostatTemperatureSetpointLow'] = \ round(temp_util.convert(attrs[climate.ATTR_TARGET_TEMP_LOW], unit, TEMP_CELSIUS), 1) else: target_temp = attrs.get(climate.ATTR_TEMPERATURE) if target_temp is not None: response['thermostatTemperatureSetpoint'] = round( temp_util.convert(target_temp, unit, TEMP_CELSIUS), 1) return response
async def async_set_smart_mode( self, auto_comfort: str = None, cool_temp: float = None, cool_min_speed: int = None, cool_max_speed: int = None, ) -> None: """Configure smart_mode settings""" if auto_comfort is not None: self._device.fan_smartmode = auto_comfort.upper() if cool_temp is not None: self._device.fan_cooltemp = convert( cool_temp, self.hass.config.units.temperature_unit, TEMP_CELSIUS, ) if cool_min_speed is not None: self._device.fan_coolminspeed = cool_min_speed if cool_max_speed is not None: self._device.fan_coolmaxspeed = cool_max_speed
def max_temp(self): """Return the maximum temperature - 30.5 means on.""" return convert(30.5, TEMP_CELSIUS, self.unit_of_measurement)
def min_temp(self): """Return the minimum temperature - 4.5 means off.""" return convert(4.5, TEMP_CELSIUS, self.unit_of_measurement)
def temperature_to_homekit(temperature: float | int, unit: str) -> float: """Convert temperature to Celsius for HomeKit.""" return round(temp_util.convert(temperature, unit, TEMP_CELSIUS), 1)
def temperature_to_states(temperature: float | int, unit: str) -> float: """Convert temperature back from Celsius to Home Assistant unit.""" return round(temp_util.convert(temperature, TEMP_CELSIUS, unit) * 2) / 2
STATISTICS_BAKERY = "recorder_statistics_bakery" STATISTICS_META_BAKERY = "recorder_statistics_meta_bakery" STATISTICS_SHORT_TERM_BAKERY = "recorder_statistics_short_term_bakery" # Convert pressure and temperature statistics from the native unit used for statistics # to the units configured by the user UNIT_CONVERSIONS = { PRESSURE_PA: lambda x, units: pressure_util.convert( x, PRESSURE_PA, units.pressure_unit ) if x is not None else None, TEMP_CELSIUS: lambda x, units: temperature_util.convert( x, TEMP_CELSIUS, units.temperature_unit ) if x is not None else None, VOLUME_CUBIC_METERS: lambda x, units: volume_util.convert( x, VOLUME_CUBIC_METERS, _configured_unit(VOLUME_CUBIC_METERS, units) ) if x is not None else None, } _LOGGER = logging.getLogger(__name__) def split_statistic_id(entity_id: str) -> list[str]: """Split a state entity ID into domain and object ID."""
def max_temp(self): """Return the maximum temperature.""" return convert(self._thermostat.max_temp, TEMP_CELSIUS, self.unit_of_measurement)
def temperature_to_homekit(temperature, unit): """Convert temperature to Celsius for HomeKit.""" return round(temp_util.convert(temperature, unit, TEMP_CELSIUS), 1)
def query_attributes(self): """Return temperature point and modes query attributes.""" 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 = self.state.state preset = attrs.get(climate.ATTR_PRESET_MODE) supported = attrs.get(ATTR_SUPPORTED_FEATURES, 0) if preset in self.preset_to_google: response["thermostatMode"] = self.preset_to_google[preset] else: response["thermostatMode"] = self.hvac_to_google.get(operation) current_temp = attrs.get(climate.ATTR_CURRENT_TEMPERATURE) if current_temp is not None: response["thermostatTemperatureAmbient"] = round( temp_util.convert(current_temp, unit, TEMP_CELSIUS), 1) current_humidity = attrs.get(climate.ATTR_CURRENT_HUMIDITY) if current_humidity is not None: response["thermostatHumidityAmbient"] = current_humidity if operation in (climate.HVAC_MODE_AUTO, climate.HVAC_MODE_HEAT_COOL): if supported & climate.SUPPORT_TARGET_TEMPERATURE_RANGE: response["thermostatTemperatureSetpointHigh"] = round( temp_util.convert(attrs[climate.ATTR_TARGET_TEMP_HIGH], unit, TEMP_CELSIUS), 1, ) response["thermostatTemperatureSetpointLow"] = round( temp_util.convert(attrs[climate.ATTR_TARGET_TEMP_LOW], unit, TEMP_CELSIUS), 1, ) else: target_temp = attrs.get(ATTR_TEMPERATURE) if target_temp is not None: target_temp = round( temp_util.convert(target_temp, unit, TEMP_CELSIUS), 1) response[ "thermostatTemperatureSetpointHigh"] = target_temp response[ "thermostatTemperatureSetpointLow"] = target_temp else: target_temp = attrs.get(ATTR_TEMPERATURE) if target_temp is not None: response["thermostatTemperatureSetpoint"] = round( temp_util.convert(target_temp, unit, TEMP_CELSIUS), 1) return response
def temperature_to_states(temperature, unit): """Convert temperature back from Celsius to Home Assistant unit.""" return round(temp_util.convert(temperature, TEMP_CELSIUS, unit), 1)
def test_convert_nonnumeric_value(): """Test exception is thrown for nonnumeric type.""" with pytest.raises(TypeError): temperature_util.convert("a", TEMP_CELSIUS, TEMP_FAHRENHEIT)
StatisticsMeta.id, StatisticsMeta.statistic_id, ] STATISTICS_BAKERY = "recorder_statistics_bakery" STATISTICS_META_BAKERY = "recorder_statistics_meta_bakery" STATISTICS_SHORT_TERM_BAKERY = "recorder_statistics_short_term_bakery" # Convert pressure and temperature statistics from the native unit used for statistics # to the units configured by the user UNIT_CONVERSIONS = { PRESSURE_PA: lambda x, units: pressure_util.convert(x, PRESSURE_PA, units.pressure_unit) if x is not None else None, TEMP_CELSIUS: lambda x, units: temperature_util.convert( x, TEMP_CELSIUS, units.temperature_unit) if x is not None else None, VOLUME_CUBIC_METERS: lambda x, units: volume_util.convert( x, VOLUME_CUBIC_METERS, _configured_unit(VOLUME_CUBIC_METERS, units)) if x is not None else None, } _LOGGER = logging.getLogger(__name__) def split_statistic_id(entity_id: str) -> list[str]: """Split a state entity ID into domain and object ID.""" return entity_id.split(":", 1) VALID_STATISTIC_ID = re.compile(
async def execute(self, command, data, params, challenge): """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 unit = self.hass.config.units.temperature_unit min_temp = self.state.attributes[climate.ATTR_MIN_TEMP] max_temp = self.state.attributes[climate.ATTR_MAX_TEMP] if command == COMMAND_THERMOSTAT_TEMPERATURE_SETPOINT: temp = temp_util.convert(params["thermostatTemperatureSetpoint"], TEMP_CELSIUS, unit) if unit == TEMP_FAHRENHEIT: temp = round(temp) if temp < min_temp or temp > max_temp: raise SmartHomeError( ERR_VALUE_OUT_OF_RANGE, "Temperature should be between {} and {}".format( min_temp, max_temp), ) await self.hass.services.async_call( climate.DOMAIN, climate.SERVICE_SET_TEMPERATURE, { ATTR_ENTITY_ID: self.state.entity_id, ATTR_TEMPERATURE: temp }, blocking=True, context=data.context, ) elif command == COMMAND_THERMOSTAT_TEMPERATURE_SET_RANGE: temp_high = temp_util.convert( params["thermostatTemperatureSetpointHigh"], TEMP_CELSIUS, unit) if unit == TEMP_FAHRENHEIT: temp_high = round(temp_high) if temp_high < min_temp or temp_high > max_temp: raise SmartHomeError( ERR_VALUE_OUT_OF_RANGE, "Upper bound for temperature range should be between " "{} and {}".format(min_temp, max_temp), ) temp_low = temp_util.convert( params["thermostatTemperatureSetpointLow"], TEMP_CELSIUS, unit) if unit == TEMP_FAHRENHEIT: temp_low = round(temp_low) if temp_low < min_temp or temp_low > max_temp: raise SmartHomeError( ERR_VALUE_OUT_OF_RANGE, "Lower bound for temperature range should be between " "{} and {}".format(min_temp, max_temp), ) supported = self.state.attributes.get(ATTR_SUPPORTED_FEATURES) svc_data = {ATTR_ENTITY_ID: self.state.entity_id} if supported & climate.SUPPORT_TARGET_TEMPERATURE_RANGE: svc_data[climate.ATTR_TARGET_TEMP_HIGH] = temp_high svc_data[climate.ATTR_TARGET_TEMP_LOW] = temp_low else: svc_data[ATTR_TEMPERATURE] = (temp_high + temp_low) / 2 await self.hass.services.async_call( climate.DOMAIN, climate.SERVICE_SET_TEMPERATURE, svc_data, blocking=True, context=data.context, ) elif command == COMMAND_THERMOSTAT_SET_MODE: target_mode = params["thermostatMode"] supported = self.state.attributes.get(ATTR_SUPPORTED_FEATURES) if target_mode == "on": await self.hass.services.async_call( climate.DOMAIN, SERVICE_TURN_ON, {ATTR_ENTITY_ID: self.state.entity_id}, blocking=True, context=data.context, ) return if target_mode == "off": await self.hass.services.async_call( climate.DOMAIN, SERVICE_TURN_OFF, {ATTR_ENTITY_ID: self.state.entity_id}, blocking=True, context=data.context, ) return if target_mode in self.google_to_preset: await self.hass.services.async_call( climate.DOMAIN, climate.SERVICE_SET_PRESET_MODE, { climate.ATTR_PRESET_MODE: self.google_to_preset[target_mode], ATTR_ENTITY_ID: self.state.entity_id, }, blocking=True, context=data.context, ) return await self.hass.services.async_call( climate.DOMAIN, climate.SERVICE_SET_HVAC_MODE, { ATTR_ENTITY_ID: self.state.entity_id, climate.ATTR_HVAC_MODE: self.google_to_hvac[target_mode], }, blocking=True, context=data.context, )
async def execute(self, command, data, params): """Execute a temperature point or mode command.""" # All sent in temperatures are always in Celsius unit = self.hass.config.units.temperature_unit min_temp = self.state.attributes[climate.ATTR_MIN_TEMP] max_temp = self.state.attributes[climate.ATTR_MAX_TEMP] if command == COMMAND_THERMOSTAT_TEMPERATURE_SETPOINT: temp = temp_util.convert( params['thermostatTemperatureSetpoint'], TEMP_CELSIUS, unit) if unit == TEMP_FAHRENHEIT: temp = round(temp) if temp < min_temp or temp > max_temp: raise SmartHomeError( ERR_VALUE_OUT_OF_RANGE, "Temperature should be between {} and {}".format(min_temp, max_temp)) await self.hass.services.async_call( climate.DOMAIN, climate.SERVICE_SET_TEMPERATURE, { ATTR_ENTITY_ID: self.state.entity_id, ATTR_TEMPERATURE: temp }, blocking=True, context=data.context) elif command == COMMAND_THERMOSTAT_TEMPERATURE_SET_RANGE: temp_high = temp_util.convert( params['thermostatTemperatureSetpointHigh'], TEMP_CELSIUS, unit) if unit == TEMP_FAHRENHEIT: temp_high = round(temp_high) if temp_high < min_temp or temp_high > max_temp: raise SmartHomeError( ERR_VALUE_OUT_OF_RANGE, "Upper bound for temperature range should be between " "{} and {}".format(min_temp, max_temp)) temp_low = temp_util.convert( params['thermostatTemperatureSetpointLow'], TEMP_CELSIUS, unit) if unit == TEMP_FAHRENHEIT: temp_low = round(temp_low) if temp_low < min_temp or temp_low > max_temp: raise SmartHomeError( ERR_VALUE_OUT_OF_RANGE, "Lower bound for temperature range should be between " "{} and {}".format(min_temp, max_temp)) supported = self.state.attributes.get(ATTR_SUPPORTED_FEATURES) svc_data = { ATTR_ENTITY_ID: self.state.entity_id, } if(supported & climate.SUPPORT_TARGET_TEMPERATURE_HIGH and supported & climate.SUPPORT_TARGET_TEMPERATURE_LOW): svc_data[climate.ATTR_TARGET_TEMP_HIGH] = temp_high svc_data[climate.ATTR_TARGET_TEMP_LOW] = temp_low else: svc_data[ATTR_TEMPERATURE] = (temp_high + temp_low) / 2 await self.hass.services.async_call( climate.DOMAIN, climate.SERVICE_SET_TEMPERATURE, svc_data, blocking=True, context=data.context) elif command == COMMAND_THERMOSTAT_SET_MODE: target_mode = params['thermostatMode'] supported = self.state.attributes.get(ATTR_SUPPORTED_FEATURES) if (target_mode in [STATE_ON, STATE_OFF] and supported & climate.SUPPORT_ON_OFF): await self.hass.services.async_call( climate.DOMAIN, (SERVICE_TURN_ON if target_mode == STATE_ON else SERVICE_TURN_OFF), {ATTR_ENTITY_ID: self.state.entity_id}, blocking=True, context=data.context) elif supported & climate.SUPPORT_OPERATION_MODE: await self.hass.services.async_call( climate.DOMAIN, climate.SERVICE_SET_OPERATION_MODE, { ATTR_ENTITY_ID: self.state.entity_id, climate.ATTR_OPERATION_MODE: self.google_to_hass[target_mode], }, blocking=True, context=data.context)
def temperature_to_states(temperature, unit): """Convert temperature back from Celsius to Safegate Pro unit.""" return round(temp_util.convert(temperature, TEMP_CELSIUS, unit) * 2) / 2
def test_convert_same_unit(): """Test conversion from any unit to same unit.""" assert temperature_util.convert(2, TEMP_CELSIUS, TEMP_CELSIUS) == 2 assert temperature_util.convert(3, TEMP_FAHRENHEIT, TEMP_FAHRENHEIT) == 3 assert temperature_util.convert(4, TEMP_KELVIN, TEMP_KELVIN) == 4
async def execute(self, command, data, params): """Execute a temperature point or mode command.""" # All sent in temperatures are always in Celsius unit = self.hass.config.units.temperature_unit min_temp = self.state.attributes[climate.ATTR_MIN_TEMP] max_temp = self.state.attributes[climate.ATTR_MAX_TEMP] if command == COMMAND_THERMOSTAT_TEMPERATURE_SETPOINT: temp = temp_util.convert(params['thermostatTemperatureSetpoint'], TEMP_CELSIUS, unit) if unit == TEMP_FAHRENHEIT: temp = round(temp) if temp < min_temp or temp > max_temp: raise SmartHomeError( ERR_VALUE_OUT_OF_RANGE, "Temperature should be between {} and {}".format( min_temp, max_temp)) await self.hass.services.async_call( climate.DOMAIN, climate.SERVICE_SET_TEMPERATURE, { ATTR_ENTITY_ID: self.state.entity_id, ATTR_TEMPERATURE: temp }, blocking=True, context=data.context) elif command == COMMAND_THERMOSTAT_TEMPERATURE_SET_RANGE: temp_high = temp_util.convert( params['thermostatTemperatureSetpointHigh'], TEMP_CELSIUS, unit) if unit == TEMP_FAHRENHEIT: temp_high = round(temp_high) if temp_high < min_temp or temp_high > max_temp: raise SmartHomeError( ERR_VALUE_OUT_OF_RANGE, "Upper bound for temperature range should be between " "{} and {}".format(min_temp, max_temp)) temp_low = temp_util.convert( params['thermostatTemperatureSetpointLow'], TEMP_CELSIUS, unit) if unit == TEMP_FAHRENHEIT: temp_low = round(temp_low) if temp_low < min_temp or temp_low > max_temp: raise SmartHomeError( ERR_VALUE_OUT_OF_RANGE, "Lower bound for temperature range should be between " "{} and {}".format(min_temp, max_temp)) supported = self.state.attributes.get(ATTR_SUPPORTED_FEATURES) svc_data = { ATTR_ENTITY_ID: self.state.entity_id, } if (supported & climate.SUPPORT_TARGET_TEMPERATURE_HIGH and supported & climate.SUPPORT_TARGET_TEMPERATURE_LOW): svc_data[climate.ATTR_TARGET_TEMP_HIGH] = temp_high svc_data[climate.ATTR_TARGET_TEMP_LOW] = temp_low else: svc_data[ATTR_TEMPERATURE] = (temp_high + temp_low) / 2 await self.hass.services.async_call( climate.DOMAIN, climate.SERVICE_SET_TEMPERATURE, svc_data, blocking=True, context=data.context) elif command == COMMAND_THERMOSTAT_SET_MODE: target_mode = params['thermostatMode'] supported = self.state.attributes.get(ATTR_SUPPORTED_FEATURES) if (target_mode in [STATE_ON, STATE_OFF] and supported & climate.SUPPORT_ON_OFF): await self.hass.services.async_call( climate.DOMAIN, (SERVICE_TURN_ON if target_mode == STATE_ON else SERVICE_TURN_OFF), {ATTR_ENTITY_ID: self.state.entity_id}, blocking=True, context=data.context) elif supported & climate.SUPPORT_OPERATION_MODE: await self.hass.services.async_call( climate.DOMAIN, climate.SERVICE_SET_OPERATION_MODE, { ATTR_ENTITY_ID: self.state.entity_id, climate.ATTR_OPERATION_MODE: self.google_to_hass[target_mode], }, blocking=True, context=data.context)
async def execute(self, command, data, params, challenge): """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 unit = self.hass.config.units.temperature_unit min_temp = self.state.attributes[climate.ATTR_MIN_TEMP] max_temp = self.state.attributes[climate.ATTR_MAX_TEMP] if command == COMMAND_THERMOSTAT_TEMPERATURE_SETPOINT: temp = temp_util.convert(params['thermostatTemperatureSetpoint'], TEMP_CELSIUS, unit) if unit == TEMP_FAHRENHEIT: temp = round(temp) if temp < min_temp or temp > max_temp: raise SmartHomeError( ERR_VALUE_OUT_OF_RANGE, "Temperature should be between {} and {}".format( min_temp, max_temp)) await self.hass.services.async_call( climate.DOMAIN, climate.SERVICE_SET_TEMPERATURE, { ATTR_ENTITY_ID: self.state.entity_id, ATTR_TEMPERATURE: temp }, blocking=True, context=data.context) elif command == COMMAND_THERMOSTAT_TEMPERATURE_SET_RANGE: temp_high = temp_util.convert( params['thermostatTemperatureSetpointHigh'], TEMP_CELSIUS, unit) if unit == TEMP_FAHRENHEIT: temp_high = round(temp_high) if temp_high < min_temp or temp_high > max_temp: raise SmartHomeError( ERR_VALUE_OUT_OF_RANGE, "Upper bound for temperature range should be between " "{} and {}".format(min_temp, max_temp)) temp_low = temp_util.convert( params['thermostatTemperatureSetpointLow'], TEMP_CELSIUS, unit) if unit == TEMP_FAHRENHEIT: temp_low = round(temp_low) if temp_low < min_temp or temp_low > max_temp: raise SmartHomeError( ERR_VALUE_OUT_OF_RANGE, "Lower bound for temperature range should be between " "{} and {}".format(min_temp, max_temp)) supported = self.state.attributes.get(ATTR_SUPPORTED_FEATURES) svc_data = { ATTR_ENTITY_ID: self.state.entity_id, } if supported & climate.SUPPORT_TARGET_TEMPERATURE_RANGE: svc_data[climate.ATTR_TARGET_TEMP_HIGH] = temp_high svc_data[climate.ATTR_TARGET_TEMP_LOW] = temp_low else: svc_data[ATTR_TEMPERATURE] = (temp_high + temp_low) / 2 await self.hass.services.async_call( climate.DOMAIN, climate.SERVICE_SET_TEMPERATURE, svc_data, blocking=True, context=data.context) elif command == COMMAND_THERMOSTAT_SET_MODE: target_mode = params['thermostatMode'] supported = self.state.attributes.get(ATTR_SUPPORTED_FEATURES) if target_mode in self.google_to_preset: await self.hass.services.async_call( climate.DOMAIN, climate.SERVICE_SET_PRESET_MODE, { climate.ATTR_PRESET_MODE: self.google_to_preset[target_mode], ATTR_ENTITY_ID: self.state.entity_id }, blocking=True, context=data.context) return if target_mode == 'on': # When targetting 'on', we're going to try best effort. modes = [ m for m in self.climate_google_modes if m != climate.HVAC_MODE_OFF ] if len(modes) == 1: target_mode = modes[0] elif 'auto' in modes: target_mode = 'auto' elif 'heatcool' in modes: target_mode = 'heatcool' else: raise SmartHomeError( ERR_FUNCTION_NOT_SUPPORTED, "Unable to translate 'on' to a HVAC mode.") await self.hass.services.async_call( climate.DOMAIN, climate.SERVICE_SET_HVAC_MODE, { ATTR_ENTITY_ID: self.state.entity_id, climate.ATTR_HVAC_MODE: self.google_to_hvac[target_mode], }, blocking=True, context=data.context)