mirror of
https://github.com/home-assistant/core.git
synced 2025-07-23 21:27:38 +00:00
Move temperature display helper from components to helpers (#10555)
This commit is contained in:
parent
b1afed9e52
commit
d25f676711
@ -9,12 +9,12 @@ from datetime import timedelta
|
|||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
import functools as ft
|
import functools as ft
|
||||||
from numbers import Number
|
|
||||||
|
|
||||||
import voluptuous as vol
|
import voluptuous as vol
|
||||||
|
|
||||||
from homeassistant.config import load_yaml_config_file
|
from homeassistant.config import load_yaml_config_file
|
||||||
from homeassistant.loader import bind_hass
|
from homeassistant.loader import bind_hass
|
||||||
|
from homeassistant.helpers.temperature import display_temp as show_temp
|
||||||
from homeassistant.util.temperature import convert as convert_temperature
|
from homeassistant.util.temperature import convert as convert_temperature
|
||||||
from homeassistant.helpers.entity_component import EntityComponent
|
from homeassistant.helpers.entity_component import EntityComponent
|
||||||
from homeassistant.helpers.entity import Entity
|
from homeassistant.helpers.entity import Entity
|
||||||
@ -22,7 +22,7 @@ from homeassistant.helpers.config_validation import PLATFORM_SCHEMA # noqa
|
|||||||
import homeassistant.helpers.config_validation as cv
|
import homeassistant.helpers.config_validation as cv
|
||||||
from homeassistant.const import (
|
from homeassistant.const import (
|
||||||
ATTR_ENTITY_ID, ATTR_TEMPERATURE, STATE_ON, STATE_OFF, STATE_UNKNOWN,
|
ATTR_ENTITY_ID, ATTR_TEMPERATURE, STATE_ON, STATE_OFF, STATE_UNKNOWN,
|
||||||
TEMP_CELSIUS)
|
TEMP_CELSIUS, PRECISION_WHOLE, PRECISION_TENTHS)
|
||||||
|
|
||||||
DOMAIN = 'climate'
|
DOMAIN = 'climate'
|
||||||
|
|
||||||
@ -71,11 +71,6 @@ ATTR_OPERATION_LIST = 'operation_list'
|
|||||||
ATTR_SWING_MODE = 'swing_mode'
|
ATTR_SWING_MODE = 'swing_mode'
|
||||||
ATTR_SWING_LIST = 'swing_list'
|
ATTR_SWING_LIST = 'swing_list'
|
||||||
|
|
||||||
# The degree of precision for each platform
|
|
||||||
PRECISION_WHOLE = 1
|
|
||||||
PRECISION_HALVES = 0.5
|
|
||||||
PRECISION_TENTHS = 0.1
|
|
||||||
|
|
||||||
CONVERTIBLE_ATTRIBUTE = [
|
CONVERTIBLE_ATTRIBUTE = [
|
||||||
ATTR_TEMPERATURE,
|
ATTR_TEMPERATURE,
|
||||||
ATTR_TARGET_TEMP_LOW,
|
ATTR_TARGET_TEMP_LOW,
|
||||||
@ -456,12 +451,18 @@ class ClimateDevice(Entity):
|
|||||||
def state_attributes(self):
|
def state_attributes(self):
|
||||||
"""Return the optional state attributes."""
|
"""Return the optional state attributes."""
|
||||||
data = {
|
data = {
|
||||||
ATTR_CURRENT_TEMPERATURE:
|
ATTR_CURRENT_TEMPERATURE: show_temp(
|
||||||
self._convert_for_display(self.current_temperature),
|
self.hass, self.current_temperature, self.temperature_unit,
|
||||||
ATTR_MIN_TEMP: self._convert_for_display(self.min_temp),
|
self.precision),
|
||||||
ATTR_MAX_TEMP: self._convert_for_display(self.max_temp),
|
ATTR_MIN_TEMP: show_temp(
|
||||||
ATTR_TEMPERATURE:
|
self.hass, self.min_temp, self.temperature_unit,
|
||||||
self._convert_for_display(self.target_temperature),
|
self.precision),
|
||||||
|
ATTR_MAX_TEMP: show_temp(
|
||||||
|
self.hass, self.max_temp, self.temperature_unit,
|
||||||
|
self.precision),
|
||||||
|
ATTR_TEMPERATURE: show_temp(
|
||||||
|
self.hass, self.target_temperature, self.temperature_unit,
|
||||||
|
self.precision),
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.target_temperature_step is not None:
|
if self.target_temperature_step is not None:
|
||||||
@ -469,10 +470,12 @@ class ClimateDevice(Entity):
|
|||||||
|
|
||||||
target_temp_high = self.target_temperature_high
|
target_temp_high = self.target_temperature_high
|
||||||
if target_temp_high is not None:
|
if target_temp_high is not None:
|
||||||
data[ATTR_TARGET_TEMP_HIGH] = self._convert_for_display(
|
data[ATTR_TARGET_TEMP_HIGH] = show_temp(
|
||||||
self.target_temperature_high)
|
self.hass, self.target_temperature_high, self.temperature_unit,
|
||||||
data[ATTR_TARGET_TEMP_LOW] = self._convert_for_display(
|
self.precision)
|
||||||
self.target_temperature_low)
|
data[ATTR_TARGET_TEMP_LOW] = show_temp(
|
||||||
|
self.hass, self.target_temperature_low, self.temperature_unit,
|
||||||
|
self.precision)
|
||||||
|
|
||||||
humidity = self.target_humidity
|
humidity = self.target_humidity
|
||||||
if humidity is not None:
|
if humidity is not None:
|
||||||
@ -733,24 +736,3 @@ class ClimateDevice(Entity):
|
|||||||
def max_humidity(self):
|
def max_humidity(self):
|
||||||
"""Return the maximum humidity."""
|
"""Return the maximum humidity."""
|
||||||
return 99
|
return 99
|
||||||
|
|
||||||
def _convert_for_display(self, temp):
|
|
||||||
"""Convert temperature into preferred units for display purposes."""
|
|
||||||
if temp is None:
|
|
||||||
return temp
|
|
||||||
|
|
||||||
# if the temperature is not a number this can cause issues
|
|
||||||
# with polymer components, so bail early there.
|
|
||||||
if not isinstance(temp, Number):
|
|
||||||
raise TypeError("Temperature is not a number: %s" % temp)
|
|
||||||
|
|
||||||
if self.temperature_unit != self.unit_of_measurement:
|
|
||||||
temp = convert_temperature(
|
|
||||||
temp, self.temperature_unit, self.unit_of_measurement)
|
|
||||||
# Round in the units appropriate
|
|
||||||
if self.precision == PRECISION_HALVES:
|
|
||||||
return round(temp * 2) / 2.0
|
|
||||||
elif self.precision == PRECISION_TENTHS:
|
|
||||||
return round(temp, 1)
|
|
||||||
# PRECISION_WHOLE as a fall back
|
|
||||||
return round(temp)
|
|
||||||
|
@ -9,12 +9,9 @@ import logging
|
|||||||
import voluptuous as vol
|
import voluptuous as vol
|
||||||
|
|
||||||
from homeassistant.components.climate import (
|
from homeassistant.components.climate import (
|
||||||
ClimateDevice, PLATFORM_SCHEMA, PRECISION_HALVES,
|
STATE_ON, STATE_OFF, STATE_AUTO, PLATFORM_SCHEMA, ClimateDevice)
|
||||||
STATE_AUTO, STATE_ON, STATE_OFF,
|
|
||||||
)
|
|
||||||
from homeassistant.const import (
|
from homeassistant.const import (
|
||||||
CONF_MAC, TEMP_CELSIUS, CONF_DEVICES, ATTR_TEMPERATURE)
|
CONF_MAC, CONF_DEVICES, TEMP_CELSIUS, ATTR_TEMPERATURE, PRECISION_HALVES)
|
||||||
|
|
||||||
import homeassistant.helpers.config_validation as cv
|
import homeassistant.helpers.config_validation as cv
|
||||||
|
|
||||||
REQUIREMENTS = ['python-eq3bt==0.1.6']
|
REQUIREMENTS = ['python-eq3bt==0.1.6']
|
||||||
@ -58,15 +55,17 @@ class EQ3BTSmartThermostat(ClimateDevice):
|
|||||||
|
|
||||||
def __init__(self, _mac, _name):
|
def __init__(self, _mac, _name):
|
||||||
"""Initialize the thermostat."""
|
"""Initialize the thermostat."""
|
||||||
# we want to avoid name clash with this module..
|
# We want to avoid name clash with this module.
|
||||||
import eq3bt as eq3
|
import eq3bt as eq3
|
||||||
|
|
||||||
self.modes = {eq3.Mode.Open: STATE_ON,
|
self.modes = {
|
||||||
eq3.Mode.Closed: STATE_OFF,
|
eq3.Mode.Open: STATE_ON,
|
||||||
eq3.Mode.Auto: STATE_AUTO,
|
eq3.Mode.Closed: STATE_OFF,
|
||||||
eq3.Mode.Manual: STATE_MANUAL,
|
eq3.Mode.Auto: STATE_AUTO,
|
||||||
eq3.Mode.Boost: STATE_BOOST,
|
eq3.Mode.Manual: STATE_MANUAL,
|
||||||
eq3.Mode.Away: STATE_AWAY}
|
eq3.Mode.Boost: STATE_BOOST,
|
||||||
|
eq3.Mode.Away: STATE_AWAY,
|
||||||
|
}
|
||||||
|
|
||||||
self.reverse_modes = {v: k for k, v in self.modes.items()}
|
self.reverse_modes = {v: k for k, v in self.modes.items()}
|
||||||
|
|
||||||
@ -153,11 +152,11 @@ class EQ3BTSmartThermostat(ClimateDevice):
|
|||||||
def device_state_attributes(self):
|
def device_state_attributes(self):
|
||||||
"""Return the device specific state attributes."""
|
"""Return the device specific state attributes."""
|
||||||
dev_specific = {
|
dev_specific = {
|
||||||
|
ATTR_STATE_AWAY_END: self._thermostat.away_end,
|
||||||
ATTR_STATE_LOCKED: self._thermostat.locked,
|
ATTR_STATE_LOCKED: self._thermostat.locked,
|
||||||
ATTR_STATE_LOW_BAT: self._thermostat.low_battery,
|
ATTR_STATE_LOW_BAT: self._thermostat.low_battery,
|
||||||
ATTR_STATE_VALVE: self._thermostat.valve_state,
|
ATTR_STATE_VALVE: self._thermostat.valve_state,
|
||||||
ATTR_STATE_WINDOW_OPEN: self._thermostat.window_open,
|
ATTR_STATE_WINDOW_OPEN: self._thermostat.window_open,
|
||||||
ATTR_STATE_AWAY_END: self._thermostat.away_end,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return dev_specific
|
return dev_specific
|
||||||
|
@ -4,46 +4,51 @@ Support for Wink thermostats, Air Conditioners, and Water Heaters.
|
|||||||
For more details about this platform, please refer to the documentation at
|
For more details about this platform, please refer to the documentation at
|
||||||
https://home-assistant.io/components/climate.wink/
|
https://home-assistant.io/components/climate.wink/
|
||||||
"""
|
"""
|
||||||
import logging
|
|
||||||
import asyncio
|
import asyncio
|
||||||
|
import logging
|
||||||
|
|
||||||
from homeassistant.components.wink import WinkDevice, DOMAIN
|
|
||||||
from homeassistant.components.climate import (
|
from homeassistant.components.climate import (
|
||||||
STATE_AUTO, STATE_COOL, STATE_HEAT, ClimateDevice,
|
STATE_ECO, STATE_GAS, STATE_AUTO, STATE_COOL, STATE_HEAT, STATE_ELECTRIC,
|
||||||
ATTR_TARGET_TEMP_HIGH, ATTR_TARGET_TEMP_LOW,
|
STATE_FAN_ONLY, STATE_HEAT_PUMP, ATTR_TEMPERATURE, STATE_HIGH_DEMAND,
|
||||||
ATTR_TEMPERATURE, STATE_FAN_ONLY,
|
STATE_PERFORMANCE, ATTR_TARGET_TEMP_LOW, ATTR_CURRENT_HUMIDITY,
|
||||||
ATTR_CURRENT_HUMIDITY, STATE_ECO, STATE_ELECTRIC,
|
ATTR_TARGET_TEMP_HIGH, ClimateDevice)
|
||||||
STATE_PERFORMANCE, STATE_HIGH_DEMAND,
|
from homeassistant.components.wink import DOMAIN, WinkDevice
|
||||||
STATE_HEAT_PUMP, STATE_GAS)
|
|
||||||
from homeassistant.const import (
|
from homeassistant.const import (
|
||||||
TEMP_CELSIUS, STATE_ON,
|
STATE_ON, STATE_OFF, TEMP_CELSIUS, STATE_UNKNOWN, PRECISION_TENTHS)
|
||||||
STATE_OFF, STATE_UNKNOWN)
|
from homeassistant.helpers.temperature import display_temp as show_temp
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
ATTR_ECO_TARGET = 'eco_target'
|
||||||
|
ATTR_EXTERNAL_TEMPERATURE = 'external_temperature'
|
||||||
|
ATTR_OCCUPIED = 'occupied'
|
||||||
|
ATTR_RHEEM_TYPE = 'rheem_type'
|
||||||
|
ATTR_SCHEDULE_ENABLED = 'schedule_enabled'
|
||||||
|
ATTR_SMART_TEMPERATURE = 'smart_temperature'
|
||||||
|
ATTR_TOTAL_CONSUMPTION = 'total_consumption'
|
||||||
|
ATTR_VACATION_MODE = 'vacation_mode'
|
||||||
|
|
||||||
DEPENDENCIES = ['wink']
|
DEPENDENCIES = ['wink']
|
||||||
|
|
||||||
SPEED_LOW = 'low'
|
SPEED_LOW = 'low'
|
||||||
SPEED_MEDIUM = 'medium'
|
SPEED_MEDIUM = 'medium'
|
||||||
SPEED_HIGH = 'high'
|
SPEED_HIGH = 'high'
|
||||||
|
|
||||||
HA_STATE_TO_WINK = {STATE_AUTO: 'auto',
|
HA_STATE_TO_WINK = {
|
||||||
STATE_ECO: 'eco',
|
STATE_AUTO: 'auto',
|
||||||
STATE_FAN_ONLY: 'fan_only',
|
STATE_COOL: 'cool_only',
|
||||||
STATE_HEAT: 'heat_only',
|
STATE_ECO: 'eco',
|
||||||
STATE_COOL: 'cool_only',
|
STATE_ELECTRIC: 'electric_only',
|
||||||
STATE_PERFORMANCE: 'performance',
|
STATE_FAN_ONLY: 'fan_only',
|
||||||
STATE_HIGH_DEMAND: 'high_demand',
|
STATE_GAS: 'gas',
|
||||||
STATE_HEAT_PUMP: 'heat_pump',
|
STATE_HEAT: 'heat_only',
|
||||||
STATE_ELECTRIC: 'electric_only',
|
STATE_HEAT_PUMP: 'heat_pump',
|
||||||
STATE_GAS: 'gas',
|
STATE_HIGH_DEMAND: 'high_demand',
|
||||||
STATE_OFF: 'off'}
|
STATE_OFF: 'off',
|
||||||
WINK_STATE_TO_HA = {value: key for key, value in HA_STATE_TO_WINK.items()}
|
STATE_PERFORMANCE: 'performance',
|
||||||
|
}
|
||||||
|
|
||||||
ATTR_EXTERNAL_TEMPERATURE = "external_temperature"
|
WINK_STATE_TO_HA = {value: key for key, value in HA_STATE_TO_WINK.items()}
|
||||||
ATTR_SMART_TEMPERATURE = "smart_temperature"
|
|
||||||
ATTR_ECO_TARGET = "eco_target"
|
|
||||||
ATTR_OCCUPIED = "occupied"
|
|
||||||
|
|
||||||
|
|
||||||
def setup_platform(hass, config, add_devices, discovery_info=None):
|
def setup_platform(hass, config, add_devices, discovery_info=None):
|
||||||
@ -85,15 +90,18 @@ class WinkThermostat(WinkDevice, ClimateDevice):
|
|||||||
target_temp_high = self.target_temperature_high
|
target_temp_high = self.target_temperature_high
|
||||||
target_temp_low = self.target_temperature_low
|
target_temp_low = self.target_temperature_low
|
||||||
if target_temp_high is not None:
|
if target_temp_high is not None:
|
||||||
data[ATTR_TARGET_TEMP_HIGH] = self._convert_for_display(
|
data[ATTR_TARGET_TEMP_HIGH] = show_temp(
|
||||||
self.target_temperature_high)
|
self.hass, self.target_temperature_high, self.temperature_unit,
|
||||||
|
PRECISION_TENTHS)
|
||||||
if target_temp_low is not None:
|
if target_temp_low is not None:
|
||||||
data[ATTR_TARGET_TEMP_LOW] = self._convert_for_display(
|
data[ATTR_TARGET_TEMP_LOW] = show_temp(
|
||||||
self.target_temperature_low)
|
self.hass, self.target_temperature_low, self.temperature_unit,
|
||||||
|
PRECISION_TENTHS)
|
||||||
|
|
||||||
if self.external_temperature:
|
if self.external_temperature:
|
||||||
data[ATTR_EXTERNAL_TEMPERATURE] = self._convert_for_display(
|
data[ATTR_EXTERNAL_TEMPERATURE] = show_temp(
|
||||||
self.external_temperature)
|
self.hass, self.external_temperature, self.temperature_unit,
|
||||||
|
PRECISION_TENTHS)
|
||||||
|
|
||||||
if self.smart_temperature:
|
if self.smart_temperature:
|
||||||
data[ATTR_SMART_TEMPERATURE] = self.smart_temperature
|
data[ATTR_SMART_TEMPERATURE] = self.smart_temperature
|
||||||
@ -358,13 +366,15 @@ class WinkAC(WinkDevice, ClimateDevice):
|
|||||||
target_temp_high = self.target_temperature_high
|
target_temp_high = self.target_temperature_high
|
||||||
target_temp_low = self.target_temperature_low
|
target_temp_low = self.target_temperature_low
|
||||||
if target_temp_high is not None:
|
if target_temp_high is not None:
|
||||||
data[ATTR_TARGET_TEMP_HIGH] = self._convert_for_display(
|
data[ATTR_TARGET_TEMP_HIGH] = show_temp(
|
||||||
self.target_temperature_high)
|
self.hass, self.target_temperature_high, self.temperature_unit,
|
||||||
|
PRECISION_TENTHS)
|
||||||
if target_temp_low is not None:
|
if target_temp_low is not None:
|
||||||
data[ATTR_TARGET_TEMP_LOW] = self._convert_for_display(
|
data[ATTR_TARGET_TEMP_LOW] = show_temp(
|
||||||
self.target_temperature_low)
|
self.hass, self.target_temperature_low, self.temperature_unit,
|
||||||
data["total_consumption"] = self.wink.total_consumption()
|
PRECISION_TENTHS)
|
||||||
data["schedule_enabled"] = self.wink.schedule_enabled()
|
data[ATTR_TOTAL_CONSUMPTION] = self.wink.total_consumption()
|
||||||
|
data[ATTR_SCHEDULE_ENABLED] = self.wink.schedule_enabled()
|
||||||
|
|
||||||
return data
|
return data
|
||||||
|
|
||||||
@ -471,8 +481,8 @@ class WinkWaterHeater(WinkDevice, ClimateDevice):
|
|||||||
def device_state_attributes(self):
|
def device_state_attributes(self):
|
||||||
"""Return the optional state attributes."""
|
"""Return the optional state attributes."""
|
||||||
data = {}
|
data = {}
|
||||||
data["vacation_mode"] = self.wink.vacation_mode_enabled()
|
data[ATTR_VACATION_MODE] = self.wink.vacation_mode_enabled()
|
||||||
data["rheem_type"] = self.wink.rheem_type()
|
data[ATTR_RHEEM_TYPE] = self.wink.rheem_type()
|
||||||
|
|
||||||
return data
|
return data
|
||||||
|
|
||||||
|
@ -6,11 +6,10 @@ https://home-assistant.io/components/weather/
|
|||||||
"""
|
"""
|
||||||
import asyncio
|
import asyncio
|
||||||
import logging
|
import logging
|
||||||
from numbers import Number
|
|
||||||
|
|
||||||
from homeassistant.const import TEMP_CELSIUS
|
|
||||||
from homeassistant.helpers.entity_component import EntityComponent
|
from homeassistant.helpers.entity_component import EntityComponent
|
||||||
from homeassistant.util.temperature import convert as convert_temperature
|
from homeassistant.helpers.temperature import display_temp as show_temp
|
||||||
|
from homeassistant.const import PRECISION_WHOLE, PRECISION_TENTHS, TEMP_CELSIUS
|
||||||
from homeassistant.helpers.config_validation import PLATFORM_SCHEMA # noqa
|
from homeassistant.helpers.config_validation import PLATFORM_SCHEMA # noqa
|
||||||
from homeassistant.helpers.entity import Entity
|
from homeassistant.helpers.entity import Entity
|
||||||
|
|
||||||
@ -98,11 +97,19 @@ class WeatherEntity(Entity):
|
|||||||
"""Return the forecast."""
|
"""Return the forecast."""
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
@property
|
||||||
|
def precision(self):
|
||||||
|
"""Return the forecast."""
|
||||||
|
return PRECISION_TENTHS if self.temperature_unit == TEMP_CELSIUS \
|
||||||
|
else PRECISION_WHOLE
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def state_attributes(self):
|
def state_attributes(self):
|
||||||
"""Return the state attributes."""
|
"""Return the state attributes."""
|
||||||
data = {
|
data = {
|
||||||
ATTR_WEATHER_TEMPERATURE: self._temp_for_display(self.temperature),
|
ATTR_WEATHER_TEMPERATURE: show_temp(
|
||||||
|
self.hass, self.temperature, self.temperature_unit,
|
||||||
|
self.precision),
|
||||||
ATTR_WEATHER_HUMIDITY: self.humidity,
|
ATTR_WEATHER_HUMIDITY: self.humidity,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -134,8 +141,9 @@ class WeatherEntity(Entity):
|
|||||||
forecast = []
|
forecast = []
|
||||||
for forecast_entry in self.forecast:
|
for forecast_entry in self.forecast:
|
||||||
forecast_entry = dict(forecast_entry)
|
forecast_entry = dict(forecast_entry)
|
||||||
forecast_entry[ATTR_FORECAST_TEMP] = self._temp_for_display(
|
forecast_entry[ATTR_FORECAST_TEMP] = show_temp(
|
||||||
forecast_entry[ATTR_FORECAST_TEMP])
|
self.hass, forecast_entry[ATTR_FORECAST_TEMP],
|
||||||
|
self.temperature_unit, self.precision)
|
||||||
forecast.append(forecast_entry)
|
forecast.append(forecast_entry)
|
||||||
|
|
||||||
data[ATTR_FORECAST] = forecast
|
data[ATTR_FORECAST] = forecast
|
||||||
@ -151,19 +159,3 @@ class WeatherEntity(Entity):
|
|||||||
def condition(self):
|
def condition(self):
|
||||||
"""Return the current condition."""
|
"""Return the current condition."""
|
||||||
raise NotImplementedError()
|
raise NotImplementedError()
|
||||||
|
|
||||||
def _temp_for_display(self, temp):
|
|
||||||
"""Convert temperature into preferred units for display purposes."""
|
|
||||||
unit = self.temperature_unit
|
|
||||||
hass_unit = self.hass.config.units.temperature_unit
|
|
||||||
|
|
||||||
if (temp is None or not isinstance(temp, Number) or
|
|
||||||
unit == hass_unit):
|
|
||||||
return temp
|
|
||||||
|
|
||||||
value = convert_temperature(temp, unit, hass_unit)
|
|
||||||
|
|
||||||
if hass_unit == TEMP_CELSIUS:
|
|
||||||
return round(value, 1)
|
|
||||||
# Users of fahrenheit generally expect integer units.
|
|
||||||
return round(value)
|
|
||||||
|
@ -31,7 +31,7 @@ CONDITION_CLASSES = {
|
|||||||
def setup_platform(hass, config, add_devices, discovery_info=None):
|
def setup_platform(hass, config, add_devices, discovery_info=None):
|
||||||
"""Set up the Demo weather."""
|
"""Set up the Demo weather."""
|
||||||
add_devices([
|
add_devices([
|
||||||
DemoWeather('South', 'Sunshine', 21, 92, 1099, 0.5, TEMP_CELSIUS,
|
DemoWeather('South', 'Sunshine', 21.6414, 92, 1099, 0.5, TEMP_CELSIUS,
|
||||||
[22, 19, 15, 12, 14, 18, 21]),
|
[22, 19, 15, 12, 14, 18, 21]),
|
||||||
DemoWeather('North', 'Shower rain', -12, 54, 987, 4.8, TEMP_FAHRENHEIT,
|
DemoWeather('North', 'Shower rain', -12, 54, 987, 4.8, TEMP_FAHRENHEIT,
|
||||||
[-10, -13, -18, -23, -19, -14, -9])
|
[-10, -13, -18, -23, -19, -14, -9])
|
||||||
|
@ -417,3 +417,8 @@ SPEED_MS = 'speed_ms' # type: str
|
|||||||
ILLUMINANCE = 'illuminance' # type: str
|
ILLUMINANCE = 'illuminance' # type: str
|
||||||
|
|
||||||
WEEKDAYS = ['mon', 'tue', 'wed', 'thu', 'fri', 'sat', 'sun']
|
WEEKDAYS = ['mon', 'tue', 'wed', 'thu', 'fri', 'sat', 'sun']
|
||||||
|
|
||||||
|
# The degree of precision for platforms
|
||||||
|
PRECISION_WHOLE = 1
|
||||||
|
PRECISION_HALVES = 0.5
|
||||||
|
PRECISION_TENTHS = 0.1
|
||||||
|
33
homeassistant/helpers/temperature.py
Normal file
33
homeassistant/helpers/temperature.py
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
"""Temperature helpers for Home Assistant."""
|
||||||
|
from numbers import Number
|
||||||
|
|
||||||
|
from homeassistant.core import HomeAssistant
|
||||||
|
from homeassistant.util.temperature import convert as convert_temperature
|
||||||
|
|
||||||
|
|
||||||
|
def display_temp(hass: HomeAssistant, temperature: float, unit: str,
|
||||||
|
precision: float) -> float:
|
||||||
|
"""Convert temperature into preferred units for display purposes."""
|
||||||
|
temperature_unit = unit
|
||||||
|
ha_unit = hass.config.units.temperature_unit
|
||||||
|
|
||||||
|
if temperature is None:
|
||||||
|
return temperature
|
||||||
|
|
||||||
|
# If the temperature is not a number this can cause issues
|
||||||
|
# with Polymer components, so bail early there.
|
||||||
|
if not isinstance(temperature, Number):
|
||||||
|
raise TypeError(
|
||||||
|
"Temperature is not a number: {}".format(temperature))
|
||||||
|
|
||||||
|
if temperature_unit != ha_unit:
|
||||||
|
temperature = convert_temperature(
|
||||||
|
temperature, temperature_unit, ha_unit)
|
||||||
|
|
||||||
|
# Round in the units appropriate
|
||||||
|
if precision == 0.5:
|
||||||
|
return round(temperature * 2) / 2.0
|
||||||
|
elif precision == 0.1:
|
||||||
|
return round(temperature, 1)
|
||||||
|
# Integer as a fall back (PRECISION_WHOLE)
|
||||||
|
return round(temperature)
|
@ -37,7 +37,7 @@ class TestWeather(unittest.TestCase):
|
|||||||
assert state.state == 'sunny'
|
assert state.state == 'sunny'
|
||||||
|
|
||||||
data = state.attributes
|
data = state.attributes
|
||||||
assert data.get(ATTR_WEATHER_TEMPERATURE) == 21
|
assert data.get(ATTR_WEATHER_TEMPERATURE) == 21.6
|
||||||
assert data.get(ATTR_WEATHER_HUMIDITY) == 92
|
assert data.get(ATTR_WEATHER_HUMIDITY) == 92
|
||||||
assert data.get(ATTR_WEATHER_PRESSURE) == 1099
|
assert data.get(ATTR_WEATHER_PRESSURE) == 1099
|
||||||
assert data.get(ATTR_WEATHER_WIND_SPEED) == 0.5
|
assert data.get(ATTR_WEATHER_WIND_SPEED) == 0.5
|
||||||
@ -57,4 +57,4 @@ class TestWeather(unittest.TestCase):
|
|||||||
assert state.state == 'rainy'
|
assert state.state == 'rainy'
|
||||||
|
|
||||||
data = state.attributes
|
data = state.attributes
|
||||||
assert data.get(ATTR_WEATHER_TEMPERATURE) == -24.4
|
assert data.get(ATTR_WEATHER_TEMPERATURE) == -24
|
||||||
|
49
tests/helpers/test_temperature.py
Normal file
49
tests/helpers/test_temperature.py
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
"""Tests Home Assistant temperature helpers."""
|
||||||
|
import unittest
|
||||||
|
|
||||||
|
from tests.common import get_test_home_assistant
|
||||||
|
|
||||||
|
from homeassistant.const import (
|
||||||
|
TEMP_CELSIUS, PRECISION_WHOLE, TEMP_FAHRENHEIT, PRECISION_HALVES,
|
||||||
|
PRECISION_TENTHS)
|
||||||
|
from homeassistant.helpers.temperature import display_temp
|
||||||
|
from homeassistant.util.unit_system import METRIC_SYSTEM
|
||||||
|
|
||||||
|
TEMP = 24.636626
|
||||||
|
|
||||||
|
|
||||||
|
class TestHelpersTemperature(unittest.TestCase):
|
||||||
|
"""Setup the temperature tests."""
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
"""Setup the tests."""
|
||||||
|
self.hass = get_test_home_assistant()
|
||||||
|
self.hass.config.unit_system = METRIC_SYSTEM
|
||||||
|
|
||||||
|
def tearDown(self):
|
||||||
|
"""Stop down stuff we started."""
|
||||||
|
self.hass.stop()
|
||||||
|
|
||||||
|
def test_temperature_not_a_number(self):
|
||||||
|
"""Test that temperature is a number."""
|
||||||
|
temp = "Temperature"
|
||||||
|
with self.assertRaises(Exception) as context:
|
||||||
|
display_temp(self.hass, temp, TEMP_CELSIUS, PRECISION_HALVES)
|
||||||
|
|
||||||
|
self.assertTrue("Temperature is not a number: {}".format(temp)
|
||||||
|
in str(context.exception))
|
||||||
|
|
||||||
|
def test_celsius_halves(self):
|
||||||
|
"""Test temperature to celsius rounding to halves."""
|
||||||
|
self.assertEqual(24.5, display_temp(
|
||||||
|
self.hass, TEMP, TEMP_CELSIUS, PRECISION_HALVES))
|
||||||
|
|
||||||
|
def test_celsius_tenths(self):
|
||||||
|
"""Test temperature to celsius rounding to tenths."""
|
||||||
|
self.assertEqual(24.6, display_temp(
|
||||||
|
self.hass, TEMP, TEMP_CELSIUS, PRECISION_TENTHS))
|
||||||
|
|
||||||
|
def test_fahrenheit_wholes(self):
|
||||||
|
"""Test temperature to fahrenheit rounding to wholes."""
|
||||||
|
self.assertEqual(-4, display_temp(
|
||||||
|
self.hass, TEMP, TEMP_FAHRENHEIT, PRECISION_WHOLE))
|
Loading…
x
Reference in New Issue
Block a user