Current section
Files
Jump to
Current section
Files
lib/geolocation_client.ex
defmodule GeolocationClient do
@moduledoc """
Client for Google Geolocation API
"""
@base_url "https://www.googleapis.com/"
@doc """
Set API key
"""
@spec set_api_key(String.t()) :: :ok
def set_api_key(key) do
Application.put_env(:geolocation_client, :api_key, key)
end
@doc """
Geolocate from a list of MAC addresses
"""
@spec geolocate_from_mac_addresses([GeolocationClient.Entities.MacAddress.t()], boolean()) :: GeolocationClient.Entities.LatLon.t() | {:error, any()}
def geolocate_from_mac_addresses(mac_addresses, consider_ip \\ false) when is_list(mac_addresses) do
# Implementation would go here
url = "#{@base_url}geolocation/v1/geolocate?key=#{Application.get_env(:geolocation_client, :api_key)}"
body = %{
"considerIp" => consider_ip,
"wifiAccessPoints" => Enum.map(mac_addresses, fn mac ->
%{
"macAddress" => mac.mac_address,
"signalStrength" => mac.signal_strength
}
end)
}
case Req.post(url, json: body) do
{:ok, %Req.Response{status: 200, body: %{"location" => location, "accuracy" => accuracy}}} ->
%GeolocationClient.Entities.LatLon{
latitude: location["lat"],
longitude: location["lng"],
accuracy: accuracy
}
{:ok, %Req.Response{status: status, body: body}} ->
{:error, %{status: status, body: body}}
{:error, reason} ->
{:error, reason}
end
end
@doc """
Get altitude for given latitude and longitude
"""
@spec get_altitude(GeolocationClient.Entities.LatLon.t()) :: float() | {:error, any()}
def get_altitude(%GeolocationClient.Entities.LatLon{latitude: lat, longitude: lon}) do
# Implementation would go here
url = "https://maps.googleapis.com/maps/api/elevation/json?locations=#{lat}%2C#{lon}&key=#{Application.get_env(:geolocation_client, :api_key)}"
case Req.get(url) do
{:ok, %Req.Response{status: 200, body: %{"results" => [%{"elevation" => elevation} | _]}}} ->
elevation
{:ok, %Req.Response{status: status, body: body}} ->
{:error, %{status: status, body: body}}
{:error, reason} ->
{:error, reason}
end
end
@doc """
Geolocate from mac addresses and get full location (LLA)
"""
@spec geolocate_full_location([GeolocationClient.Entities.MacAddress.t()], boolean()) :: GeolocationClient.Entities.Location.t() | {:error, any()}
def geolocate_full_location(mac_addresses, consider_ip \\ false) when is_list(mac_addresses) do
case geolocate_from_mac_addresses(mac_addresses, consider_ip) do
%GeolocationClient.Entities.LatLon{latitude: lat, longitude: lon} = lat_lon ->
case get_altitude(lat_lon) do
elevation when is_float(elevation) ->
%GeolocationClient.Entities.Location{
latitude: lat,
longitude: lon,
altitude: elevation
}
{:error, _} = error ->
error
end
{:error, _} = error ->
error
end
end
end