From 45026437da636fc7079d3035e43c6cf0f2d2dd4e Mon Sep 17 00:00:00 2001 From: Graham McIntire Date: Thu, 2 Apr 2026 16:42:20 -0500 Subject: [PATCH] Add Weather.sync_stations! to import ASOS/RAOB stations from IEM --- lib/microwaveprop/weather.ex | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/lib/microwaveprop/weather.ex b/lib/microwaveprop/weather.ex index d9a032b6..5ab7d804 100644 --- a/lib/microwaveprop/weather.ex +++ b/lib/microwaveprop/weather.ex @@ -3,7 +3,10 @@ defmodule Microwaveprop.Weather do import Ecto.Query + require Logger + alias Microwaveprop.Repo + alias Microwaveprop.Weather.IemClient alias Microwaveprop.Weather.HrrrProfile alias Microwaveprop.Weather.IemreObservation alias Microwaveprop.Weather.SolarIndex @@ -93,6 +96,34 @@ defmodule Microwaveprop.Weather do |> MapSet.new() end + def sync_stations! do + asos = for s <- ~w(AK AL AR AZ CA CO CT DE FL GA HI IA ID IL IN KS KY LA MA MD ME MI MN MO MS MT NC ND NE NH NJ NM NV NY OH OK OR PA RI SC SD TN TX UT VA VT WA WI WV WY), do: "#{s}_ASOS" + + for network <- asos ++ ["RAOB"] do + type = if String.contains?(network, "ASOS"), do: "asos", else: "sounding" + + case IemClient.fetch_network(network) do + {:ok, stations} -> + for s <- stations do + %Station{} + |> Station.changeset(Map.put(s, :station_type, type)) + |> Repo.insert(on_conflict: :nothing, conflict_target: [:station_code, :station_type]) + end + + Logger.info("Synced #{length(stations)} stations from #{network}") + + {:error, e} -> + Logger.warning("Failed to sync #{network}: #{inspect(e)}") + end + + Process.sleep(200) + end + + count = Repo.aggregate(Station, :count) + Logger.info("Weather stations sync complete: #{count} total") + :ok + end + def nearby_stations(lat, lon, station_type, radius_km) do dlat = radius_km / @km_per_deg_lat dlon = radius_km / (@km_per_deg_lat * :math.cos(lat * :math.pi() / 180))