Add WeatherJSON view module for API responses
- Implements nearby/1 function to format weather station data - Returns structured JSON with data and meta fields - Handles null weather fields gracefully - Includes distance, position, weather data, and symbols - Formats DateTime to ISO8601 strings - All tests passing (3/3)
This commit is contained in:
parent
47fc071263
commit
e539dc5a3e
2 changed files with 160 additions and 0 deletions
53
lib/aprsme_web/controllers/api/v1/weather_json.ex
Normal file
53
lib/aprsme_web/controllers/api/v1/weather_json.ex
Normal file
|
|
@ -0,0 +1,53 @@
|
||||||
|
defmodule AprsmeWeb.Api.V1.WeatherJSON do
|
||||||
|
@moduledoc """
|
||||||
|
JSON view for weather API responses.
|
||||||
|
"""
|
||||||
|
|
||||||
|
@doc """
|
||||||
|
Renders a list of nearby weather stations.
|
||||||
|
"""
|
||||||
|
def nearby(%{stations: stations, params: params}) do
|
||||||
|
%{
|
||||||
|
data: Enum.map(stations, &station_json/1),
|
||||||
|
meta: %{
|
||||||
|
count: length(stations),
|
||||||
|
params: params
|
||||||
|
}
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
defp station_json(station) do
|
||||||
|
%{
|
||||||
|
callsign: station.callsign,
|
||||||
|
base_callsign: station.base_callsign,
|
||||||
|
position: %{
|
||||||
|
lat: station.latitude,
|
||||||
|
lon: station.longitude
|
||||||
|
},
|
||||||
|
distance_miles: station.distance_miles,
|
||||||
|
weather: %{
|
||||||
|
temperature: station.temperature,
|
||||||
|
humidity: station.humidity,
|
||||||
|
pressure: station.pressure,
|
||||||
|
wind_speed: station.wind_speed,
|
||||||
|
wind_direction: station.wind_direction,
|
||||||
|
wind_gust: station.wind_gust,
|
||||||
|
rain_1h: station.rain_1h,
|
||||||
|
rain_24h: station.rain_24h,
|
||||||
|
rain_since_midnight: station.rain_since_midnight
|
||||||
|
},
|
||||||
|
symbol: %{
|
||||||
|
table_id: station.symbol_table_id,
|
||||||
|
code: station.symbol_code
|
||||||
|
},
|
||||||
|
comment: station.comment,
|
||||||
|
last_report: format_datetime(station.last_report)
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
defp format_datetime(%DateTime{} = dt) do
|
||||||
|
DateTime.to_iso8601(dt)
|
||||||
|
end
|
||||||
|
|
||||||
|
defp format_datetime(nil), do: nil
|
||||||
|
end
|
||||||
107
test/aprsme_web/controllers/api/v1/weather_json_test.exs
Normal file
107
test/aprsme_web/controllers/api/v1/weather_json_test.exs
Normal file
|
|
@ -0,0 +1,107 @@
|
||||||
|
defmodule AprsmeWeb.Api.V1.WeatherJSONTest do
|
||||||
|
use ExUnit.Case, async: true
|
||||||
|
|
||||||
|
alias AprsmeWeb.Api.V1.WeatherJSON
|
||||||
|
|
||||||
|
describe "nearby/1" do
|
||||||
|
test "renders list of weather stations with all fields" do
|
||||||
|
stations = [
|
||||||
|
%{
|
||||||
|
callsign: "W1XYZ-13",
|
||||||
|
base_callsign: "W1XYZ",
|
||||||
|
latitude: 42.3601,
|
||||||
|
longitude: -71.0589,
|
||||||
|
distance_miles: 1.23,
|
||||||
|
temperature: 72.5,
|
||||||
|
humidity: 65,
|
||||||
|
pressure: 1013.25,
|
||||||
|
wind_speed: 5.0,
|
||||||
|
wind_direction: 180,
|
||||||
|
wind_gust: 8.0,
|
||||||
|
rain_1h: 0.1,
|
||||||
|
rain_24h: 0.5,
|
||||||
|
rain_since_midnight: 0.3,
|
||||||
|
symbol_table_id: "/",
|
||||||
|
symbol_code: "_",
|
||||||
|
comment: "Test station",
|
||||||
|
last_report: ~U[2024-01-15 12:30:00Z]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
params = %{lat: 42.36, lon: -71.06, radius: 10}
|
||||||
|
|
||||||
|
result = WeatherJSON.nearby(%{stations: stations, params: params})
|
||||||
|
|
||||||
|
assert %{data: [station], meta: meta} = result
|
||||||
|
assert station.callsign == "W1XYZ-13"
|
||||||
|
assert station.base_callsign == "W1XYZ"
|
||||||
|
assert station.position == %{lat: 42.3601, lon: -71.0589}
|
||||||
|
assert station.distance_miles == 1.23
|
||||||
|
assert station.weather.temperature == 72.5
|
||||||
|
assert station.weather.humidity == 65
|
||||||
|
assert station.weather.pressure == 1013.25
|
||||||
|
assert station.weather.wind_speed == 5.0
|
||||||
|
assert station.weather.wind_direction == 180
|
||||||
|
assert station.weather.wind_gust == 8.0
|
||||||
|
assert station.weather.rain_1h == 0.1
|
||||||
|
assert station.weather.rain_24h == 0.5
|
||||||
|
assert station.weather.rain_since_midnight == 0.3
|
||||||
|
assert station.symbol == %{table_id: "/", code: "_"}
|
||||||
|
assert station.comment == "Test station"
|
||||||
|
assert station.last_report == "2024-01-15T12:30:00Z"
|
||||||
|
assert meta.count == 1
|
||||||
|
assert meta.params == params
|
||||||
|
end
|
||||||
|
|
||||||
|
test "handles null weather fields gracefully" do
|
||||||
|
stations = [
|
||||||
|
%{
|
||||||
|
callsign: "W2ABC",
|
||||||
|
base_callsign: "W2ABC",
|
||||||
|
latitude: 40.7128,
|
||||||
|
longitude: -74.006,
|
||||||
|
distance_miles: 5.0,
|
||||||
|
temperature: nil,
|
||||||
|
humidity: nil,
|
||||||
|
pressure: nil,
|
||||||
|
wind_speed: nil,
|
||||||
|
wind_direction: nil,
|
||||||
|
wind_gust: nil,
|
||||||
|
rain_1h: nil,
|
||||||
|
rain_24h: nil,
|
||||||
|
rain_since_midnight: nil,
|
||||||
|
symbol_table_id: "\\",
|
||||||
|
symbol_code: "n",
|
||||||
|
comment: nil,
|
||||||
|
last_report: ~U[2024-01-15 13:00:00Z]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
params = %{lat: 40.71, lon: -74.01, radius: 10}
|
||||||
|
|
||||||
|
result = WeatherJSON.nearby(%{stations: stations, params: params})
|
||||||
|
|
||||||
|
assert %{data: [station], meta: _meta} = result
|
||||||
|
assert station.weather.temperature == nil
|
||||||
|
assert station.weather.humidity == nil
|
||||||
|
assert station.weather.pressure == nil
|
||||||
|
assert station.weather.wind_speed == nil
|
||||||
|
assert station.weather.wind_direction == nil
|
||||||
|
assert station.weather.wind_gust == nil
|
||||||
|
assert station.weather.rain_1h == nil
|
||||||
|
assert station.weather.rain_24h == nil
|
||||||
|
assert station.weather.rain_since_midnight == nil
|
||||||
|
assert station.comment == nil
|
||||||
|
end
|
||||||
|
|
||||||
|
test "renders empty list when no stations found" do
|
||||||
|
params = %{lat: 42.36, lon: -71.06, radius: 10}
|
||||||
|
|
||||||
|
result = WeatherJSON.nearby(%{stations: [], params: params})
|
||||||
|
|
||||||
|
assert %{data: [], meta: meta} = result
|
||||||
|
assert meta.count == 0
|
||||||
|
assert meta.params == params
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
Loading…
Add table
Reference in a new issue