diff --git a/DESCRIPTION b/DESCRIPTION index b053176..4b8379b 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,7 +1,7 @@ Package: tfnswapi Type: Package Title: Access TfNSW Open Data from R -Version: 0.2.0 +Version: 0.3.0 Author: Amarin Siripanich Maintainer: Amarin Siripanich Description: Access TfNSW Open Data from R. diff --git a/NEWS.md b/NEWS.md index 485cb26..c39ff84 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,3 +1,7 @@ +# tfnswapi 0.3.0 + +* Added the ability to specific which protobuf descriptor `tfnswapi_get()` will use to parse a 'application/x-google-protobuf' response. You can select one of `transit_realtime.*` variables, `transit_realtime.FeedMessage` is selected as default. + # tfnswapi 0.2.0 * You now can quickly browse TfNSW API with `tfnswapi_browse()`. diff --git a/R/get.R b/R/get.R index 4966d21..5a0bde0 100644 --- a/R/get.R +++ b/R/get.R @@ -9,6 +9,9 @@ tfnsw_base_api_url = "https://api.transport.nsw.gov.au/" #' here. #' @param key Character (optional). An API key can be provided, else if emptied #' it will look for any previously registered API key. +#' @param descriptor This field is only used if the response is of type +#' `application/x-google-protobuf`. You must select one of `transit_realtime` variables. +#' By default this is `transit_realtime.FeedMessage`. #' #' @return a response with parsed content. #' @export @@ -22,18 +25,21 @@ tfnsw_base_api_url = "https://api.transport.nsw.gov.au/" #' tfnswapi_get("carpark", params = list(facility = 2)) #' #' } -tfnswapi_get = function(api, params = NULL, key = tfnswapi_get_api_key()) { +tfnswapi_get = function(api, + params = NULL, + key = tfnswapi_get_api_key(), + descriptor = transit_realtime.FeedMessage) { - checkmate::assert_string(api) - - path = glue::glue("v1/{api}") + path = construct_path(api) response = tfnswapi_get_response(path, params, key) - response$content = switch(httr::http_type(response), - "application/json" = parse_json_response(response), - "application/x-google-protobuf" = parse_ggprotobuf_response(response), - stop("Don't know how to parse ", httr::http_type(response))) + response$content = switch( + httr::http_type(response), + "application/json" = parse_json_response(response), + "application/x-google-protobuf" = parse_ggprotobuf_response(response, descriptor), + stop("Don't know how to parse ", httr::http_type(response)) + ) if (httr::status_code(response) != 200) { stop( @@ -74,9 +80,13 @@ parse_json_response = function(response) { jsonlite::fromJSON(httr::content(response, "text"), simplifyVector = FALSE) } -parse_ggprotobuf_response = function(response) { - FeedMessage = RProtoBuf::read(descriptor = transit_realtime.FeedMessage, - input = response$content) +parse_ggprotobuf_response = function(response, descriptor = transit_realtime.FeedMessage) { + FeedMessage = RProtoBuf::read(descriptor = descriptor, input = response$content) json = RProtoBuf::toJSON(FeedMessage) lst = jsonlite::fromJSON(json) } + +construct_path = function(api) { + checkmate::assert_string(api) + glue::glue("v1/{api}") +} diff --git a/README.Rmd b/README.Rmd index b0ca018..55758e2 100644 --- a/README.Rmd +++ b/README.Rmd @@ -16,7 +16,6 @@ knitr::opts_chunk$set( # tfnswapi -[![Lifecycle: experimental](https://img.shields.io/badge/lifecycle-experimental-orange.svg)](https://www.tidyverse.org/lifecycle/#experimental) [![R build status](https://github.com/asiripanich/tfnswapi/workflows/R-CMD-check/badge.svg)](https://github.com/asiripanich/tfnswapi/actions) @@ -34,9 +33,11 @@ You can install the `tfnswapi` package from [GitHub](https://github.com/asiripan install.packages("tfnswapi") ``` -## Example +## Examples -```{r example} +### Carpark API + +```{r carpark-example, dpi=300} library(tfnswapi) # See what facilities are available @@ -68,3 +69,43 @@ ggplot(data = tidied_carpark, aes(x = zone_id)) + y = "# Spots" ) ``` +### GTFS Realtime API + +See TfNSW GTFS Realtime documentation [here](https://opendata.transport.nsw.gov.au/sites/default/files/TfNSW_GTFS_Realtime_Buses_Technical_Doc.pdf). + +```{r gtfsr-example, dpi=300, message=FALSE} +library(tfnswapi) +library(ggplot2) +library(ggmap) +library(sf) + +# remove `if (FALSE)` to register your own API key +if (FALSE) { + tfnswapi_register("") +} + +bus_response = tfnswapi_get("gtfs/vehiclepos/buses") +bus_position_table = bus_response$content$entity$vehicle$position + +bus_position_table = + bus_position_table %>% + sf::st_as_sf(coords = c("longitude", "latitude")) %>% + sf::st_set_crs(value = sf::st_crs("WGS84")) + +# Convert momentary speed measured by the vehicle in meters per second to +# kilometers per hour +bus_position_table$speed = 3.6 * bus_position_table$speed + +# get base map +sydney_bbox = sf::st_geometry(bus_position_table) %>% sf::st_bbox() +names(sydney_bbox) <- c("left", "bottom", "right", "top") +sydney_map = get_stamenmap(sydney_bbox, maptype = "toner-lite", messaging = FALSE) + +ggmap(sydney_map) + + coord_sf(crs = sf::st_crs("WGS84")) + + geom_sf(data = bus_position_table, aes(color = speed), inherit.aes = FALSE) + + labs(title = "Realtime positions of buses in Sydney, Australia", + color = "Speed (km/hr)", + subtitle = bus_response$date) +``` + diff --git a/README.md b/README.md index f437214..33e9998 100644 --- a/README.md +++ b/README.md @@ -5,8 +5,6 @@ -[![Lifecycle: -experimental](https://img.shields.io/badge/lifecycle-experimental-orange.svg)](https://www.tidyverse.org/lifecycle/#experimental) [![R build status](https://github.com/asiripanich/tfnswapi/workflows/R-CMD-check/badge.svg)](https://github.com/asiripanich/tfnswapi/actions) @@ -29,7 +27,9 @@ You can install the `tfnswapi` package from install.packages("tfnswapi") ``` -## Example +## Examples + +### Carpark API ``` r library(tfnswapi) @@ -76,4 +76,46 @@ ggplot(data = tidied_carpark, aes(x = zone_id)) + ) ``` - + +\#\#\# GTFS Realtime API + +See TfNSW GTFS Realtime documentation +[here](https://opendata.transport.nsw.gov.au/sites/default/files/TfNSW_GTFS_Realtime_Buses_Technical_Doc.pdf). + +``` r +library(tfnswapi) +library(ggplot2) +library(ggmap) +library(sf) + +# remove `if (FALSE)` to register your own API key +if (FALSE) { + tfnswapi_register("") +} + +bus_response = tfnswapi_get("gtfs/vehiclepos/buses") +bus_position_table = bus_response$content$entity$vehicle$position + +bus_position_table = + bus_position_table %>% + sf::st_as_sf(coords = c("longitude", "latitude")) %>% + sf::st_set_crs(value = sf::st_crs("WGS84")) + +# Convert momentary speed measured by the vehicle in meters per second to +# kilometers per hour +bus_position_table$speed = 3.6 * bus_position_table$speed + +# get base map +sydney_bbox = sf::st_geometry(bus_position_table) %>% sf::st_bbox() +names(sydney_bbox) <- c("left", "bottom", "right", "top") +sydney_map = get_stamenmap(sydney_bbox, maptype = "toner-lite", messaging = FALSE) + +ggmap(sydney_map) + + coord_sf(crs = sf::st_crs("WGS84")) + + geom_sf(data = bus_position_table, aes(color = speed), inherit.aes = FALSE) + + labs(title = "Realtime positions of buses in Sydney, Australia", + color = "Speed (km/hr)", + subtitle = bus_response$date) +``` + + diff --git a/man/tfnswapi_get.Rd b/man/tfnswapi_get.Rd index 73757fe..5235d40 100644 --- a/man/tfnswapi_get.Rd +++ b/man/tfnswapi_get.Rd @@ -5,7 +5,12 @@ \alias{tfnswapi_get_response} \title{Get data using GET API.} \usage{ -tfnswapi_get(api, params = NULL, key = tfnswapi_get_api_key()) +tfnswapi_get( + api, + params = NULL, + key = tfnswapi_get_api_key(), + descriptor = transit_realtime.FeedMessage +) tfnswapi_get_response(path, params = NULL, key = tfnswapi_get_api_key()) } @@ -19,6 +24,10 @@ here.} \item{key}{Character (optional). An API key can be provided, else if emptied it will look for any previously registered API key.} +\item{descriptor}{This field is only used if the response is of type +\code{application/x-google-protobuf}. You must select one of \code{transit_realtime} variables. +By default this is \code{transit_realtime.FeedMessage}.} + \item{path}{Character.} } \value{