mirror of
https://github.com/home-assistant/core.git
synced 2025-07-23 13:17:32 +00:00
Merge pull request #2731 from home-assistant/teagan-unit-system
Teagan unit system
This commit is contained in:
commit
d1107a9cf3
@ -10,8 +10,8 @@ homeassistant:
|
||||
# Impacts weather/sunrise data
|
||||
elevation: 665
|
||||
|
||||
# C for Celsius, F for Fahrenheit
|
||||
temperature_unit: C
|
||||
# 'metric' for Metric System, 'imperial' for imperial system
|
||||
unit_system: metric
|
||||
|
||||
# Pick yours from here:
|
||||
# http://en.wikipedia.org/wiki/List_of_tz_database_time_zones
|
||||
|
@ -419,8 +419,9 @@ definitions:
|
||||
description: Longitude of Home Assistant server
|
||||
location_name:
|
||||
type: string
|
||||
temperature_unit:
|
||||
unit_system:
|
||||
type: string
|
||||
description: The system for measurement units
|
||||
time_zone:
|
||||
type: string
|
||||
version:
|
||||
|
@ -1 +1 @@
|
||||
Subproject commit cbafbda5fdd2216ab4b6ebd962cbd1164fa8abec
|
||||
Subproject commit a343d3d098e78976fc66f8ed66ce0ae5d7bc3861
|
@ -6,13 +6,14 @@ https://home-assistant.io/components/hvac/
|
||||
"""
|
||||
import logging
|
||||
import os
|
||||
from numbers import Number
|
||||
|
||||
from homeassistant.helpers.entity_component import EntityComponent
|
||||
|
||||
from homeassistant.config import load_yaml_config_file
|
||||
import homeassistant.util as util
|
||||
from homeassistant.util.temperature import convert as convert_temperature
|
||||
from homeassistant.helpers.entity import Entity
|
||||
from homeassistant.helpers.temperature import convert
|
||||
from homeassistant.helpers.config_validation import PLATFORM_SCHEMA # noqa
|
||||
from homeassistant.const import (
|
||||
ATTR_ENTITY_ID, ATTR_TEMPERATURE, STATE_ON, STATE_OFF, STATE_UNKNOWN,
|
||||
@ -204,8 +205,8 @@ def setup(hass, config):
|
||||
return
|
||||
|
||||
for hvac in target_hvacs:
|
||||
hvac.set_temperature(convert(
|
||||
temperature, hass.config.temperature_unit,
|
||||
hvac.set_temperature(convert_temperature(
|
||||
temperature, hass.config.units.temperature_unit,
|
||||
hvac.unit_of_measurement))
|
||||
|
||||
if hvac.should_poll:
|
||||
@ -462,12 +463,12 @@ class HvacDevice(Entity):
|
||||
@property
|
||||
def min_temp(self):
|
||||
"""Return the minimum temperature."""
|
||||
return convert(19, TEMP_CELSIUS, self.unit_of_measurement)
|
||||
return convert_temperature(19, TEMP_CELSIUS, self.unit_of_measurement)
|
||||
|
||||
@property
|
||||
def max_temp(self):
|
||||
"""Return the maximum temperature."""
|
||||
return convert(30, TEMP_CELSIUS, self.unit_of_measurement)
|
||||
return convert_temperature(30, TEMP_CELSIUS, self.unit_of_measurement)
|
||||
|
||||
@property
|
||||
def min_humidity(self):
|
||||
@ -481,13 +482,13 @@ class HvacDevice(Entity):
|
||||
|
||||
def _convert_for_display(self, temp):
|
||||
"""Convert temperature into preferred units for display purposes."""
|
||||
if temp is None:
|
||||
return None
|
||||
if temp is None or not isinstance(temp, Number):
|
||||
return temp
|
||||
|
||||
value = convert(temp, self.unit_of_measurement,
|
||||
self.hass.config.temperature_unit)
|
||||
value = convert_temperature(temp, self.unit_of_measurement,
|
||||
self.hass.config.units.temperature_unit)
|
||||
|
||||
if self.hass.config.temperature_unit is TEMP_CELSIUS:
|
||||
if self.hass.config.units.temperature_unit is TEMP_CELSIUS:
|
||||
decimal_count = 1
|
||||
else:
|
||||
# Users of fahrenheit generally expect integer units.
|
||||
|
@ -10,7 +10,7 @@ import socket
|
||||
from homeassistant.const import (ATTR_BATTERY_LEVEL, CONF_OPTIMISTIC,
|
||||
EVENT_HOMEASSISTANT_START,
|
||||
EVENT_HOMEASSISTANT_STOP,
|
||||
STATE_OFF, STATE_ON, TEMP_CELSIUS)
|
||||
STATE_OFF, STATE_ON)
|
||||
from homeassistant.helpers import validate_config, discovery
|
||||
|
||||
CONF_GATEWAYS = 'gateways'
|
||||
@ -53,7 +53,7 @@ def setup(hass, config): # pylint: disable=too-many-locals
|
||||
import mysensors.mysensors as mysensors
|
||||
|
||||
version = str(config[DOMAIN].get(CONF_VERSION, DEFAULT_VERSION))
|
||||
is_metric = (hass.config.temperature_unit == TEMP_CELSIUS)
|
||||
is_metric = hass.config.units.is_metric
|
||||
persistence = config[DOMAIN].get(CONF_PERSISTENCE, True)
|
||||
|
||||
def setup_gateway(device, persistence_file, baud_rate, tcp_port):
|
||||
|
@ -27,9 +27,6 @@ DEFAULT_TOLERANCE = 1
|
||||
# Default zone
|
||||
DEFAULT_PROXIMITY_ZONE = 'home'
|
||||
|
||||
# Default unit of measure
|
||||
DEFAULT_UNIT_OF_MEASUREMENT = 'km'
|
||||
|
||||
# Default distance to zone
|
||||
DEFAULT_DIST_TO_ZONE = NOT_SET
|
||||
|
||||
@ -71,7 +68,7 @@ def setup_proximity_component(hass, config):
|
||||
|
||||
# Get the unit of measurement from configuration.yaml.
|
||||
unit_of_measure = config.get(ATTR_UNIT_OF_MEASUREMENT,
|
||||
DEFAULT_UNIT_OF_MEASUREMENT)
|
||||
hass.config.units.length_unit)
|
||||
|
||||
zone_id = 'zone.{}'.format(proximity_zone)
|
||||
state = hass.states.get(zone_id)
|
||||
@ -216,11 +213,11 @@ class Proximity(Entity): # pylint: disable=too-many-instance-attributes
|
||||
|
||||
# Loop through each of the distances collected and work out the
|
||||
# closest.
|
||||
closest_device = ''
|
||||
dist_to_zone = 1000000
|
||||
closest_device = None # type: str
|
||||
dist_to_zone = None # type: float
|
||||
|
||||
for device in distances_to_zone:
|
||||
if distances_to_zone[device] < dist_to_zone:
|
||||
if not dist_to_zone or distances_to_zone[device] < dist_to_zone:
|
||||
closest_device = device
|
||||
dist_to_zone = distances_to_zone[device]
|
||||
|
||||
|
@ -10,6 +10,7 @@ from datetime import timedelta
|
||||
from homeassistant.const import TEMP_FAHRENHEIT
|
||||
from homeassistant.helpers.entity import Entity
|
||||
from homeassistant.util import Throttle
|
||||
from homeassistant.util.temperature import celsius_to_fahrenheit
|
||||
|
||||
# Update this requirement to upstream as soon as it supports Python 3.
|
||||
REQUIREMENTS = ['http://github.com/mala-zaba/Adafruit_Python_DHT/archive/'
|
||||
@ -32,8 +33,7 @@ def setup_platform(hass, config, add_devices, discovery_info=None):
|
||||
# pylint: disable=import-error
|
||||
import Adafruit_DHT
|
||||
|
||||
SENSOR_TYPES['temperature'][1] = hass.config.temperature_unit
|
||||
unit = hass.config.temperature_unit
|
||||
SENSOR_TYPES['temperature'][1] = hass.config.units.temperature_unit
|
||||
available_sensors = {
|
||||
"DHT11": Adafruit_DHT.DHT11,
|
||||
"DHT22": Adafruit_DHT.DHT22,
|
||||
@ -58,7 +58,8 @@ def setup_platform(hass, config, add_devices, discovery_info=None):
|
||||
if variable not in SENSOR_TYPES:
|
||||
_LOGGER.error('Sensor type: "%s" does not exist', variable)
|
||||
else:
|
||||
dev.append(DHTSensor(data, variable, unit, name))
|
||||
dev.append(
|
||||
DHTSensor(data, variable, SENSOR_TYPES[variable][1], name))
|
||||
except KeyError:
|
||||
pass
|
||||
|
||||
@ -103,7 +104,8 @@ class DHTSensor(Entity):
|
||||
if self.type == 'temperature':
|
||||
self._state = round(data['temperature'], 1)
|
||||
if self.temp_unit == TEMP_FAHRENHEIT:
|
||||
self._state = round(data['temperature'] * 1.8 + 32, 1)
|
||||
self._state = round(celsius_to_fahrenheit(data['temperature']),
|
||||
1)
|
||||
elif self.type == 'humidity':
|
||||
self._state = round(data['humidity'], 1)
|
||||
|
||||
|
@ -10,7 +10,6 @@ import logging
|
||||
import datetime
|
||||
import time
|
||||
|
||||
from homeassistant.const import TEMP_CELSIUS
|
||||
from homeassistant.util import Throttle
|
||||
from homeassistant.helpers.entity import Entity
|
||||
from homeassistant.loader import get_component
|
||||
@ -238,8 +237,7 @@ def setup_platform(hass, config, add_devices, discovery_info=None):
|
||||
for resource in config.get("monitored_resources",
|
||||
FITBIT_DEFAULT_RESOURCE_LIST):
|
||||
dev.append(FitbitSensor(authd_client, config_path, resource,
|
||||
hass.config.temperature_unit ==
|
||||
TEMP_CELSIUS))
|
||||
hass.config.units.is_metric))
|
||||
add_devices(dev)
|
||||
|
||||
else:
|
||||
|
@ -10,7 +10,7 @@ from requests.exceptions import ConnectionError as ConnectError, \
|
||||
HTTPError, Timeout
|
||||
|
||||
from homeassistant.components.sensor import DOMAIN
|
||||
from homeassistant.const import CONF_API_KEY, TEMP_CELSIUS
|
||||
from homeassistant.const import CONF_API_KEY
|
||||
from homeassistant.helpers import validate_config
|
||||
from homeassistant.helpers.entity import Entity
|
||||
from homeassistant.util import Throttle
|
||||
@ -62,7 +62,7 @@ def setup_platform(hass, config, add_devices, discovery_info=None):
|
||||
|
||||
if 'units' in config:
|
||||
units = config['units']
|
||||
elif hass.config.temperature_unit == TEMP_CELSIUS:
|
||||
elif hass.config.units.is_metric:
|
||||
units = 'si'
|
||||
else:
|
||||
units = 'us'
|
||||
|
@ -11,8 +11,7 @@ import voluptuous as vol
|
||||
|
||||
from homeassistant.helpers.entity import Entity
|
||||
from homeassistant.const import (
|
||||
CONF_API_KEY, TEMP_CELSIUS, TEMP_FAHRENHEIT,
|
||||
EVENT_HOMEASSISTANT_START, ATTR_LATITUDE, ATTR_LONGITUDE)
|
||||
CONF_API_KEY, EVENT_HOMEASSISTANT_START, ATTR_LATITUDE, ATTR_LONGITUDE)
|
||||
|
||||
from homeassistant.util import Throttle
|
||||
import homeassistant.helpers.config_validation as cv
|
||||
@ -92,10 +91,7 @@ def setup_platform(hass, config, add_devices_callback, discovery_info=None):
|
||||
options = config.get(CONF_OPTIONS)
|
||||
|
||||
if options.get('units') is None:
|
||||
if hass.config.temperature_unit is TEMP_CELSIUS:
|
||||
options['units'] = 'metric'
|
||||
elif hass.config.temperature_unit is TEMP_FAHRENHEIT:
|
||||
options['units'] = 'imperial'
|
||||
options['units'] = hass.config.units.name
|
||||
|
||||
travel_mode = config.get(CONF_TRAVEL_MODE)
|
||||
mode = options.get(CONF_MODE)
|
||||
|
@ -65,7 +65,7 @@ class MoldIndicator(Entity):
|
||||
self._indoor_humidity_sensor = indoor_humidity_sensor
|
||||
self._outdoor_temp_sensor = outdoor_temp_sensor
|
||||
self._calib_factor = calib_factor
|
||||
self._is_metric = (hass.config.temperature_unit == TEMP_CELSIUS)
|
||||
self._is_metric = hass.config.units.is_metric
|
||||
|
||||
self._dewpoint = None
|
||||
self._indoor_temp = None
|
||||
|
@ -48,8 +48,7 @@ def setup_platform(hass, config, add_devices, discovery_info=None):
|
||||
|
||||
from pyowm import OWM
|
||||
|
||||
SENSOR_TYPES['temperature'][1] = hass.config.temperature_unit
|
||||
unit = hass.config.temperature_unit
|
||||
SENSOR_TYPES['temperature'][1] = hass.config.units.temperature_unit
|
||||
forecast = config.get('forecast')
|
||||
owm = OWM(config.get(CONF_API_KEY, None))
|
||||
|
||||
@ -67,13 +66,15 @@ def setup_platform(hass, config, add_devices, discovery_info=None):
|
||||
if variable not in SENSOR_TYPES:
|
||||
_LOGGER.error('Sensor type: "%s" does not exist', variable)
|
||||
else:
|
||||
dev.append(OpenWeatherMapSensor(data, variable, unit))
|
||||
dev.append(OpenWeatherMapSensor(data, variable,
|
||||
SENSOR_TYPES[variable][1]))
|
||||
except KeyError:
|
||||
pass
|
||||
|
||||
if forecast:
|
||||
SENSOR_TYPES['forecast'] = ['Forecast', None]
|
||||
dev.append(OpenWeatherMapSensor(data, 'forecast', unit))
|
||||
dev.append(OpenWeatherMapSensor(data, 'forecast',
|
||||
SENSOR_TYPES['temperature'][1]))
|
||||
|
||||
add_devices(dev)
|
||||
|
||||
|
@ -21,7 +21,7 @@ def setup_platform(hass, config, add_devices_callback, discovery_info=None):
|
||||
"""Setup the Temper sensors."""
|
||||
from temperusb.temper import TemperHandler
|
||||
|
||||
temp_unit = hass.config.temperature_unit
|
||||
temp_unit = hass.config.units.temperature_unit
|
||||
name = config.get(CONF_NAME, DEVICE_DEFAULT_NAME)
|
||||
temper_devices = TemperHandler().get_devices()
|
||||
add_devices_callback([TemperSensor(dev, temp_unit, name + '_' + str(idx))
|
||||
|
@ -51,7 +51,8 @@ class VeraSensor(VeraDevice, Entity):
|
||||
def update(self):
|
||||
"""Update the state."""
|
||||
if self.vera_device.category == "Temperature Sensor":
|
||||
current_temp = self.vera_device.temperature
|
||||
self.current_value = self.vera_device.temperature
|
||||
|
||||
vera_temp_units = (
|
||||
self.vera_device.vera_controller.temperature_units)
|
||||
|
||||
@ -60,14 +61,6 @@ class VeraSensor(VeraDevice, Entity):
|
||||
else:
|
||||
self._temperature_units = TEMP_CELSIUS
|
||||
|
||||
if self.hass:
|
||||
temp = self.hass.config.temperature(
|
||||
current_temp,
|
||||
self._temperature_units)
|
||||
|
||||
current_temp, self._temperature_units = temp
|
||||
|
||||
self.current_value = current_temp
|
||||
elif self.vera_device.category == "Light Sensor":
|
||||
self.current_value = self.vera_device.light
|
||||
elif self.vera_device.category == "Humidity Sensor":
|
||||
|
@ -45,7 +45,7 @@ def setup_platform(hass, config, add_devices, discovery_info=None):
|
||||
"""Setup the Yahoo! weather sensor."""
|
||||
from yahooweather import get_woeid, UNIT_C, UNIT_F
|
||||
|
||||
unit = hass.config.temperature_unit
|
||||
unit = hass.config.units.temperature_unit
|
||||
woeid = config.get("woeid", None)
|
||||
forecast = config.get("forecast", 0)
|
||||
|
||||
|
@ -6,6 +6,7 @@ https://home-assistant.io/components/thermostat/
|
||||
"""
|
||||
import logging
|
||||
import os
|
||||
from numbers import Number
|
||||
|
||||
import voluptuous as vol
|
||||
|
||||
@ -13,9 +14,9 @@ from homeassistant.helpers.entity_component import EntityComponent
|
||||
|
||||
from homeassistant.config import load_yaml_config_file
|
||||
from homeassistant.helpers.entity import Entity
|
||||
from homeassistant.helpers.temperature import convert
|
||||
from homeassistant.helpers.config_validation import PLATFORM_SCHEMA # noqa
|
||||
import homeassistant.helpers.config_validation as cv
|
||||
from homeassistant.util.temperature import convert
|
||||
from homeassistant.const import (
|
||||
ATTR_ENTITY_ID, ATTR_TEMPERATURE, STATE_ON, STATE_OFF, STATE_UNKNOWN,
|
||||
TEMP_CELSIUS)
|
||||
@ -146,10 +147,11 @@ def setup(hass, config):
|
||||
temperature = service.data[ATTR_TEMPERATURE]
|
||||
|
||||
for thermostat in target_thermostats:
|
||||
thermostat.set_temperature(convert(
|
||||
temperature, hass.config.temperature_unit,
|
||||
thermostat.unit_of_measurement))
|
||||
converted_temperature = convert(
|
||||
temperature, hass.config.units.temperature_unit,
|
||||
thermostat.unit_of_measurement)
|
||||
|
||||
thermostat.set_temperature(converted_temperature)
|
||||
thermostat.update_ha_state(True)
|
||||
|
||||
hass.services.register(
|
||||
@ -310,13 +312,13 @@ class ThermostatDevice(Entity):
|
||||
|
||||
def _convert_for_display(self, temp):
|
||||
"""Convert temperature into preferred units for display purposes."""
|
||||
if temp is None:
|
||||
return None
|
||||
if temp is None or not isinstance(temp, Number):
|
||||
return temp
|
||||
|
||||
value = convert(temp, self.unit_of_measurement,
|
||||
self.hass.config.temperature_unit)
|
||||
value = self.hass.config.units.temperature(temp,
|
||||
self.unit_of_measurement)
|
||||
|
||||
if self.hass.config.temperature_unit is TEMP_CELSIUS:
|
||||
if self.hass.config.units.is_metric:
|
||||
decimal_count = 1
|
||||
else:
|
||||
# Users of fahrenheit generally expect integer units.
|
||||
|
@ -8,7 +8,7 @@ import logging
|
||||
|
||||
from homeassistant.components.thermostat import ThermostatDevice
|
||||
from homeassistant.const import TEMP_CELSIUS
|
||||
from homeassistant.helpers.temperature import convert
|
||||
from homeassistant.util.temperature import convert
|
||||
|
||||
REQUIREMENTS = ['bluepy_devices==0.2.0']
|
||||
|
||||
|
@ -8,12 +8,10 @@ import logging
|
||||
import voluptuous as vol
|
||||
|
||||
import homeassistant.helpers.config_validation as cv
|
||||
import homeassistant.util as util
|
||||
from homeassistant.components import switch
|
||||
from homeassistant.components.thermostat import (
|
||||
STATE_HEAT, STATE_COOL, STATE_IDLE, ThermostatDevice)
|
||||
from homeassistant.const import (
|
||||
ATTR_UNIT_OF_MEASUREMENT, TEMP_CELSIUS, TEMP_FAHRENHEIT)
|
||||
from homeassistant.const import ATTR_UNIT_OF_MEASUREMENT
|
||||
from homeassistant.helpers.event import track_state_change
|
||||
|
||||
DEPENDENCIES = ['switch', 'sensor']
|
||||
@ -75,7 +73,7 @@ class HeatControl(ThermostatDevice):
|
||||
self._min_temp = min_temp
|
||||
self._max_temp = max_temp
|
||||
self._target_temp = target_temp
|
||||
self._unit = None
|
||||
self._unit = hass.config.units.temperature_unit
|
||||
|
||||
track_state_change(hass, sensor_entity_id, self._sensor_changed)
|
||||
|
||||
@ -157,24 +155,11 @@ class HeatControl(ThermostatDevice):
|
||||
"""Update thermostat with latest state from sensor."""
|
||||
unit = state.attributes.get(ATTR_UNIT_OF_MEASUREMENT)
|
||||
|
||||
if unit not in (TEMP_CELSIUS, TEMP_FAHRENHEIT):
|
||||
self._cur_temp = None
|
||||
self._unit = None
|
||||
_LOGGER.error('Sensor has unsupported unit: %s (allowed: %s, %s)',
|
||||
unit, TEMP_CELSIUS, TEMP_FAHRENHEIT)
|
||||
return
|
||||
|
||||
temp = util.convert(state.state, float)
|
||||
|
||||
if temp is None:
|
||||
self._cur_temp = None
|
||||
self._unit = None
|
||||
_LOGGER.error('Unable to parse sensor temperature: %s',
|
||||
state.state)
|
||||
return
|
||||
|
||||
self._cur_temp = temp
|
||||
self._unit = unit
|
||||
try:
|
||||
self._cur_temp = self.hass.config.units.temperature(
|
||||
float(state.state), unit)
|
||||
except ValueError as ex:
|
||||
_LOGGER.error('Unable to update from sensor: %s', ex)
|
||||
|
||||
def _control_heating(self):
|
||||
"""Check if we need to turn heating on or off."""
|
||||
|
@ -7,7 +7,7 @@ https://home-assistant.io/components/thermostat.homematic/
|
||||
import logging
|
||||
import homeassistant.components.homematic as homematic
|
||||
from homeassistant.components.thermostat import ThermostatDevice
|
||||
from homeassistant.helpers.temperature import convert
|
||||
from homeassistant.util.temperature import convert
|
||||
from homeassistant.const import TEMP_CELSIUS, STATE_UNKNOWN
|
||||
|
||||
DEPENDENCIES = ['homematic']
|
||||
|
@ -7,12 +7,14 @@ from types import MappingProxyType
|
||||
import voluptuous as vol
|
||||
|
||||
from homeassistant.const import (
|
||||
CONF_LATITUDE, CONF_LONGITUDE, CONF_NAME, CONF_TEMPERATURE_UNIT,
|
||||
CONF_TIME_ZONE, CONF_CUSTOMIZE, CONF_ELEVATION, TEMP_FAHRENHEIT,
|
||||
TEMP_CELSIUS, __version__)
|
||||
CONF_LATITUDE, CONF_LONGITUDE, CONF_NAME, CONF_UNIT_SYSTEM,
|
||||
CONF_TIME_ZONE, CONF_CUSTOMIZE, CONF_ELEVATION, CONF_UNIT_SYSTEM_METRIC,
|
||||
CONF_UNIT_SYSTEM_IMPERIAL, CONF_TEMPERATURE_UNIT, TEMP_CELSIUS,
|
||||
__version__)
|
||||
from homeassistant.exceptions import HomeAssistantError
|
||||
from homeassistant.util.yaml import load_yaml
|
||||
import homeassistant.helpers.config_validation as cv
|
||||
from homeassistant.helpers.unit_system import (IMPERIAL_SYSTEM, METRIC_SYSTEM)
|
||||
from homeassistant.helpers.entity import valid_entity_id, set_customize
|
||||
from homeassistant.util import dt as date_util, location as loc_util
|
||||
|
||||
@ -30,7 +32,9 @@ DEFAULT_CORE_CONFIG = (
|
||||
' the sun rises and sets'),
|
||||
(CONF_LONGITUDE, 0, 'longitude', None),
|
||||
(CONF_ELEVATION, 0, None, 'Impacts weather/sunrise data'),
|
||||
(CONF_TEMPERATURE_UNIT, 'C', None, 'C for Celsius, F for Fahrenheit'),
|
||||
(CONF_UNIT_SYSTEM, CONF_UNIT_SYSTEM_METRIC, None,
|
||||
'{} for Metric, {} for Imperial'.format(CONF_UNIT_SYSTEM_METRIC,
|
||||
CONF_UNIT_SYSTEM_IMPERIAL)),
|
||||
(CONF_TIME_ZONE, 'UTC', 'time_zone', 'Pick yours from here: http://en.wiki'
|
||||
'pedia.org/wiki/List_of_tz_database_time_zones'),
|
||||
)
|
||||
@ -88,7 +92,8 @@ CORE_CONFIG_SCHEMA = vol.Schema({
|
||||
CONF_LATITUDE: cv.latitude,
|
||||
CONF_LONGITUDE: cv.longitude,
|
||||
CONF_ELEVATION: vol.Coerce(int),
|
||||
CONF_TEMPERATURE_UNIT: cv.temperature_unit,
|
||||
vol.Optional(CONF_TEMPERATURE_UNIT): cv.temperature_unit,
|
||||
CONF_UNIT_SYSTEM: cv.unit_system,
|
||||
CONF_TIME_ZONE: cv.time_zone,
|
||||
vol.Required(CONF_CUSTOMIZE,
|
||||
default=MappingProxyType({})): _valid_customize,
|
||||
@ -131,8 +136,10 @@ def create_default_config(config_dir, detect_location=True):
|
||||
location_info = detect_location and loc_util.detect_location_info()
|
||||
|
||||
if location_info:
|
||||
if location_info.use_fahrenheit:
|
||||
info[CONF_TEMPERATURE_UNIT] = 'F'
|
||||
if location_info.use_metric:
|
||||
info[CONF_UNIT_SYSTEM] = CONF_UNIT_SYSTEM_METRIC
|
||||
else:
|
||||
info[CONF_UNIT_SYSTEM] = CONF_UNIT_SYSTEM_IMPERIAL
|
||||
|
||||
for attr, default, prop, _ in DEFAULT_CORE_CONFIG:
|
||||
if prop is None:
|
||||
@ -244,18 +251,30 @@ def process_ha_core_config(hass, config):
|
||||
|
||||
set_customize(config.get(CONF_CUSTOMIZE) or {})
|
||||
|
||||
if CONF_TEMPERATURE_UNIT in config:
|
||||
hac.temperature_unit = config[CONF_TEMPERATURE_UNIT]
|
||||
if CONF_UNIT_SYSTEM in config:
|
||||
if config[CONF_UNIT_SYSTEM] == CONF_UNIT_SYSTEM_IMPERIAL:
|
||||
hac.units = IMPERIAL_SYSTEM
|
||||
else:
|
||||
hac.units = METRIC_SYSTEM
|
||||
elif CONF_TEMPERATURE_UNIT in config:
|
||||
unit = config[CONF_TEMPERATURE_UNIT]
|
||||
if unit == TEMP_CELSIUS:
|
||||
hac.units = METRIC_SYSTEM
|
||||
else:
|
||||
hac.units = IMPERIAL_SYSTEM
|
||||
_LOGGER.warning("Found deprecated temperature unit in core config, "
|
||||
"expected unit system. Replace 'temperature: %s' with "
|
||||
"'unit_system: %s'", unit, hac.units.name)
|
||||
|
||||
# Shortcut if no auto-detection necessary
|
||||
if None not in (hac.latitude, hac.longitude, hac.temperature_unit,
|
||||
if None not in (hac.latitude, hac.longitude, hac.units,
|
||||
hac.time_zone, hac.elevation):
|
||||
return
|
||||
|
||||
discovered = []
|
||||
|
||||
# If we miss some of the needed values, auto detect them
|
||||
if None in (hac.latitude, hac.longitude, hac.temperature_unit,
|
||||
if None in (hac.latitude, hac.longitude, hac.units,
|
||||
hac.time_zone):
|
||||
info = loc_util.detect_location_info()
|
||||
|
||||
@ -264,18 +283,13 @@ def process_ha_core_config(hass, config):
|
||||
return
|
||||
|
||||
if hac.latitude is None and hac.longitude is None:
|
||||
hac.latitude = info.latitude
|
||||
hac.longitude = info.longitude
|
||||
hac.latitude, hac.longitude = (info.latitude, info.longitude)
|
||||
discovered.append(('latitude', hac.latitude))
|
||||
discovered.append(('longitude', hac.longitude))
|
||||
|
||||
if hac.temperature_unit is None:
|
||||
if info.use_fahrenheit:
|
||||
hac.temperature_unit = TEMP_FAHRENHEIT
|
||||
discovered.append(('temperature_unit', 'F'))
|
||||
else:
|
||||
hac.temperature_unit = TEMP_CELSIUS
|
||||
discovered.append(('temperature_unit', 'C'))
|
||||
if hac.units is None:
|
||||
hac.units = METRIC_SYSTEM if info.use_metric else IMPERIAL_SYSTEM
|
||||
discovered.append((CONF_UNIT_SYSTEM, hac.units.name))
|
||||
|
||||
if hac.location_name is None:
|
||||
hac.location_name = info.city
|
||||
|
@ -47,6 +47,7 @@ CONF_PORT = 'port'
|
||||
CONF_SCAN_INTERVAL = 'scan_interval'
|
||||
CONF_STATE = 'state'
|
||||
CONF_TEMPERATURE_UNIT = 'temperature_unit'
|
||||
CONF_UNIT_SYSTEM = 'unit_system'
|
||||
CONF_TIME_ZONE = 'time_zone'
|
||||
CONF_USERNAME = 'username'
|
||||
CONF_VALUE_TEMPLATE = 'value_template'
|
||||
@ -112,11 +113,38 @@ ATTR_ICON = "icon"
|
||||
# The unit of measurement if applicable
|
||||
ATTR_UNIT_OF_MEASUREMENT = "unit_of_measurement"
|
||||
|
||||
CONF_UNIT_SYSTEM_METRIC = 'metric' # type: str
|
||||
CONF_UNIT_SYSTEM_IMPERIAL = 'imperial' # type: str
|
||||
|
||||
# Temperature attribute
|
||||
ATTR_TEMPERATURE = "temperature"
|
||||
TEMP_CELSIUS = "°C"
|
||||
TEMP_FAHRENHEIT = "°F"
|
||||
|
||||
# Length units
|
||||
LENGTH_CENTIMETERS = "cm" # type: str
|
||||
LENGTH_METERS = "m" # type: str
|
||||
LENGTH_KILOMETERS = "km" # type: str
|
||||
|
||||
LENGTH_INCHES = "in" # type: str
|
||||
LENGTH_FEET = "ft" # type: str
|
||||
LENGTH_YARD = "yd" # type: str
|
||||
LENGTH_MILES = "mi" # type: str
|
||||
|
||||
# Volume units
|
||||
VOLUME_LITERS = "L" # type: str
|
||||
VOLUME_MILLILITERS = "mL" # type: str
|
||||
|
||||
VOLUME_GALLONS = "gal" # type: str
|
||||
VOLUME_FLUID_OUNCE = "fl. oz." # type: str
|
||||
|
||||
# Mass units
|
||||
MASS_GRAMS = "g" # type: str
|
||||
MASS_KILOGRAMS = "kg" # type: str
|
||||
|
||||
MASS_OUNCES = "oz" # type: str
|
||||
MASS_POUNDS = "lb" # type: str
|
||||
|
||||
# Contains the information that is discovered
|
||||
ATTR_DISCOVERED = "discovered"
|
||||
|
||||
@ -243,3 +271,10 @@ CONTENT_TYPE_TEXT_PLAIN = 'text/plain'
|
||||
|
||||
# The exit code to send to request a restart
|
||||
RESTART_EXIT_CODE = 100
|
||||
|
||||
UNIT_NOT_RECOGNIZED_TEMPLATE = '{} is not a recognized {} unit.' # type: str
|
||||
|
||||
LENGTH = 'length' # type: str
|
||||
MASS = 'mass' # type: str
|
||||
VOLUME = 'volume' # type: str
|
||||
TEMPERATURE = 'temperature' # type: str
|
||||
|
@ -17,7 +17,6 @@ from types import MappingProxyType
|
||||
from typing import Any, Callable
|
||||
import voluptuous as vol
|
||||
|
||||
import homeassistant.helpers.temperature as temp_helper
|
||||
import homeassistant.util as util
|
||||
import homeassistant.util.dt as dt_util
|
||||
import homeassistant.util.location as location
|
||||
@ -28,11 +27,13 @@ from homeassistant.const import (
|
||||
EVENT_HOMEASSISTANT_START, EVENT_HOMEASSISTANT_STOP,
|
||||
EVENT_SERVICE_EXECUTED, EVENT_SERVICE_REGISTERED, EVENT_STATE_CHANGED,
|
||||
EVENT_TIME_CHANGED, MATCH_ALL, RESTART_EXIT_CODE,
|
||||
SERVICE_HOMEASSISTANT_RESTART, SERVICE_HOMEASSISTANT_STOP, TEMP_CELSIUS,
|
||||
TEMP_FAHRENHEIT, __version__)
|
||||
SERVICE_HOMEASSISTANT_RESTART, SERVICE_HOMEASSISTANT_STOP, __version__)
|
||||
from homeassistant.exceptions import (
|
||||
HomeAssistantError, InvalidEntityFormatError)
|
||||
from homeassistant.helpers.entity import split_entity_id, valid_entity_id
|
||||
from homeassistant.helpers.unit_system import (
|
||||
METRIC_SYSTEM,
|
||||
)
|
||||
|
||||
DOMAIN = "homeassistant"
|
||||
|
||||
@ -95,7 +96,7 @@ class HomeAssistant(object):
|
||||
self.bus = EventBus(pool)
|
||||
self.services = ServiceRegistry(self.bus, self.add_job)
|
||||
self.states = StateMachine(self.bus)
|
||||
self.config = Config()
|
||||
self.config = Config() # type: Config
|
||||
self.state = CoreState.not_running
|
||||
|
||||
@property
|
||||
@ -715,9 +716,9 @@ class Config(object):
|
||||
self.latitude = None
|
||||
self.longitude = None
|
||||
self.elevation = None
|
||||
self.temperature_unit = None
|
||||
self.location_name = None
|
||||
self.time_zone = None
|
||||
self.units = METRIC_SYSTEM
|
||||
|
||||
# If True, pip install is skipped for requirements on startup
|
||||
self.skip_pip = False
|
||||
@ -731,29 +732,15 @@ class Config(object):
|
||||
# Directory that holds the configuration
|
||||
self.config_dir = get_default_config_dir()
|
||||
|
||||
def distance(self, lat, lon):
|
||||
"""Calculate distance from Home Assistant in meters."""
|
||||
return location.distance(self.latitude, self.longitude, lat, lon)
|
||||
def distance(self: object, lat: float, lon: float) -> float:
|
||||
"""Calculate distance from Home Assistant."""
|
||||
return self.units.length(
|
||||
location.distance(self.latitude, self.longitude, lat, lon), 'm')
|
||||
|
||||
def path(self, *path):
|
||||
"""Generate path to the file within the config dir."""
|
||||
return os.path.join(self.config_dir, *path)
|
||||
|
||||
def temperature(self, value, unit):
|
||||
"""Convert temperature to user preferred unit if set."""
|
||||
if not (unit in (TEMP_CELSIUS, TEMP_FAHRENHEIT) and
|
||||
self.temperature_unit and unit != self.temperature_unit):
|
||||
return value, unit
|
||||
|
||||
try:
|
||||
temp = float(value)
|
||||
except ValueError: # Could not convert value to float
|
||||
return value, unit
|
||||
|
||||
return (
|
||||
round(temp_helper.convert(temp, unit, self.temperature_unit), 1),
|
||||
self.temperature_unit)
|
||||
|
||||
def as_dict(self):
|
||||
"""Create a dict representation of this dict."""
|
||||
time_zone = self.time_zone or dt_util.UTC
|
||||
@ -761,7 +748,7 @@ class Config(object):
|
||||
return {
|
||||
'latitude': self.latitude,
|
||||
'longitude': self.longitude,
|
||||
'temperature_unit': self.temperature_unit,
|
||||
'unit_system': self.units.as_dict(),
|
||||
'location_name': self.location_name,
|
||||
'time_zone': time_zone.zone,
|
||||
'components': self.components,
|
||||
|
@ -9,7 +9,7 @@ from homeassistant.const import (
|
||||
CONF_PLATFORM, CONF_SCAN_INTERVAL, TEMP_CELSIUS, TEMP_FAHRENHEIT,
|
||||
CONF_ALIAS, CONF_ENTITY_ID, CONF_VALUE_TEMPLATE, WEEKDAYS,
|
||||
CONF_CONDITION, CONF_BELOW, CONF_ABOVE, SUN_EVENT_SUNSET,
|
||||
SUN_EVENT_SUNRISE)
|
||||
SUN_EVENT_SUNRISE, CONF_UNIT_SYSTEM_IMPERIAL, CONF_UNIT_SYSTEM_METRIC)
|
||||
from homeassistant.helpers.entity import valid_entity_id
|
||||
import homeassistant.util.dt as dt_util
|
||||
from homeassistant.util import slugify
|
||||
@ -226,6 +226,10 @@ def temperature_unit(value):
|
||||
raise vol.Invalid('invalid temperature unit (expected C or F)')
|
||||
|
||||
|
||||
unit_system = vol.All(vol.Lower, vol.Any(CONF_UNIT_SYSTEM_METRIC,
|
||||
CONF_UNIT_SYSTEM_IMPERIAL))
|
||||
|
||||
|
||||
def template(value):
|
||||
"""Validate a jinja2 template."""
|
||||
if value is None:
|
||||
|
@ -199,13 +199,15 @@ class Entity(object):
|
||||
attr.pop(ATTR_HIDDEN)
|
||||
|
||||
# Convert temperature if we detect one
|
||||
if attr.get(ATTR_UNIT_OF_MEASUREMENT) in (TEMP_CELSIUS,
|
||||
TEMP_FAHRENHEIT):
|
||||
|
||||
state, attr[ATTR_UNIT_OF_MEASUREMENT] = \
|
||||
self.hass.config.temperature(
|
||||
state, attr[ATTR_UNIT_OF_MEASUREMENT])
|
||||
state = str(state)
|
||||
try:
|
||||
unit_of_measure = attr.get(ATTR_UNIT_OF_MEASUREMENT)
|
||||
if unit_of_measure in (TEMP_CELSIUS, TEMP_FAHRENHEIT):
|
||||
units = self.hass.config.units
|
||||
state = str(units.temperature(float(state), unit_of_measure))
|
||||
attr[ATTR_UNIT_OF_MEASUREMENT] = units.temperature_unit
|
||||
except ValueError:
|
||||
# Could not convert state to float
|
||||
pass
|
||||
|
||||
return self.hass.states.set(
|
||||
self.entity_id, state, attr, self.force_update)
|
||||
|
@ -1,13 +0,0 @@
|
||||
"""Methods to help handle temperature in Home Assistant."""
|
||||
import homeassistant.util.temperature as temp_util
|
||||
from homeassistant.const import TEMP_CELSIUS
|
||||
|
||||
|
||||
def convert(temperature, unit, to_unit):
|
||||
"""Convert temperature to correct unit."""
|
||||
if unit == to_unit or unit is None or to_unit is None:
|
||||
return temperature
|
||||
elif unit == TEMP_CELSIUS:
|
||||
return temp_util.celsius_to_fahrenheit(temperature)
|
||||
|
||||
return temp_util.fahrenheit_to_celsius(temperature)
|
@ -219,7 +219,8 @@ class LocationMethods(object):
|
||||
if len(locations) == 1:
|
||||
return self._hass.config.distance(*locations[0])
|
||||
|
||||
return loc_util.distance(*locations[0] + locations[1])
|
||||
return self._hass.config.units.length(
|
||||
loc_util.distance(*locations[0] + locations[1]), 'm')
|
||||
|
||||
def _resolve_state(self, entity_id_or_state):
|
||||
"""Return state or entity_id if given."""
|
||||
|
125
homeassistant/helpers/unit_system.py
Normal file
125
homeassistant/helpers/unit_system.py
Normal file
@ -0,0 +1,125 @@
|
||||
"""Unit system helper class and methods."""
|
||||
|
||||
import logging
|
||||
from numbers import Number
|
||||
from homeassistant.const import (
|
||||
TEMP_CELSIUS, TEMP_FAHRENHEIT, LENGTH_CENTIMETERS, LENGTH_METERS,
|
||||
LENGTH_KILOMETERS, LENGTH_INCHES, LENGTH_FEET, LENGTH_YARD, LENGTH_MILES,
|
||||
VOLUME_LITERS, VOLUME_MILLILITERS, VOLUME_GALLONS, VOLUME_FLUID_OUNCE,
|
||||
MASS_GRAMS, MASS_KILOGRAMS, MASS_OUNCES, MASS_POUNDS,
|
||||
CONF_UNIT_SYSTEM_METRIC,
|
||||
CONF_UNIT_SYSTEM_IMPERIAL, LENGTH, MASS, VOLUME, TEMPERATURE,
|
||||
UNIT_NOT_RECOGNIZED_TEMPLATE)
|
||||
from homeassistant.util import temperature as temperature_util
|
||||
from homeassistant.util import distance as distance_util
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
LENGTH_UNITS = [
|
||||
LENGTH_MILES,
|
||||
LENGTH_YARD,
|
||||
LENGTH_FEET,
|
||||
LENGTH_INCHES,
|
||||
LENGTH_KILOMETERS,
|
||||
LENGTH_METERS,
|
||||
LENGTH_CENTIMETERS,
|
||||
]
|
||||
|
||||
MASS_UNITS = [
|
||||
MASS_POUNDS,
|
||||
MASS_OUNCES,
|
||||
MASS_KILOGRAMS,
|
||||
MASS_GRAMS,
|
||||
]
|
||||
|
||||
VOLUME_UNITS = [
|
||||
VOLUME_GALLONS,
|
||||
VOLUME_FLUID_OUNCE,
|
||||
VOLUME_LITERS,
|
||||
VOLUME_MILLILITERS,
|
||||
]
|
||||
|
||||
TEMPERATURE_UNITS = [
|
||||
TEMP_FAHRENHEIT,
|
||||
TEMP_CELSIUS,
|
||||
]
|
||||
|
||||
|
||||
def is_valid_unit(unit: str, unit_type: str) -> bool:
|
||||
"""Check if the unit is valid for it's type."""
|
||||
if unit_type == LENGTH:
|
||||
units = LENGTH_UNITS
|
||||
elif unit_type == TEMPERATURE:
|
||||
units = TEMPERATURE_UNITS
|
||||
elif unit_type == MASS:
|
||||
units = MASS_UNITS
|
||||
elif unit_type == VOLUME:
|
||||
units = VOLUME_UNITS
|
||||
else:
|
||||
return False
|
||||
|
||||
return unit in units
|
||||
|
||||
|
||||
class UnitSystem(object):
|
||||
"""A container for units of measure."""
|
||||
|
||||
# pylint: disable=too-many-arguments
|
||||
def __init__(self: object, name: str, temperature: str, length: str,
|
||||
volume: str, mass: str) -> None:
|
||||
"""Initialize the unit system object."""
|
||||
errors = \
|
||||
', '.join(UNIT_NOT_RECOGNIZED_TEMPLATE.format(unit, unit_type)
|
||||
for unit, unit_type in [
|
||||
(temperature, TEMPERATURE),
|
||||
(length, LENGTH),
|
||||
(volume, VOLUME),
|
||||
(mass, MASS), ]
|
||||
if not is_valid_unit(unit, unit_type)) # type: str
|
||||
|
||||
if errors:
|
||||
raise ValueError(errors)
|
||||
|
||||
self.name = name
|
||||
self.temperature_unit = temperature
|
||||
self.length_unit = length
|
||||
self.mass_unit = mass
|
||||
self.volume_unit = volume
|
||||
|
||||
@property
|
||||
def is_metric(self: object) -> bool:
|
||||
"""Determine if this is the metric unit system."""
|
||||
return self.name == CONF_UNIT_SYSTEM_METRIC
|
||||
|
||||
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 length(self: object, length: float, from_unit: str) -> float:
|
||||
"""Convert the given length to this unit system."""
|
||||
if not isinstance(length, Number):
|
||||
raise TypeError('{} is not a numeric value.'.format(str(length)))
|
||||
|
||||
return distance_util.convert(length, from_unit,
|
||||
self.length_unit) # type: float
|
||||
|
||||
def as_dict(self) -> dict:
|
||||
"""Convert the unit system to a dictionary."""
|
||||
return {
|
||||
LENGTH: self.length_unit,
|
||||
MASS: self.mass_unit,
|
||||
TEMPERATURE: self.temperature_unit,
|
||||
VOLUME: self.volume_unit
|
||||
}
|
||||
|
||||
|
||||
METRIC_SYSTEM = UnitSystem(CONF_UNIT_SYSTEM_METRIC, TEMP_CELSIUS,
|
||||
LENGTH_KILOMETERS, VOLUME_LITERS, MASS_GRAMS)
|
||||
|
||||
IMPERIAL_SYSTEM = UnitSystem(CONF_UNIT_SYSTEM_IMPERIAL, TEMP_FAHRENHEIT,
|
||||
LENGTH_MILES, VOLUME_GALLONS, MASS_POUNDS)
|
@ -3,82 +3,86 @@
|
||||
import logging
|
||||
from numbers import Number
|
||||
|
||||
from homeassistant.const import (
|
||||
LENGTH_KILOMETERS,
|
||||
LENGTH_MILES,
|
||||
LENGTH_FEET,
|
||||
LENGTH_METERS,
|
||||
UNIT_NOT_RECOGNIZED_TEMPLATE,
|
||||
LENGTH,
|
||||
)
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
KILOMETERS_SYMBOL = 'km'
|
||||
METERS_SYMBOL = 'm'
|
||||
FEET_SYMBOL = 'ft'
|
||||
MILES_SYMBOL = 'mi'
|
||||
|
||||
VALID_UNITS = [
|
||||
KILOMETERS_SYMBOL,
|
||||
METERS_SYMBOL,
|
||||
FEET_SYMBOL,
|
||||
MILES_SYMBOL,
|
||||
LENGTH_KILOMETERS,
|
||||
LENGTH_MILES,
|
||||
LENGTH_FEET,
|
||||
LENGTH_METERS,
|
||||
]
|
||||
|
||||
|
||||
def convert(value, unit_1, unit_2):
|
||||
def convert(value: float, unit_1: str, unit_2: str) -> float:
|
||||
"""Convert one unit of measurement to another."""
|
||||
if not isinstance(value, Number):
|
||||
raise TypeError(str(value) + ' is not of numeric type')
|
||||
|
||||
if unit_1 == unit_2:
|
||||
return value
|
||||
|
||||
if unit_1 not in VALID_UNITS:
|
||||
_LOGGER.error('Unknown unit of measure: ' + str(unit_1))
|
||||
raise ValueError('Unknown unit of measure: ' + str(unit_1))
|
||||
elif unit_2 not in VALID_UNITS:
|
||||
_LOGGER.error('Unknown unit of measure: ' + str(unit_2))
|
||||
raise ValueError('Unknown unit of measure: ' + str(unit_2))
|
||||
raise ValueError(
|
||||
UNIT_NOT_RECOGNIZED_TEMPLATE.format(unit_1, LENGTH))
|
||||
if unit_2 not in VALID_UNITS:
|
||||
raise ValueError(
|
||||
UNIT_NOT_RECOGNIZED_TEMPLATE.format(unit_2, LENGTH))
|
||||
|
||||
if not isinstance(value, Number):
|
||||
raise TypeError('{} is not of numeric type'.format(value))
|
||||
|
||||
if unit_1 == unit_2 or unit_1 not in VALID_UNITS:
|
||||
return value
|
||||
|
||||
meters = value
|
||||
|
||||
if unit_1 == MILES_SYMBOL:
|
||||
if unit_1 == LENGTH_MILES:
|
||||
meters = __miles_to_meters(value)
|
||||
elif unit_1 == FEET_SYMBOL:
|
||||
elif unit_1 == LENGTH_FEET:
|
||||
meters = __feet_to_meters(value)
|
||||
elif unit_1 == KILOMETERS_SYMBOL:
|
||||
elif unit_1 == LENGTH_KILOMETERS:
|
||||
meters = __kilometers_to_meters(value)
|
||||
|
||||
result = meters
|
||||
|
||||
if unit_2 == MILES_SYMBOL:
|
||||
if unit_2 == LENGTH_MILES:
|
||||
result = __meters_to_miles(meters)
|
||||
elif unit_2 == FEET_SYMBOL:
|
||||
elif unit_2 == LENGTH_FEET:
|
||||
result = __meters_to_feet(meters)
|
||||
elif unit_2 == KILOMETERS_SYMBOL:
|
||||
elif unit_2 == LENGTH_KILOMETERS:
|
||||
result = __meters_to_kilometers(meters)
|
||||
|
||||
return result
|
||||
|
||||
|
||||
def __miles_to_meters(miles):
|
||||
def __miles_to_meters(miles: float) -> float:
|
||||
"""Convert miles to meters."""
|
||||
return miles * 1609.344
|
||||
|
||||
|
||||
def __feet_to_meters(feet):
|
||||
def __feet_to_meters(feet: float) -> float:
|
||||
"""Convert feet to meters."""
|
||||
return feet * 0.3048
|
||||
|
||||
|
||||
def __kilometers_to_meters(kilometers):
|
||||
def __kilometers_to_meters(kilometers: float) -> float:
|
||||
"""Convert kilometers to meters."""
|
||||
return kilometers * 1000
|
||||
|
||||
|
||||
def __meters_to_miles(meters):
|
||||
def __meters_to_miles(meters: float) -> float:
|
||||
"""Convert meters to miles."""
|
||||
return meters * 0.000621371
|
||||
|
||||
|
||||
def __meters_to_feet(meters):
|
||||
def __meters_to_feet(meters: float) -> float:
|
||||
"""Convert meters to feet."""
|
||||
return meters * 3.28084
|
||||
|
||||
|
||||
def __meters_to_kilometers(meters):
|
||||
def __meters_to_kilometers(meters: float) -> float:
|
||||
"""Convert meters to kilometers."""
|
||||
return meters * 0.001
|
||||
|
@ -31,7 +31,7 @@ LocationInfo = collections.namedtuple(
|
||||
"LocationInfo",
|
||||
['ip', 'country_code', 'country_name', 'region_code', 'region_name',
|
||||
'city', 'zip_code', 'time_zone', 'latitude', 'longitude',
|
||||
'use_fahrenheit'])
|
||||
'use_metric'])
|
||||
|
||||
|
||||
def detect_location_info():
|
||||
@ -44,11 +44,8 @@ def detect_location_info():
|
||||
if data is None:
|
||||
return None
|
||||
|
||||
# From Wikipedia: Fahrenheit is used in the Bahamas, Belize,
|
||||
# the Cayman Islands, Palau, and the United States and associated
|
||||
# territories of American Samoa and the U.S. Virgin Islands
|
||||
data['use_fahrenheit'] = data['country_code'] in (
|
||||
'BS', 'BZ', 'KY', 'PW', 'US', 'AS', 'VI')
|
||||
data['use_metric'] = data['country_code'] not in (
|
||||
'US', 'MM', 'LR')
|
||||
|
||||
return LocationInfo(**data)
|
||||
|
||||
|
@ -1,4 +1,10 @@
|
||||
"""Temperature util functions."""
|
||||
from homeassistant.const import (
|
||||
TEMP_CELSIUS,
|
||||
TEMP_FAHRENHEIT,
|
||||
UNIT_NOT_RECOGNIZED_TEMPLATE,
|
||||
TEMPERATURE
|
||||
)
|
||||
|
||||
|
||||
def fahrenheit_to_celsius(fahrenheit: float) -> float:
|
||||
@ -9,3 +15,20 @@ def fahrenheit_to_celsius(fahrenheit: float) -> float:
|
||||
def celsius_to_fahrenheit(celsius: float) -> float:
|
||||
"""Convert a Celsius temperature to Fahrenheit."""
|
||||
return celsius * 1.8 + 32.0
|
||||
|
||||
|
||||
def convert(temperature: float, from_unit: str, to_unit: str) -> float:
|
||||
"""Convert a temperature from one unit to another."""
|
||||
if from_unit not in (TEMP_CELSIUS, TEMP_FAHRENHEIT):
|
||||
raise ValueError(UNIT_NOT_RECOGNIZED_TEMPLATE.format(from_unit,
|
||||
TEMPERATURE))
|
||||
if to_unit not in (TEMP_CELSIUS, TEMP_FAHRENHEIT):
|
||||
raise ValueError(UNIT_NOT_RECOGNIZED_TEMPLATE.format(to_unit,
|
||||
TEMPERATURE))
|
||||
|
||||
if from_unit == to_unit:
|
||||
return temperature
|
||||
elif from_unit == TEMP_CELSIUS:
|
||||
return celsius_to_fahrenheit(temperature)
|
||||
else:
|
||||
return round(fahrenheit_to_celsius(temperature), 1)
|
||||
|
@ -6,11 +6,12 @@ from unittest import mock
|
||||
from homeassistant import core as ha, loader
|
||||
from homeassistant.bootstrap import _setup_component
|
||||
from homeassistant.helpers.entity import ToggleEntity
|
||||
from homeassistant.helpers.unit_system import METRIC_SYSTEM
|
||||
import homeassistant.util.dt as date_util
|
||||
from homeassistant.const import (
|
||||
STATE_ON, STATE_OFF, DEVICE_DEFAULT_NAME, EVENT_TIME_CHANGED,
|
||||
EVENT_STATE_CHANGED, EVENT_PLATFORM_DISCOVERED, ATTR_SERVICE,
|
||||
ATTR_DISCOVERED, SERVER_PORT, TEMP_CELSIUS)
|
||||
ATTR_DISCOVERED, SERVER_PORT)
|
||||
from homeassistant.components import sun, mqtt
|
||||
|
||||
_TEST_INSTANCE_PORT = SERVER_PORT
|
||||
@ -37,7 +38,7 @@ def get_test_home_assistant(num_threads=None):
|
||||
hass.config.longitude = -117.22743
|
||||
hass.config.elevation = 0
|
||||
hass.config.time_zone = date_util.get_time_zone('US/Pacific')
|
||||
hass.config.temperature_unit = TEMP_CELSIUS
|
||||
hass.config.units = METRIC_SYSTEM
|
||||
|
||||
if 'custom_components.test' not in loader.AVAILABLE_COMPONENTS:
|
||||
loader.prepare(hass)
|
||||
|
@ -1,8 +1,8 @@
|
||||
"""The tests for the demo hvac."""
|
||||
import unittest
|
||||
|
||||
from homeassistant.const import (
|
||||
TEMP_CELSIUS,
|
||||
from homeassistant.helpers.unit_system import (
|
||||
METRIC_SYSTEM,
|
||||
)
|
||||
from homeassistant.components import hvac
|
||||
|
||||
@ -18,7 +18,7 @@ class TestDemoHvac(unittest.TestCase):
|
||||
def setUp(self): # pylint: disable=invalid-name
|
||||
"""Setup things to be run when tests are started."""
|
||||
self.hass = get_test_home_assistant()
|
||||
self.hass.config.temperature_unit = TEMP_CELSIUS
|
||||
self.hass.config.units = METRIC_SYSTEM
|
||||
self.assertTrue(hvac.setup(self.hass, {'hvac': {
|
||||
'platform': 'demo',
|
||||
}}))
|
||||
|
@ -1,8 +1,8 @@
|
||||
"""The tests for the demo thermostat."""
|
||||
import unittest
|
||||
|
||||
from homeassistant.const import (
|
||||
TEMP_CELSIUS,
|
||||
from homeassistant.helpers.unit_system import (
|
||||
METRIC_SYSTEM,
|
||||
)
|
||||
from homeassistant.components import thermostat
|
||||
|
||||
@ -18,7 +18,7 @@ class TestDemoThermostat(unittest.TestCase):
|
||||
def setUp(self): # pylint: disable=invalid-name
|
||||
"""Setup things to be run when tests are started."""
|
||||
self.hass = get_test_home_assistant()
|
||||
self.hass.config.temperature_unit = TEMP_CELSIUS
|
||||
self.hass.config.units = METRIC_SYSTEM
|
||||
self.assertTrue(thermostat.setup(self.hass, {'thermostat': {
|
||||
'platform': 'demo',
|
||||
}}))
|
||||
@ -43,10 +43,10 @@ class TestDemoThermostat(unittest.TestCase):
|
||||
|
||||
def test_set_target_temp_bad_attr(self):
|
||||
"""Test setting the target temperature without required attribute."""
|
||||
self.assertEqual('21', self.hass.states.get(ENTITY_NEST).state)
|
||||
self.assertEqual('21.0', self.hass.states.get(ENTITY_NEST).state)
|
||||
thermostat.set_temperature(self.hass, None, ENTITY_NEST)
|
||||
self.hass.pool.block_till_done()
|
||||
self.assertEqual('21', self.hass.states.get(ENTITY_NEST).state)
|
||||
self.assertEqual('21.0', self.hass.states.get(ENTITY_NEST).state)
|
||||
|
||||
def test_set_target_temp(self):
|
||||
"""Test the setting of the target temperature."""
|
||||
|
@ -10,6 +10,7 @@ from homeassistant.const import (
|
||||
STATE_OFF,
|
||||
TEMP_CELSIUS,
|
||||
)
|
||||
from homeassistant.helpers.unit_system import METRIC_SYSTEM
|
||||
from homeassistant.components import thermostat
|
||||
|
||||
from tests.common import get_test_home_assistant
|
||||
@ -75,7 +76,7 @@ class TestThermostatHeatControl(unittest.TestCase):
|
||||
def setUp(self): # pylint: disable=invalid-name
|
||||
"""Setup things to be run when tests are started."""
|
||||
self.hass = get_test_home_assistant()
|
||||
self.hass.config.temperature_unit = TEMP_CELSIUS
|
||||
self.hass.config.units = METRIC_SYSTEM
|
||||
thermostat.setup(self.hass, {'thermostat': {
|
||||
'platform': 'heat_control',
|
||||
'name': 'test',
|
||||
@ -123,19 +124,29 @@ class TestThermostatHeatControl(unittest.TestCase):
|
||||
|
||||
def test_sensor_bad_unit(self):
|
||||
"""Test sensor that have bad unit."""
|
||||
state = self.hass.states.get(ENTITY)
|
||||
temp = state.attributes.get('current_temperature')
|
||||
unit = state.attributes.get('unit_of_measurement')
|
||||
|
||||
self._setup_sensor(22.0, unit='bad_unit')
|
||||
self.hass.pool.block_till_done()
|
||||
|
||||
state = self.hass.states.get(ENTITY)
|
||||
self.assertEqual(None, state.attributes.get('unit_of_measurement'))
|
||||
self.assertEqual(None, state.attributes.get('current_temperature'))
|
||||
self.assertEqual(unit, state.attributes.get('unit_of_measurement'))
|
||||
self.assertEqual(temp, state.attributes.get('current_temperature'))
|
||||
|
||||
def test_sensor_bad_value(self):
|
||||
"""Test sensor that have None as state."""
|
||||
state = self.hass.states.get(ENTITY)
|
||||
temp = state.attributes.get('current_temperature')
|
||||
unit = state.attributes.get('unit_of_measurement')
|
||||
|
||||
self._setup_sensor(None)
|
||||
self.hass.pool.block_till_done()
|
||||
|
||||
state = self.hass.states.get(ENTITY)
|
||||
self.assertEqual(None, state.attributes.get('unit_of_measurement'))
|
||||
self.assertEqual(None, state.attributes.get('current_temperature'))
|
||||
self.assertEqual(unit, state.attributes.get('unit_of_measurement'))
|
||||
self.assertEqual(temp, state.attributes.get('current_temperature'))
|
||||
|
||||
def test_set_target_temp_heater_on(self):
|
||||
"""Test if target temperature turn heater on."""
|
||||
|
@ -6,6 +6,13 @@ from unittest.mock import patch
|
||||
from homeassistant.components import group
|
||||
from homeassistant.exceptions import TemplateError
|
||||
from homeassistant.helpers import template
|
||||
from homeassistant.helpers.unit_system import UnitSystem
|
||||
from homeassistant.const import (
|
||||
LENGTH_METERS,
|
||||
TEMP_CELSIUS,
|
||||
MASS_GRAMS,
|
||||
VOLUME_LITERS,
|
||||
)
|
||||
import homeassistant.util.dt as dt_util
|
||||
|
||||
from tests.common import get_test_home_assistant
|
||||
@ -17,6 +24,9 @@ class TestUtilTemplate(unittest.TestCase):
|
||||
def setUp(self): # pylint: disable=invalid-name
|
||||
"""Setup the tests."""
|
||||
self.hass = get_test_home_assistant()
|
||||
self.hass.config.units = UnitSystem('custom', TEMP_CELSIUS,
|
||||
LENGTH_METERS, VOLUME_LITERS,
|
||||
MASS_GRAMS)
|
||||
|
||||
def tearDown(self): # pylint: disable=invalid-name
|
||||
"""Stop down stuff we started."""
|
||||
|
132
tests/helpers/test_unit_system.py
Normal file
132
tests/helpers/test_unit_system.py
Normal file
@ -0,0 +1,132 @@
|
||||
"""Test the unit system helper."""
|
||||
import unittest
|
||||
|
||||
from homeassistant.helpers.unit_system import (
|
||||
UnitSystem,
|
||||
METRIC_SYSTEM,
|
||||
IMPERIAL_SYSTEM,
|
||||
)
|
||||
from homeassistant.const import (
|
||||
LENGTH_METERS,
|
||||
LENGTH_KILOMETERS,
|
||||
MASS_GRAMS,
|
||||
VOLUME_LITERS,
|
||||
TEMP_CELSIUS,
|
||||
LENGTH,
|
||||
MASS,
|
||||
TEMPERATURE,
|
||||
VOLUME
|
||||
)
|
||||
|
||||
SYSTEM_NAME = 'TEST'
|
||||
INVALID_UNIT = 'INVALID'
|
||||
|
||||
|
||||
class TestUnitSystem(unittest.TestCase):
|
||||
"""Test the unit system helper."""
|
||||
|
||||
def test_invalid_units(self):
|
||||
"""Test errors are raised when invalid units are passed in."""
|
||||
with self.assertRaises(ValueError):
|
||||
UnitSystem(SYSTEM_NAME, INVALID_UNIT, LENGTH_METERS, VOLUME_LITERS,
|
||||
MASS_GRAMS)
|
||||
|
||||
with self.assertRaises(ValueError):
|
||||
UnitSystem(SYSTEM_NAME, TEMP_CELSIUS, INVALID_UNIT, VOLUME_LITERS,
|
||||
MASS_GRAMS)
|
||||
|
||||
with self.assertRaises(ValueError):
|
||||
UnitSystem(SYSTEM_NAME, TEMP_CELSIUS, LENGTH_METERS, INVALID_UNIT,
|
||||
MASS_GRAMS)
|
||||
|
||||
with self.assertRaises(ValueError):
|
||||
UnitSystem(SYSTEM_NAME, TEMP_CELSIUS, LENGTH_METERS, VOLUME_LITERS,
|
||||
INVALID_UNIT)
|
||||
|
||||
def test_invalid_value(self):
|
||||
"""Test no conversion happens if value is non-numeric."""
|
||||
with self.assertRaises(TypeError):
|
||||
METRIC_SYSTEM.length('25a', LENGTH_KILOMETERS)
|
||||
with self.assertRaises(TypeError):
|
||||
METRIC_SYSTEM.temperature('50K', TEMP_CELSIUS)
|
||||
|
||||
def test_as_dict(self):
|
||||
"""Test that the as_dict() method returns the expected dictionary."""
|
||||
expected = {
|
||||
LENGTH: LENGTH_KILOMETERS,
|
||||
TEMPERATURE: TEMP_CELSIUS,
|
||||
VOLUME: VOLUME_LITERS,
|
||||
MASS: MASS_GRAMS
|
||||
}
|
||||
|
||||
self.assertEqual(expected, METRIC_SYSTEM.as_dict())
|
||||
|
||||
def test_temperature_same_unit(self):
|
||||
"""Test no conversion happens if to unit is same as from unit."""
|
||||
self.assertEqual(
|
||||
5,
|
||||
METRIC_SYSTEM.temperature(5,
|
||||
METRIC_SYSTEM.temperature_unit))
|
||||
|
||||
def test_temperature_unknown_unit(self):
|
||||
"""Test no conversion happens if unknown unit."""
|
||||
with self.assertRaises(ValueError):
|
||||
METRIC_SYSTEM.temperature(5, 'K')
|
||||
|
||||
def test_temperature_to_metric(self):
|
||||
"""Test temperature conversion to metric system."""
|
||||
self.assertEqual(
|
||||
25,
|
||||
METRIC_SYSTEM.temperature(25, METRIC_SYSTEM.temperature_unit))
|
||||
self.assertEqual(
|
||||
26.7,
|
||||
METRIC_SYSTEM.temperature(80, IMPERIAL_SYSTEM.temperature_unit))
|
||||
|
||||
def test_temperature_to_imperial(self):
|
||||
"""Test temperature conversion to imperial system."""
|
||||
self.assertEqual(
|
||||
77,
|
||||
IMPERIAL_SYSTEM.temperature(77, IMPERIAL_SYSTEM.temperature_unit))
|
||||
self.assertEqual(
|
||||
77,
|
||||
IMPERIAL_SYSTEM.temperature(25, METRIC_SYSTEM.temperature_unit))
|
||||
|
||||
def test_length_unknown_unit(self):
|
||||
"""Test length conversion with unknown from unit."""
|
||||
with self.assertRaises(ValueError):
|
||||
METRIC_SYSTEM.length(5, 'fr')
|
||||
|
||||
def test_length_to_metric(self):
|
||||
"""Test length conversion to metric system."""
|
||||
self.assertEqual(
|
||||
100,
|
||||
METRIC_SYSTEM.length(100, METRIC_SYSTEM.length_unit)
|
||||
)
|
||||
self.assertEqual(
|
||||
8.04672,
|
||||
METRIC_SYSTEM.length(5, IMPERIAL_SYSTEM.length_unit)
|
||||
)
|
||||
|
||||
def test_length_to_imperial(self):
|
||||
"""Test length conversion to imperial system."""
|
||||
self.assertEqual(
|
||||
100,
|
||||
IMPERIAL_SYSTEM.length(100,
|
||||
IMPERIAL_SYSTEM.length_unit)
|
||||
)
|
||||
self.assertEqual(
|
||||
3.106855,
|
||||
IMPERIAL_SYSTEM.length(5, METRIC_SYSTEM.length_unit)
|
||||
)
|
||||
|
||||
def test_properties(self):
|
||||
"""Test the unit properties are returned as expected."""
|
||||
self.assertEqual(LENGTH_KILOMETERS, METRIC_SYSTEM.length_unit)
|
||||
self.assertEqual(TEMP_CELSIUS, METRIC_SYSTEM.temperature_unit)
|
||||
self.assertEqual(MASS_GRAMS, METRIC_SYSTEM.mass_unit)
|
||||
self.assertEqual(VOLUME_LITERS, METRIC_SYSTEM.volume_unit)
|
||||
|
||||
def test_is_metric(self):
|
||||
"""Test the is metric flag."""
|
||||
self.assertTrue(METRIC_SYSTEM.is_metric)
|
||||
self.assertFalse(IMPERIAL_SYSTEM.is_metric)
|
@ -11,9 +11,9 @@ from voluptuous import MultipleInvalid
|
||||
from homeassistant.core import DOMAIN, HomeAssistantError, Config
|
||||
import homeassistant.config as config_util
|
||||
from homeassistant.const import (
|
||||
CONF_LATITUDE, CONF_LONGITUDE, CONF_TEMPERATURE_UNIT, CONF_NAME,
|
||||
CONF_LATITUDE, CONF_LONGITUDE, CONF_UNIT_SYSTEM, CONF_NAME,
|
||||
CONF_TIME_ZONE, CONF_ELEVATION, CONF_CUSTOMIZE, __version__,
|
||||
TEMP_FAHRENHEIT)
|
||||
CONF_UNIT_SYSTEM_METRIC, CONF_UNIT_SYSTEM_IMPERIAL, CONF_TEMPERATURE_UNIT)
|
||||
from homeassistant.util import location as location_util, dt as dt_util
|
||||
from homeassistant.helpers.entity import Entity
|
||||
|
||||
@ -145,7 +145,7 @@ class TestConfig(unittest.TestCase):
|
||||
CONF_LATITUDE: 32.8594,
|
||||
CONF_LONGITUDE: -117.2073,
|
||||
CONF_ELEVATION: 101,
|
||||
CONF_TEMPERATURE_UNIT: 'F',
|
||||
CONF_UNIT_SYSTEM: CONF_UNIT_SYSTEM_METRIC,
|
||||
CONF_NAME: 'Home',
|
||||
CONF_TIME_ZONE: 'America/Los_Angeles'
|
||||
}
|
||||
@ -167,7 +167,7 @@ class TestConfig(unittest.TestCase):
|
||||
|
||||
def test_core_config_schema(self):
|
||||
for value in (
|
||||
{'temperature_unit': 'K'},
|
||||
{CONF_UNIT_SYSTEM: 'K'},
|
||||
{'time_zone': 'non-exist'},
|
||||
{'latitude': '91'},
|
||||
{'longitude': -181},
|
||||
@ -182,7 +182,7 @@ class TestConfig(unittest.TestCase):
|
||||
'name': 'Test name',
|
||||
'latitude': '-23.45',
|
||||
'longitude': '123.45',
|
||||
'temperature_unit': 'c',
|
||||
CONF_UNIT_SYSTEM: CONF_UNIT_SYSTEM_METRIC,
|
||||
'customize': {
|
||||
'sensor.temperature': {
|
||||
'hidden': True,
|
||||
@ -264,7 +264,7 @@ class TestConfig(unittest.TestCase):
|
||||
'longitude': 50,
|
||||
'elevation': 25,
|
||||
'name': 'Huis',
|
||||
'temperature_unit': 'F',
|
||||
CONF_UNIT_SYSTEM: CONF_UNIT_SYSTEM_IMPERIAL,
|
||||
'time_zone': 'America/New_York',
|
||||
})
|
||||
|
||||
@ -272,7 +272,28 @@ class TestConfig(unittest.TestCase):
|
||||
assert config.longitude == 50
|
||||
assert config.elevation == 25
|
||||
assert config.location_name == 'Huis'
|
||||
assert config.temperature_unit == TEMP_FAHRENHEIT
|
||||
assert config.units.name == CONF_UNIT_SYSTEM_IMPERIAL
|
||||
assert config.time_zone.zone == 'America/New_York'
|
||||
|
||||
def test_loading_configuration_temperature_unit(self):
|
||||
"""Test backward compatibility when loading core config."""
|
||||
config = Config()
|
||||
hass = mock.Mock(config=config)
|
||||
|
||||
config_util.process_ha_core_config(hass, {
|
||||
'latitude': 60,
|
||||
'longitude': 50,
|
||||
'elevation': 25,
|
||||
'name': 'Huis',
|
||||
CONF_TEMPERATURE_UNIT: 'C',
|
||||
'time_zone': 'America/New_York',
|
||||
})
|
||||
|
||||
assert config.latitude == 60
|
||||
assert config.longitude == 50
|
||||
assert config.elevation == 25
|
||||
assert config.location_name == 'Huis'
|
||||
assert config.units.name == CONF_UNIT_SYSTEM_METRIC
|
||||
assert config.time_zone.zone == 'America/New_York'
|
||||
|
||||
@mock.patch('homeassistant.util.location.detect_location_info',
|
||||
@ -292,7 +313,8 @@ class TestConfig(unittest.TestCase):
|
||||
assert config.longitude == -117.2073
|
||||
assert config.elevation == 101
|
||||
assert config.location_name == 'San Diego'
|
||||
assert config.temperature_unit == TEMP_FAHRENHEIT
|
||||
assert config.units.name == CONF_UNIT_SYSTEM_METRIC
|
||||
assert config.units.is_metric
|
||||
assert config.time_zone.zone == 'America/Los_Angeles'
|
||||
|
||||
@mock.patch('homeassistant.util.location.detect_location_info',
|
||||
@ -311,5 +333,5 @@ class TestConfig(unittest.TestCase):
|
||||
assert config.longitude == blankConfig.longitude
|
||||
assert config.elevation == blankConfig.elevation
|
||||
assert config.location_name == blankConfig.location_name
|
||||
assert config.temperature_unit == blankConfig.temperature_unit
|
||||
assert config.units == blankConfig.units
|
||||
assert config.time_zone == blankConfig.time_zone
|
||||
|
@ -15,10 +15,10 @@ import homeassistant.core as ha
|
||||
from homeassistant.exceptions import (
|
||||
HomeAssistantError, InvalidEntityFormatError)
|
||||
import homeassistant.util.dt as dt_util
|
||||
from homeassistant.helpers.unit_system import (METRIC_SYSTEM)
|
||||
from homeassistant.const import (
|
||||
__version__, EVENT_HOMEASSISTANT_START, EVENT_HOMEASSISTANT_STOP,
|
||||
EVENT_STATE_CHANGED, ATTR_FRIENDLY_NAME, TEMP_CELSIUS,
|
||||
TEMP_FAHRENHEIT)
|
||||
EVENT_STATE_CHANGED, ATTR_FRIENDLY_NAME, CONF_UNIT_SYSTEM)
|
||||
|
||||
from tests.common import get_test_home_assistant
|
||||
|
||||
@ -465,56 +465,12 @@ class TestConfig(unittest.TestCase):
|
||||
os.path.join(data_dir, ".homeassistant", "dir", "test.conf"),
|
||||
self.config.path("dir", "test.conf"))
|
||||
|
||||
def test_temperature_not_convert_if_no_preference(self):
|
||||
"""No unit conversion to happen if no preference."""
|
||||
self.assertEqual(
|
||||
(25, TEMP_CELSIUS),
|
||||
self.config.temperature(25, TEMP_CELSIUS))
|
||||
self.assertEqual(
|
||||
(80, TEMP_FAHRENHEIT),
|
||||
self.config.temperature(80, TEMP_FAHRENHEIT))
|
||||
|
||||
def test_temperature_not_convert_if_invalid_value(self):
|
||||
"""No unit conversion to happen if no preference."""
|
||||
self.config.temperature_unit = TEMP_FAHRENHEIT
|
||||
self.assertEqual(
|
||||
('25a', TEMP_CELSIUS),
|
||||
self.config.temperature('25a', TEMP_CELSIUS))
|
||||
|
||||
def test_temperature_not_convert_if_invalid_unit(self):
|
||||
"""No unit conversion to happen if no preference."""
|
||||
self.assertEqual(
|
||||
(25, 'Invalid unit'),
|
||||
self.config.temperature(25, 'Invalid unit'))
|
||||
|
||||
def test_temperature_to_convert_to_celsius(self):
|
||||
"""Test temperature conversion to celsius."""
|
||||
self.config.temperature_unit = TEMP_CELSIUS
|
||||
|
||||
self.assertEqual(
|
||||
(25, TEMP_CELSIUS),
|
||||
self.config.temperature(25, TEMP_CELSIUS))
|
||||
self.assertEqual(
|
||||
(26.7, TEMP_CELSIUS),
|
||||
self.config.temperature(80, TEMP_FAHRENHEIT))
|
||||
|
||||
def test_temperature_to_convert_to_fahrenheit(self):
|
||||
"""Test temperature conversion to fahrenheit."""
|
||||
self.config.temperature_unit = TEMP_FAHRENHEIT
|
||||
|
||||
self.assertEqual(
|
||||
(77, TEMP_FAHRENHEIT),
|
||||
self.config.temperature(25, TEMP_CELSIUS))
|
||||
self.assertEqual(
|
||||
(80, TEMP_FAHRENHEIT),
|
||||
self.config.temperature(80, TEMP_FAHRENHEIT))
|
||||
|
||||
def test_as_dict(self):
|
||||
"""Test as dict."""
|
||||
expected = {
|
||||
'latitude': None,
|
||||
'longitude': None,
|
||||
'temperature_unit': None,
|
||||
CONF_UNIT_SYSTEM: METRIC_SYSTEM.as_dict(),
|
||||
'location_name': None,
|
||||
'time_zone': 'UTC',
|
||||
'components': [],
|
||||
|
@ -2,14 +2,11 @@
|
||||
|
||||
import unittest
|
||||
import homeassistant.util.distance as distance_util
|
||||
|
||||
KILOMETERS = distance_util.KILOMETERS_SYMBOL
|
||||
METERS = distance_util.METERS_SYMBOL
|
||||
FEET = distance_util.FEET_SYMBOL
|
||||
MILES = distance_util.MILES_SYMBOL
|
||||
from homeassistant.const import (LENGTH_KILOMETERS, LENGTH_METERS, LENGTH_FEET,
|
||||
LENGTH_MILES)
|
||||
|
||||
INVALID_SYMBOL = 'bob'
|
||||
VALID_SYMBOL = KILOMETERS
|
||||
VALID_SYMBOL = LENGTH_KILOMETERS
|
||||
|
||||
|
||||
class TestDistanceUtil(unittest.TestCase):
|
||||
@ -17,52 +14,78 @@ class TestDistanceUtil(unittest.TestCase):
|
||||
|
||||
def test_convert_same_unit(self):
|
||||
"""Test conversion from any unit to same unit."""
|
||||
self.assertEqual(5, distance_util.convert(5, KILOMETERS, KILOMETERS))
|
||||
self.assertEqual(2, distance_util.convert(2, METERS, METERS))
|
||||
self.assertEqual(10, distance_util.convert(10, MILES, MILES))
|
||||
self.assertEqual(9, distance_util.convert(9, FEET, FEET))
|
||||
self.assertEqual(5,
|
||||
distance_util.convert(5, LENGTH_KILOMETERS,
|
||||
LENGTH_KILOMETERS))
|
||||
self.assertEqual(2,
|
||||
distance_util.convert(2, LENGTH_METERS,
|
||||
LENGTH_METERS))
|
||||
self.assertEqual(10,
|
||||
distance_util.convert(10, LENGTH_MILES, LENGTH_MILES))
|
||||
self.assertEqual(9,
|
||||
distance_util.convert(9, LENGTH_FEET, LENGTH_FEET))
|
||||
|
||||
def test_convert_invalid_unit(self):
|
||||
"""Test exception is thrown for invalid units."""
|
||||
with self.assertRaises(ValueError):
|
||||
distance_util.convert(5, INVALID_SYMBOL, VALID_SYMBOL)
|
||||
distance_util.convert(5, INVALID_SYMBOL,
|
||||
VALID_SYMBOL)
|
||||
|
||||
with self.assertRaises(ValueError):
|
||||
distance_util.convert(5, VALID_SYMBOL, INVALID_SYMBOL)
|
||||
distance_util.convert(5, VALID_SYMBOL,
|
||||
INVALID_SYMBOL)
|
||||
|
||||
def test_convert_nonnumeric_value(self):
|
||||
"""Test exception is thrown for nonnumeric type."""
|
||||
with self.assertRaises(TypeError):
|
||||
distance_util.convert('a', KILOMETERS, METERS)
|
||||
distance_util.convert('a', LENGTH_KILOMETERS, LENGTH_METERS)
|
||||
|
||||
def test_convert_from_miles(self):
|
||||
"""Test conversion from miles to other units."""
|
||||
miles = 5
|
||||
self.assertEqual(distance_util.convert(miles, MILES, KILOMETERS),
|
||||
self.assertEqual(
|
||||
distance_util.convert(miles, LENGTH_MILES, LENGTH_KILOMETERS),
|
||||
8.04672)
|
||||
self.assertEqual(distance_util.convert(miles, MILES, METERS), 8046.72)
|
||||
self.assertEqual(distance_util.convert(miles, MILES, FEET),
|
||||
self.assertEqual(
|
||||
distance_util.convert(miles, LENGTH_MILES, LENGTH_METERS),
|
||||
8046.72)
|
||||
self.assertEqual(
|
||||
distance_util.convert(miles, LENGTH_MILES, LENGTH_FEET),
|
||||
26400.0008448)
|
||||
|
||||
def test_convert_from_feet(self):
|
||||
"""Test conversion from feet to other units."""
|
||||
feet = 5000
|
||||
self.assertEqual(distance_util.convert(feet, FEET, KILOMETERS), 1.524)
|
||||
self.assertEqual(distance_util.convert(feet, FEET, METERS), 1524)
|
||||
self.assertEqual(distance_util.convert(feet, FEET, MILES),
|
||||
self.assertEqual(
|
||||
distance_util.convert(feet, LENGTH_FEET, LENGTH_KILOMETERS),
|
||||
1.524)
|
||||
self.assertEqual(
|
||||
distance_util.convert(feet, LENGTH_FEET, LENGTH_METERS),
|
||||
1524)
|
||||
self.assertEqual(
|
||||
distance_util.convert(feet, LENGTH_FEET, LENGTH_MILES),
|
||||
0.9469694040000001)
|
||||
|
||||
def test_convert_from_kilometers(self):
|
||||
"""Test conversion from kilometers to other units."""
|
||||
km = 5
|
||||
self.assertEqual(distance_util.convert(km, KILOMETERS, FEET), 16404.2)
|
||||
self.assertEqual(distance_util.convert(km, KILOMETERS, METERS), 5000)
|
||||
self.assertEqual(distance_util.convert(km, KILOMETERS, MILES),
|
||||
self.assertEqual(
|
||||
distance_util.convert(km, LENGTH_KILOMETERS, LENGTH_FEET),
|
||||
16404.2)
|
||||
self.assertEqual(
|
||||
distance_util.convert(km, LENGTH_KILOMETERS, LENGTH_METERS),
|
||||
5000)
|
||||
self.assertEqual(
|
||||
distance_util.convert(km, LENGTH_KILOMETERS, LENGTH_MILES),
|
||||
3.106855)
|
||||
|
||||
def test_convert_from_meters(self):
|
||||
"""Test conversion from meters to other units."""
|
||||
m = 5000
|
||||
self.assertEqual(distance_util.convert(m, METERS, FEET), 16404.2)
|
||||
self.assertEqual(distance_util.convert(m, METERS, KILOMETERS), 5)
|
||||
self.assertEqual(distance_util.convert(m, METERS, MILES), 3.106855)
|
||||
self.assertEqual(distance_util.convert(m, LENGTH_METERS, LENGTH_FEET),
|
||||
16404.2)
|
||||
self.assertEqual(
|
||||
distance_util.convert(m, LENGTH_METERS, LENGTH_KILOMETERS),
|
||||
5)
|
||||
self.assertEqual(distance_util.convert(m, LENGTH_METERS, LENGTH_MILES),
|
||||
3.106855)
|
||||
|
@ -79,7 +79,7 @@ class TestLocationUtil(TestCase):
|
||||
assert info.time_zone == 'America/Los_Angeles'
|
||||
assert info.latitude == 32.8594
|
||||
assert info.longitude == -117.2073
|
||||
assert info.use_fahrenheit
|
||||
assert not info.use_metric
|
||||
|
||||
@requests_mock.Mocker()
|
||||
@patch('homeassistant.util.location._get_freegeoip', return_value=None)
|
||||
@ -101,7 +101,7 @@ class TestLocationUtil(TestCase):
|
||||
assert info.time_zone == 'America/Los_Angeles'
|
||||
assert info.latitude == 32.8594
|
||||
assert info.longitude == -117.2073
|
||||
assert info.use_fahrenheit
|
||||
assert not info.use_metric
|
||||
|
||||
@patch('homeassistant.util.location.elevation', return_value=0)
|
||||
@patch('homeassistant.util.location._get_freegeoip', return_value=None)
|
||||
|
Loading…
x
Reference in New Issue
Block a user