Lab 7

APIs & Space!
Author

Matt and Visruth

Published

May 19, 2025

Modified

June 6, 2025

Pass Times for U.S. State Captials

library(tidyverse)
library(tidyjson)
library(lubridate)
library(lutz)

states <- read_table(
  "https://people.sc.fsu.edu/~jburkardt/datasets/states/state_capitals_ll.txt",
  col_names = c("state", "lat", "long")
) |>
  filter(state != "US") |>
  mutate(tz = tz_lookup_coords(lat, long, method = "accurate"))

get_datetimes <- function(state, lat, long, tz, wait = 0.1) {
  Sys.sleep(wait)

  tryCatch(
    {
      start_times <- httr::GET(
        glue::glue(
          "https://api.g7vrd.co.uk/v1/satellite-passes/25544/{lat}/{long}.json"
        ),
        httr::timeout(10)
      )$content |>
        rawToChar() |>
        as.tbl_json() |>
        enter_object("passes") |>
        gather_array() |>
        spread_all() |>
        mutate(start_dt = as_datetime(start, tz = tz)) |>
        filter(!is.na(start_dt)) |>
        arrange(start_dt) |>
        pull(start_dt)

      valid_pass <- \(n)
        if (length(start_times) >= n) start_times[n] else NA_POSIXct_

      tibble(
        pass1 = valid_pass(1),
        pass2 = valid_pass(2),
        pass3 = valid_pass(3),
      )
    },
    error = function(e) {
      warning(glue::glue(
        "Error processing API for {state} ({lat},{long}): {e$message}"
      ))
      tibble(
        pass1 = NA_POSIXct_,
        pass2 = NA_POSIXct_,
        pass3 = NA_POSIXct_
      )
    }
  )
}

result <- bind_cols(
  states,
  pmap_df(states, get_datetimes)
)

International Space Station Pass Times (Local Time Zones)

library(leaflet)

rocket_icon <- makeIcon(
  iconUrl = "rocket.svg",
  iconWidth = 30,
  iconHeight = 30
)
custom_format_date <- \(date) format(date, "%Y-%m-%d %H:%M:%S")

m <- leaflet(result) |>
  addTiles() |>
  addMarkers(
    lng = ~long,
    lat = ~lat,
    icon = rocket_icon,
    label = ~ glue::glue("Next pass: {custom_format_date(pass1)}"),
    popup = ~ glue::glue(
      "<b>{state}</b><br/>",
      "Pass 1: {custom_format_date(pass1)}<br/>",
      "Pass 2: {custom_format_date(pass2)}<br/>",
      "Pass 3: {custom_format_date(pass3)}"
    )
  )

m

Drawing the Route of the ISS

library(leaflet.extras2)

m |>
  addArrowhead(
    data = result |>
      filter(!is.na(pass1)) |>
      arrange(pass1),
    lat = ~lat,
    lng = ~long,
    color = "red",
    options = arrowheadOptions(
      frequency = "200px",
      size = "10px",
      color = "purple",
      opacity = 1,
      fill = TRUE
    )
  )