Skip to content
Merged
10 changes: 9 additions & 1 deletion homeassistant/components/proximity/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
LENGTH_FEET,
LENGTH_KILOMETERS,
LENGTH_METERS,
LENGTH_MILES,
LENGTH_YARD,
)
import homeassistant.helpers.config_validation as cv
from homeassistant.helpers.entity import Entity
Expand All @@ -37,7 +39,13 @@
DEFAULT_TOLERANCE = 1
DOMAIN = "proximity"

UNITS = [LENGTH_KILOMETERS, LENGTH_METERS, "mi", LENGTH_FEET]
UNITS = [
LENGTH_METERS,
LENGTH_KILOMETERS,
LENGTH_FEET,
LENGTH_YARD,
LENGTH_MILES,
]

ZONE_SCHEMA = vol.Schema(
{
Expand Down
71 changes: 70 additions & 1 deletion homeassistant/util/distance.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,27 @@

from homeassistant.const import (
LENGTH,
LENGTH_CENTIMETERS,
LENGTH_FEET,
LENGTH_INCHES,
LENGTH_KILOMETERS,
LENGTH_METERS,
LENGTH_MILES,
LENGTH_MILLIMETERS,
LENGTH_YARD,
UNIT_NOT_RECOGNIZED_TEMPLATE,
)

VALID_UNITS = [LENGTH_KILOMETERS, LENGTH_MILES, LENGTH_FEET, LENGTH_METERS]
VALID_UNITS = [
LENGTH_KILOMETERS,
LENGTH_MILES,
LENGTH_FEET,
LENGTH_METERS,
LENGTH_CENTIMETERS,
LENGTH_MILLIMETERS,
LENGTH_INCHES,
LENGTH_YARD,
]


def convert(value: float, unit_1: str, unit_2: str) -> float:
Expand All @@ -30,19 +43,35 @@ def convert(value: float, unit_1: str, unit_2: str) -> float:

if unit_1 == LENGTH_MILES:
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For a future PR, instead of doing hundreds of if…elif statements, we should rewrite this like this:

TO_METERS = {
  LENGTH_METERS: lambda meters: meters,
  LENGTH_YARD: lambda yards: yards * 0.9144,
  LENGTH_FEET: lambda feet: feet * 0.3048,
  ...
}

meters = TO_METERS[unit_1](value)

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done in #43107

meters = __miles_to_meters(value)
elif unit_1 == LENGTH_YARD:
meters = __yards_to_meters(value)
elif unit_1 == LENGTH_FEET:
meters = __feet_to_meters(value)
elif unit_1 == LENGTH_INCHES:
meters = __inches_to_meters(value)
elif unit_1 == LENGTH_KILOMETERS:
meters = __kilometers_to_meters(value)
elif unit_1 == LENGTH_CENTIMETERS:
meters = __centimeters_to_meters(value)
elif unit_1 == LENGTH_MILLIMETERS:
meters = __millimeters_to_meters(value)

result = meters

if unit_2 == LENGTH_MILES:
result = __meters_to_miles(meters)
elif unit_2 == LENGTH_YARD:
result = __meters_to_yards(meters)
elif unit_2 == LENGTH_FEET:
result = __meters_to_feet(meters)
elif unit_2 == LENGTH_INCHES:
result = __meters_to_inches(meters)
elif unit_2 == LENGTH_KILOMETERS:
result = __meters_to_kilometers(meters)
elif unit_2 == LENGTH_CENTIMETERS:
result = __meters_to_centimeters(meters)
elif unit_2 == LENGTH_MILLIMETERS:
result = __meters_to_millimeters(meters)

return result

Expand All @@ -52,26 +81,66 @@ def __miles_to_meters(miles: float) -> float:
return miles * 1609.344


def __yards_to_meters(yards: float) -> float:
"""Convert yards to meters."""
return yards * 0.9144


def __feet_to_meters(feet: float) -> float:
"""Convert feet to meters."""
return feet * 0.3048


def __inches_to_meters(inches: float) -> float:
"""Convert inches to meters."""
return inches * 0.0254


def __kilometers_to_meters(kilometers: float) -> float:
"""Convert kilometers to meters."""
return kilometers * 1000


def __centimeters_to_meters(centimeters: float) -> float:
"""Convert centimeters to meters."""
return centimeters * 0.01


def __millimeters_to_meters(millimeters: float) -> float:
"""Convert millimeters to meters."""
return millimeters * 0.001


def __meters_to_miles(meters: float) -> float:
"""Convert meters to miles."""
return meters * 0.000621371


def __meters_to_yards(meters: float) -> float:
"""Convert meters to yards."""
return meters * 1.09361


def __meters_to_feet(meters: float) -> float:
"""Convert meters to feet."""
return meters * 3.28084


def __meters_to_inches(meters: float) -> float:
"""Convert meters to inches."""
return meters * 39.3701


def __meters_to_kilometers(meters: float) -> float:
"""Convert meters to kilometers."""
return meters * 0.001


def __meters_to_centimeters(meters: float) -> float:
"""Convert meters to centimeters."""
return meters * 100


def __meters_to_millimeters(meters: float) -> float:
"""Convert meters to millimeters."""
return meters * 1000
Comment thread
springstan marked this conversation as resolved.
83 changes: 80 additions & 3 deletions tests/util/test_distance.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,14 @@
import pytest

from homeassistant.const import (
LENGTH_CENTIMETERS,
LENGTH_FEET,
LENGTH_INCHES,
LENGTH_KILOMETERS,
LENGTH_METERS,
LENGTH_MILES,
LENGTH_MILLIMETERS,
LENGTH_YARD,
)
import homeassistant.util.distance as distance_util

Expand All @@ -18,8 +22,12 @@ def test_convert_same_unit():
"""Test conversion from any unit to same unit."""
assert distance_util.convert(5, LENGTH_KILOMETERS, LENGTH_KILOMETERS) == 5
assert distance_util.convert(2, LENGTH_METERS, LENGTH_METERS) == 2
assert distance_util.convert(6, LENGTH_CENTIMETERS, LENGTH_CENTIMETERS) == 6
assert distance_util.convert(3, LENGTH_MILLIMETERS, LENGTH_MILLIMETERS) == 3
assert distance_util.convert(10, LENGTH_MILES, LENGTH_MILES) == 10
assert distance_util.convert(9, LENGTH_FEET, LENGTH_FEET) == 9
assert distance_util.convert(9, LENGTH_YARD, LENGTH_YARD) == 9
assert distance_util.convert(8, LENGTH_FEET, LENGTH_FEET) == 8
assert distance_util.convert(7, LENGTH_INCHES, LENGTH_INCHES) == 7


def test_convert_invalid_unit():
Expand All @@ -42,28 +50,97 @@ def test_convert_from_miles():
miles = 5
assert distance_util.convert(miles, LENGTH_MILES, LENGTH_KILOMETERS) == 8.04672
assert distance_util.convert(miles, LENGTH_MILES, LENGTH_METERS) == 8046.72
assert distance_util.convert(miles, LENGTH_MILES, LENGTH_CENTIMETERS) == 804672.0
assert distance_util.convert(miles, LENGTH_MILES, LENGTH_MILLIMETERS) == 8046720.0
assert distance_util.convert(miles, LENGTH_MILES, LENGTH_YARD) == 8799.9734592
assert distance_util.convert(miles, LENGTH_MILES, LENGTH_FEET) == 26400.0008448
assert distance_util.convert(miles, LENGTH_MILES, LENGTH_INCHES) == 316800.171072


def test_convert_from_yards():
"""Test conversion from yards to other units."""
yards = 5
assert (
distance_util.convert(yards, LENGTH_YARD, LENGTH_KILOMETERS)
== 0.0045720000000000005
)
assert distance_util.convert(yards, LENGTH_YARD, LENGTH_METERS) == 4.572
assert distance_util.convert(yards, LENGTH_YARD, LENGTH_CENTIMETERS) == 457.2
assert distance_util.convert(yards, LENGTH_YARD, LENGTH_MILLIMETERS) == 4572.0
assert distance_util.convert(yards, LENGTH_YARD, LENGTH_MILES) == 0.002840908212
assert distance_util.convert(yards, LENGTH_YARD, LENGTH_FEET) == 15.00000048
assert distance_util.convert(yards, LENGTH_YARD, LENGTH_INCHES) == 180.0000972


def test_convert_from_feet():
"""Test conversion from feet to other units."""
feet = 5000
assert distance_util.convert(feet, LENGTH_FEET, LENGTH_KILOMETERS) == 1.524
assert distance_util.convert(feet, LENGTH_FEET, LENGTH_METERS) == 1524
assert distance_util.convert(feet, LENGTH_FEET, LENGTH_CENTIMETERS) == 152400.0
assert distance_util.convert(feet, LENGTH_FEET, LENGTH_MILLIMETERS) == 1524000.0
assert distance_util.convert(feet, LENGTH_FEET, LENGTH_MILES) == 0.9469694040000001
assert distance_util.convert(feet, LENGTH_FEET, LENGTH_YARD) == 1666.66164
assert distance_util.convert(feet, LENGTH_FEET, LENGTH_INCHES) == 60000.032400000004


def test_convert_from_inches():
"""Test conversion from inches to other units."""
inches = 5000
assert distance_util.convert(inches, LENGTH_INCHES, LENGTH_KILOMETERS) == 0.127
assert distance_util.convert(inches, LENGTH_INCHES, LENGTH_METERS) == 127.0
assert distance_util.convert(inches, LENGTH_INCHES, LENGTH_CENTIMETERS) == 12700.0
assert distance_util.convert(inches, LENGTH_INCHES, LENGTH_MILLIMETERS) == 127000.0
assert distance_util.convert(inches, LENGTH_INCHES, LENGTH_MILES) == 0.078914117
assert (
distance_util.convert(inches, LENGTH_INCHES, LENGTH_YARD) == 138.88846999999998
)
assert distance_util.convert(inches, LENGTH_INCHES, LENGTH_FEET) == 416.66668


def test_convert_from_kilometers():
"""Test conversion from kilometers to other units."""
km = 5
assert distance_util.convert(km, LENGTH_KILOMETERS, LENGTH_FEET) == 16404.2
assert distance_util.convert(km, LENGTH_KILOMETERS, LENGTH_METERS) == 5000
assert distance_util.convert(km, LENGTH_KILOMETERS, LENGTH_CENTIMETERS) == 500000
assert distance_util.convert(km, LENGTH_KILOMETERS, LENGTH_MILLIMETERS) == 5000000
assert distance_util.convert(km, LENGTH_KILOMETERS, LENGTH_MILES) == 3.106855
assert distance_util.convert(km, LENGTH_KILOMETERS, LENGTH_YARD) == 5468.05
assert distance_util.convert(km, LENGTH_KILOMETERS, LENGTH_FEET) == 16404.2
assert distance_util.convert(km, LENGTH_KILOMETERS, LENGTH_INCHES) == 196850.5


def test_convert_from_meters():
"""Test conversion from meters to other units."""
m = 5000
assert distance_util.convert(m, LENGTH_METERS, LENGTH_FEET) == 16404.2
assert distance_util.convert(m, LENGTH_METERS, LENGTH_KILOMETERS) == 5
assert distance_util.convert(m, LENGTH_METERS, LENGTH_CENTIMETERS) == 500000
assert distance_util.convert(m, LENGTH_METERS, LENGTH_MILLIMETERS) == 5000000
assert distance_util.convert(m, LENGTH_METERS, LENGTH_MILES) == 3.106855
assert distance_util.convert(m, LENGTH_METERS, LENGTH_YARD) == 5468.05
assert distance_util.convert(m, LENGTH_METERS, LENGTH_FEET) == 16404.2
assert distance_util.convert(m, LENGTH_METERS, LENGTH_INCHES) == 196850.5


def test_convert_from_centimeters():
"""Test conversion from centimeters to other units."""
cm = 500000
assert distance_util.convert(cm, LENGTH_CENTIMETERS, LENGTH_KILOMETERS) == 5
assert distance_util.convert(cm, LENGTH_CENTIMETERS, LENGTH_METERS) == 5000
assert distance_util.convert(cm, LENGTH_CENTIMETERS, LENGTH_MILLIMETERS) == 5000000
assert distance_util.convert(cm, LENGTH_CENTIMETERS, LENGTH_MILES) == 3.106855
assert distance_util.convert(cm, LENGTH_CENTIMETERS, LENGTH_YARD) == 5468.05
assert distance_util.convert(cm, LENGTH_CENTIMETERS, LENGTH_FEET) == 16404.2
assert distance_util.convert(cm, LENGTH_CENTIMETERS, LENGTH_INCHES) == 196850.5


def test_convert_from_millimeters():
"""Test conversion from millimeters to other units."""
mm = 5000000
assert distance_util.convert(mm, LENGTH_MILLIMETERS, LENGTH_KILOMETERS) == 5
assert distance_util.convert(mm, LENGTH_MILLIMETERS, LENGTH_METERS) == 5000
assert distance_util.convert(mm, LENGTH_MILLIMETERS, LENGTH_CENTIMETERS) == 500000
assert distance_util.convert(mm, LENGTH_MILLIMETERS, LENGTH_MILES) == 3.106855
assert distance_util.convert(mm, LENGTH_MILLIMETERS, LENGTH_YARD) == 5468.05
assert distance_util.convert(mm, LENGTH_MILLIMETERS, LENGTH_FEET) == 16404.2
assert distance_util.convert(mm, LENGTH_MILLIMETERS, LENGTH_INCHES) == 196850.5