core/homeassistant/util/location.py

78 lines
2.4 KiB
Python
Raw Normal View History

2016-01-26 23:08:06 +00:00
"""
Module with location helpers.
2016-02-05 06:26:02 +00:00
detect_location_info and elevation are mocked by default during tests.
2016-01-26 23:08:06 +00:00
"""
2015-07-07 07:01:17 +00:00
import collections
import requests
2016-02-19 05:27:50 +00:00
2015-09-29 07:18:52 +00:00
from vincenty import vincenty
2015-07-07 07:01:17 +00:00
2015-12-27 19:07:25 +00:00
ELEVATION_URL = 'http://maps.googleapis.com/maps/api/elevation/json'
2015-07-07 07:01:17 +00:00
LocationInfo = collections.namedtuple(
"LocationInfo",
['ip', 'country_code', 'country_name', 'region_code', 'region_name',
'city', 'zip_code', 'time_zone', 'latitude', 'longitude',
'use_fahrenheit'])
DATA_SOURCE = ['https://freegeoip.io/json/', 'http://ip-api.com/json']
2015-07-07 07:01:17 +00:00
def detect_location_info():
"""Detect location information."""
success = None
2015-07-07 07:01:17 +00:00
for source in DATA_SOURCE:
try:
raw_info = requests.get(source, timeout=5).json()
success = source
break
except (requests.RequestException, ValueError):
success = False
if success is False:
return None
else:
data = {key: raw_info.get(key) for key in LocationInfo._fields}
if success is DATA_SOURCE[1]:
data['ip'] = raw_info.get('query')
data['country_code'] = raw_info.get('countryCode')
data['country_name'] = raw_info.get('country')
data['region_code'] = raw_info.get('region')
data['region_name'] = raw_info.get('regionName')
data['zip_code'] = raw_info.get('zip')
data['time_zone'] = raw_info.get('timezone')
data['latitude'] = raw_info.get('lat')
data['longitude'] = raw_info.get('lon')
2015-07-07 07:01:17 +00:00
# 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')
return LocationInfo(**data)
2015-09-20 16:35:03 +00:00
2015-10-02 15:16:53 +00:00
def distance(lat1, lon1, lat2, lon2):
"""Calculate the distance in meters between two points."""
2015-10-02 15:16:53 +00:00
return vincenty((lat1, lon1), (lat2, lon2)) * 1000
2015-12-27 19:07:25 +00:00
def elevation(latitude, longitude):
"""Return elevation for given latitude and longitude."""
2015-12-27 19:07:25 +00:00
req = requests.get(ELEVATION_URL, params={
'locations': '{},{}'.format(latitude, longitude),
'sensor': 'false',
})
if req.status_code != 200:
return 0
try:
return int(float(req.json()['results'][0]['elevation']))
except (ValueError, KeyError):
return 0