mirror of https://github.com/home-assistant/core
Add unit system support
Add unit symbol constants Initial unit system object Import more constants Pydoc for unit system file Import constants for configuration validation Unit system validation method Typing for constants Inches are valid lengths too Typings Change base class to dict - needed for remote api call serialization Validation Use dictionary keys Defined unit systems Update location util to use metric instead of us fahrenheit Update constant imports Import defined unit systems Update configuration to use unit system Update schema to use unit system Update constants Add imports to core for unit system and distance Type for config Default unit system Convert distance from HASS instance Update temperature conversion to use unit system Update temperature conversion Set unit system based on configuration Set info unit system Return unit system dictionary with config dictionary Auto discover unit system Update location test for use metric Update forecast unit system Update mold indicator unit system Update thermostat unit system Update thermostat demo test Unit tests around unit system Update test common hass configuration Update configuration unit tests There should always be a unit system! Update core unit tests Constants typing Linting issues Remove unused import Update fitbit sensor to use application unit system Update google travel time to use application unit system Update configuration example Update dht sensor Update DHT temperature conversion to use the utility function Update swagger config Update my sensors metric flag Update hvac component temperature conversion HVAC conversion for temperature Pull unit from sensor type map Pull unit from sensor type map Update the temper sensor unit Update yWeather sensor unit Update hvac demo unit test Set unit test config unit system to metric Use hass unit system length for default in proximity Use the name of the system instead of temperature Use constants from const Unused import Forecasted temperature Fix calculation in case furthest distance is greater than 1000000 units Remove unneeded constants Set default length to km or miles Use constants Linting doesn't like importing just for typing Fix reference Test is expecting meters - set config to meters Use constant Use constant PyDoc for unit test Should be not in Rename to units Change unit system to be an object - not a dictionary Return tuple in conversion Move convert to temperature util Temperature conversion is now in unit system Update imports Rename to units Units is now an object Use temperature util conversion Unit system is now an object Validate and convert unit system config Return the scalar value in template distance Test is expecting meters Update unit tests around unit system Distance util returns tuple Fix location info test Set units Update unit tests Convert distance DOH Pull out the scalar from the vector Linting I really hate python linting Linting again BLARG Unit test documentation Unit test around is metric flag Break ternary statement into if/else blocks Don't use dictionary - use members is metric flag Rename constants Use is metric flag Move constants to CONST file Move to const file Raise error if unit is not expected Typing No need to return unit since only performing conversion if it can work Use constants Line wrapping Raise error if invalid value Remove subscripts from conversion as they are no longer returned as tuples No longer tuples No longer tuples Check for numeric type Fix string format to use correct variable Typing Assert errors raised Remove subscript Only convert temperature if we know the unit If no unit of measurement set - default to HASS config Convert only if we know the unit Remove subscription Fix not in clause Linting fixes Wants a boolean Clearer if-block Check if the key is in the config first Missed a couple expecting tuples Backwards compatibility No like-y ternary! Error handling around state setting Pretty unit system configuration validation More tuple crap Use is metric flag Error handling around min/max temp Explode if no unit Pull unit from config Celsius has a decimal Unused import Check if it's a temperature before we try to convert it to a temperature Linting says too many statements - combine lat/long in a fairly reasonable manner Backwards compatibility unit test Better doc
This commit is contained in:
parent
792154a6a7
commit
26526ca57a
|
@ -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:
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -61,11 +61,11 @@ class VeraSensor(VeraDevice, Entity):
|
|||
self._temperature_units = TEMP_CELSIUS
|
||||
|
||||
if self.hass:
|
||||
temp = self.hass.config.temperature(
|
||||
temp = self.hass.config.units.temperature(
|
||||
current_temp,
|
||||
self._temperature_units)
|
||||
|
||||
current_temp, self._temperature_units = temp
|
||||
current_temp = temp
|
||||
|
||||
self.current_value = current_temp
|
||||
elif self.vera_device.category == "Light 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,9 +147,13 @@ 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))
|
||||
if thermostat.unit_of_measurement is not None:
|
||||
converted_temperature = convert(
|
||||
temperature, hass.config.units.temperature_unit,
|
||||
thermostat.unit_of_measurement)
|
||||
else:
|
||||
converted_temperature = temperature
|
||||
thermostat.set_temperature(converted_temperature)
|
||||
|
||||
thermostat.update_ha_state(True)
|
||||
|
||||
|
@ -301,22 +306,30 @@ class ThermostatDevice(Entity):
|
|||
@property
|
||||
def min_temp(self):
|
||||
"""Return the minimum temperature."""
|
||||
return convert(7, TEMP_CELSIUS, self.unit_of_measurement)
|
||||
try:
|
||||
unit = self.unit_of_measurement
|
||||
return convert(7, TEMP_CELSIUS, unit)
|
||||
except ValueError:
|
||||
return STATE_UNKNOWN
|
||||
|
||||
@property
|
||||
def max_temp(self):
|
||||
"""Return the maximum temperature."""
|
||||
return convert(35, TEMP_CELSIUS, self.unit_of_measurement)
|
||||
try:
|
||||
unit = self.unit_of_measurement
|
||||
return convert(35, TEMP_CELSIUS, unit)
|
||||
except ValueError:
|
||||
return STATE_UNKNOWN
|
||||
|
||||
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']
|
||||
|
||||
|
|
|
@ -75,7 +75,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)
|
||||
|
||||
|
|
|
@ -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):
|
||||
state = \
|
||||
str(self.hass.config.units.temperature(float(state),
|
||||
unit_of_measure))
|
||||
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."""
|
||||
|
|
|
@ -0,0 +1,126 @@
|
|||
"""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, str):
|
||||
"""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',
|
||||
|
|
|
@ -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."""
|
||||
|
|
|
@ -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),
|
||||
8.04672)
|
||||
self.assertEqual(distance_util.convert(miles, MILES, METERS), 8046.72)
|
||||
self.assertEqual(distance_util.convert(miles, MILES, FEET),
|
||||
26400.0008448)
|
||||
self.assertEqual(
|
||||
distance_util.convert(miles, LENGTH_MILES, LENGTH_KILOMETERS),
|
||||
8.04672)
|
||||
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),
|
||||
0.9469694040000001)
|
||||
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),
|
||||
3.106855)
|
||||
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…
Reference in New Issue