diff --git a/lib/microwaveprop/terrain/elevation_client.ex b/lib/microwaveprop/terrain/elevation_client.ex index ff610e42..2e6f1481 100644 --- a/lib/microwaveprop/terrain/elevation_client.ex +++ b/lib/microwaveprop/terrain/elevation_client.ex @@ -7,16 +7,16 @@ defmodule Microwaveprop.Terrain.ElevationClient do @batch_size 100 - @spec fetch_elevation_profile(float(), float(), float(), float(), pos_integer()) :: + @spec fetch_elevation_profile(float(), float(), float(), float(), pos_integer(), keyword()) :: {:ok, list(map())} | {:error, String.t()} - def fetch_elevation_profile(lat1, lon1, lat2, lon2, n \\ 64) do + def fetch_elevation_profile(lat1, lon1, lat2, lon2, n \\ 64, opts \\ []) do case srtm_tiles_dir() do nil -> Logger.debug("SRTM tiles_dir not configured, using API") fetch_elevation_profile_api(lat1, lon1, lat2, lon2, n) tiles_dir -> - case Srtm.fetch_elevation_profile(lat1, lon1, lat2, lon2, tiles_dir, n) do + case Srtm.fetch_elevation_profile(lat1, lon1, lat2, lon2, tiles_dir, n, opts) do {:ok, _profile} = ok -> Logger.info("Elevation profile served from SRTM tiles") ok diff --git a/lib/microwaveprop/terrain/srtm.ex b/lib/microwaveprop/terrain/srtm.ex index 730a8513..44b75a53 100644 --- a/lib/microwaveprop/terrain/srtm.ex +++ b/lib/microwaveprop/terrain/srtm.ex @@ -51,9 +51,9 @@ defmodule Microwaveprop.Terrain.Srtm do end end - @spec lookup(float(), float(), String.t()) :: + @spec lookup(float(), float(), String.t(), keyword()) :: {:ok, integer()} | {:error, :no_tile} | {:error, :void} - def lookup(lat, lon, tiles_dir) do + def lookup(lat, lon, tiles_dir, opts \\ []) do path = Path.join(tiles_dir, tile_filename(lat, lon)) case :file.open(path, [:read, :binary, :raw]) do @@ -61,9 +61,9 @@ defmodule Microwaveprop.Terrain.Srtm do read_elevation(fd, lat, lon) {:error, :enoent} -> - if File.dir?(tiles_dir) do + if opts[:download] && File.dir?(tiles_dir) do case download_tile(lat, lon, tiles_dir) do - {:ok, _path} -> + {:ok, _} -> case :file.open(path, [:read, :binary, :raw]) do {:ok, fd} -> read_elevation(fd, lat, lon) {:error, _} -> {:error, :no_tile} @@ -78,15 +78,15 @@ defmodule Microwaveprop.Terrain.Srtm do end end - @spec fetch_elevation_profile(float(), float(), float(), float(), String.t(), pos_integer()) :: + @spec fetch_elevation_profile(float(), float(), float(), float(), String.t(), pos_integer(), keyword()) :: {:ok, list(map())} | {:error, term()} - def fetch_elevation_profile(lat1, lon1, lat2, lon2, tiles_dir, n \\ 64) do + def fetch_elevation_profile(lat1, lon1, lat2, lon2, tiles_dir, n \\ 64, opts \\ []) do pts = sample_path(lat1, lon1, lat2, lon2, n) dist_km = haversine_km(lat1, lon1, lat2, lon2) results = Enum.reduce_while(pts, {:ok, []}, fn pt, {:ok, acc} -> - case lookup(pt.lat, pt.lon, tiles_dir) do + case lookup(pt.lat, pt.lon, tiles_dir, opts) do {:ok, elev} -> entry = %{ lat: pt.lat, diff --git a/lib/microwaveprop/workers/terrain_profile_worker.ex b/lib/microwaveprop/workers/terrain_profile_worker.ex index 11ed3c87..fc87ca1c 100644 --- a/lib/microwaveprop/workers/terrain_profile_worker.ex +++ b/lib/microwaveprop/workers/terrain_profile_worker.ex @@ -29,7 +29,7 @@ defmodule Microwaveprop.Workers.TerrainProfileWorker do # Look up HRRR refractivity gradient for dynamic k-factor k = lookup_k_factor(contact) - case ElevationClient.fetch_elevation_profile(lat1, lon1, lat2, lon2) do + case ElevationClient.fetch_elevation_profile(lat1, lon1, lat2, lon2, 64, download: true) do {:ok, profile} -> analysis = TerrainAnalysis.analyse(profile, dist_km, freq_ghz, k_factor: k) diff --git a/lib/microwaveprop_web/live/contact_live/show.ex b/lib/microwaveprop_web/live/contact_live/show.ex index 53a17ae4..0296ebbe 100644 --- a/lib/microwaveprop_web/live/contact_live/show.ex +++ b/lib/microwaveprop_web/live/contact_live/show.ex @@ -13,6 +13,7 @@ defmodule MicrowavepropWeb.ContactLive.Show do alias Microwaveprop.Weather # alias Microwaveprop.Weather.HrrrClient # alias Microwaveprop.Workers.HrrrFetchWorker + alias Microwaveprop.Workers.TerrainProfileWorker @earth_radius_m 6_371_000.0 @@ -26,6 +27,7 @@ defmodule MicrowavepropWeb.ContactLive.Show do hrrr = List.first(hrrr_path) {hrrr, hrrr_status} = maybe_enqueue_hrrr(hrrr, contact) terrain = Terrain.get_terrain_profile(contact.id) + maybe_enqueue_terrain(terrain, contact) elevation_profile = compute_elevation_profile(contact, hrrr_path, weather.soundings) propagation_analysis = build_propagation_analysis(contact, hrrr, terrain, elevation_profile, weather.soundings) @@ -175,6 +177,16 @@ defmodule MicrowavepropWeb.ContactLive.Show do end end + defp maybe_enqueue_terrain(terrain, _contact) when not is_nil(terrain), do: :ok + + defp maybe_enqueue_terrain(nil, contact) do + if contact.pos1 && contact.pos2 do + Oban.insert(TerrainProfileWorker.new(%{"qso_id" => contact.id})) + end + + :ok + end + defp maybe_enqueue_hrrr(hrrr, _contact) when not is_nil(hrrr), do: {hrrr, :loaded} # TODO: Re-enable auto HRRR backfill on page view when appropriate diff --git a/test/microwaveprop/terrain/srtm_test.exs b/test/microwaveprop/terrain/srtm_test.exs index a564fd01..7fea0be5 100644 --- a/test/microwaveprop/terrain/srtm_test.exs +++ b/test/microwaveprop/terrain/srtm_test.exs @@ -98,7 +98,15 @@ defmodule Microwaveprop.Terrain.SrtmTest do Plug.Conn.send_resp(conn, 200, gzipped) end) - assert {:ok, @test_elevation} = Srtm.lookup(32.0, -97.0, tmp_dir) + assert {:ok, @test_elevation} = Srtm.lookup(32.0, -97.0, tmp_dir, download: true) + end + + test "returns {:error, :no_tile} without download opt" do + tmp_dir = Path.join(System.tmp_dir!(), "srtm_test_#{System.unique_integer([:positive])}") + File.mkdir_p!(tmp_dir) + on_exit(fn -> File.rm_rf!(tmp_dir) end) + + assert {:error, :no_tile} = Srtm.lookup(32.0, -97.0, tmp_dir) end test "returns {:error, :no_tile} when download fails" do @@ -112,7 +120,7 @@ defmodule Microwaveprop.Terrain.SrtmTest do end) capture_log(fn -> - assert {:error, :no_tile} = Srtm.lookup(80.0, 0.0, tmp_dir) + assert {:error, :no_tile} = Srtm.lookup(80.0, 0.0, tmp_dir, download: true) end) end end