From 88413efc94974606e32cb9ebe4ada92d1e41f380 Mon Sep 17 00:00:00 2001 From: ChrisMuir Date: Sun, 27 Sep 2020 22:23:04 -0400 Subject: [PATCH 1/2] add compatibility for api version 3 --- DESCRIPTION | 2 +- R/get_coords.R | 18 ++++--- R/get_location.R | 14 ++++- R/utils.R | 98 +++++++++++++++++++++++++++++----- R/zzz.R | 1 + man/bmap_get_coords.Rd | 9 +++- man/bmap_get_location.Rd | 9 +++- tests/testthat/test-baidugeo.R | 8 +++ 8 files changed, 133 insertions(+), 26 deletions(-) diff --git a/DESCRIPTION b/DESCRIPTION index 08ea5ce..23ccad9 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -14,7 +14,7 @@ Imports: Rcpp License: GPL-3 LazyData: true -RoxygenNote: 6.1.0 +RoxygenNote: 7.1.1 LinkingTo: Rcpp, rapidjsonr Suggests: knitr, testthat diff --git a/R/get_coords.R b/R/get_coords.R index 68c0d9f..f20c0f2 100644 --- a/R/get_coords.R +++ b/R/get_coords.R @@ -120,18 +120,24 @@ bmap_get_coords <- function(location, type = c("data.frame", "json"), envir = bmap_env) # If API key is invalid, throw error. - if (grepl("message", res) && !grepl('\"lng\"', res)) { + if (invalid_key(res)) { stop(invalid_key_msg(res), call. = FALSE) } + # If API response contains "APP 服务被禁用", try flipping the API version + # and making the call again. If that returns "APP 服务被禁用", throw + # error. + if (key_api_version_incompatible(res)) { + flip_api_version() + res <- baidu_coord_query(location[x]) + if (key_api_version_incompatible(res)) { + stop(key_api_version_incompatible_msg(), call. = FALSE) + } + } + # Assign res to output vector. out[x] <- res - # If API key is invalid, throw error. - if (grepl("message", res) && !grepl('\"lng\"', res)) { - stop(invalid_key_msg(res), call. = FALSE) - } - # If there was a connection error or http status code 302, do not cache # the result to addr_hash_map. if (grepl('con error:|"status\\":302', res)) { diff --git a/R/get_location.R b/R/get_location.R index 35bc5a1..46fac6c 100644 --- a/R/get_location.R +++ b/R/get_location.R @@ -116,10 +116,22 @@ bmap_get_location <- function(lat, lon, type = c("data.frame", "json"), envir = bmap_env) # If API key is invalid, throw error. - if (grepl("message", res) && !grepl('\"lng\"', res)) { + if (invalid_key(res)) { stop(invalid_key_msg(res), call. = FALSE) } + # If API response contains "APP 服务被禁用", try flipping the API version + # and making the call again. If that returns "APP 服务被禁用", throw + # error. + if (key_api_version_incompatible(res)) { + flip_api_version() + uri <- get_addr_query_uri(lon[x], lat[x]) + res <- baidu_location_query(uri) + if (key_api_version_incompatible(res)) { + stop(key_api_version_incompatible_msg(), call. = FALSE) + } + } + # Assign res to output vector. out[x] <- res diff --git a/R/utils.R b/R/utils.R index 3a9c4f7..bf92e39 100644 --- a/R/utils.R +++ b/R/utils.R @@ -3,12 +3,23 @@ #' #' @noRd get_coords_query_uri <- function(location) { - paste0( - "http://api.map.baidu.com/geocoder/v2/?address=", - location, - "&output=json&ak=", - "%s" - ) + api_version <- get_api_version() + if (api_version == "v2") { + uri <- paste0( + "http://api.map.baidu.com/geocoder/v2/?address=", + location, + "&output=json&ak=", + "%s" + ) + } else { + uri <- paste0( + "http://api.map.baidu.com/geocoding/v3/?address=", + location, + "&output=json&ak=", + "%s" + ) + } + uri } @@ -16,13 +27,72 @@ get_coords_query_uri <- function(location) { #' #' @noRd get_addr_query_uri <- function(lon, lat) { + api_version <- get_api_version() + if (api_version == "v2") { + uri <- paste0( + "http://api.map.baidu.com/geocoder/v2/?ak=", + "%s", + "&location=", + lat, + ",", + lon, + "&output=json&pois=0" + ) + } else { + uri <- paste0( + "http://api.map.baidu.com/geocoding/v3/?ak=", + "%s", + "&location=", + lat, + ",", + lon, + "&output=json&coordtype=wgs84ll" + ) + } + uri +} + +#' Get API version, either v2 or v3 +#' +#' @noRd +get_api_version <- function() { + get("api_key_version", envir = bmap_env) +} + +#' Flip API version, between v2 and v3 +#' +#' @noRd +flip_api_version <- function() { + curr <- get_api_version() + if (curr == "v2") { + assign("api_key_version", "v3", envir = bmap_env) + } else { + assign("api_key_version", "v2", envir = bmap_env) + } +} + +#' Check to see if a json string response indicates the API key is not valid +#' +#' @noRd +invalid_key <- function(res) { + grepl('\"message\":\"APP不存在,AK有误请检查再重试\"', res) +} + +#' Check to see if a json string response indicates that an API key is not +#' compatible with the current API version, as indicated by get_api_version() +#' +#' @noRd +key_api_version_incompatible <- function(res) { + grepl("APP 服务被禁用", res) && grepl('\"status\":240', res) +} + +#' Error message indiating an API key is incompatible with both v2 and v3 +#' of the Baidu API +#' +#' @noRd +key_api_version_incompatible_msg <- function() { paste0( - "http://api.map.baidu.com/geocoder/v2/?ak=", - "%s", - "&location=", - lat, - ",", - lon, - "&output=json&pois=0" - ) + "Current API key is incompatible with both v2 and v3 of the Baidu API.\n", + missing_key_msg() + ) } diff --git a/R/zzz.R b/R/zzz.R index 9609e51..40594b0 100644 --- a/R/zzz.R +++ b/R/zzz.R @@ -6,6 +6,7 @@ assign("bmap_daily_rate_limit", 5950L, envir = bmap_env) assign("queries_left_today", 5950L, envir = bmap_env) assign("next_limit_reset", NULL, envir = bmap_env) assign("time_of_last_query", Sys.time(), envir = bmap_env) +assign("api_key_version", "v2", envir = bmap_env) # Initialize placeholders for package data within bmap_env. assign("coord_hash_map", NULL, envir = bmap_env) diff --git a/man/bmap_get_coords.Rd b/man/bmap_get_coords.Rd index 7141c45..0e1c617 100644 --- a/man/bmap_get_coords.Rd +++ b/man/bmap_get_coords.Rd @@ -4,8 +4,13 @@ \alias{bmap_get_coords} \title{Get Coordinates for a Vector of Locations.} \usage{ -bmap_get_coords(location, type = c("data.frame", "json"), - force = FALSE, skip_short_str = FALSE, cache_chunk_size = NULL) +bmap_get_coords( + location, + type = c("data.frame", "json"), + force = FALSE, + skip_short_str = FALSE, + cache_chunk_size = NULL +) } \arguments{ \item{location}{char vector, vector of locations.} diff --git a/man/bmap_get_location.Rd b/man/bmap_get_location.Rd index 2827256..6fbbf76 100644 --- a/man/bmap_get_location.Rd +++ b/man/bmap_get_location.Rd @@ -4,8 +4,13 @@ \alias{bmap_get_location} \title{Get Location for a Vector of lat/lon coordinates.} \usage{ -bmap_get_location(lat, lon, type = c("data.frame", "json"), - force = FALSE, cache_chunk_size = NULL) +bmap_get_location( + lat, + lon, + type = c("data.frame", "json"), + force = FALSE, + cache_chunk_size = NULL +) } \arguments{ \item{lat}{numeric vector, vector of latitude values.} diff --git a/tests/testthat/test-baidugeo.R b/tests/testthat/test-baidugeo.R index 66869f5..d046042 100644 --- a/tests/testthat/test-baidugeo.R +++ b/tests/testthat/test-baidugeo.R @@ -33,3 +33,11 @@ test_that("invalid key msg is correct", { "len of str is 3 or fewer chars") ) }) + +context("flip_api_versoin") + +test_that("flip_api_version correctly flips the api version env var", { + assign("api_key_version", "v3", envir = bmap_env) + flip_api_version() + expect_equal(get_api_version(), "v2") +}) From 44f21092564a9c8a8a929a6838eab4106136356d Mon Sep 17 00:00:00 2001 From: ChrisMuir Date: Mon, 28 Sep 2020 18:29:05 -0400 Subject: [PATCH 2/2] update reverse base url --- R/utils.R | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/R/utils.R b/R/utils.R index bf92e39..400d84a 100644 --- a/R/utils.R +++ b/R/utils.R @@ -40,7 +40,7 @@ get_addr_query_uri <- function(lon, lat) { ) } else { uri <- paste0( - "http://api.map.baidu.com/geocoding/v3/?ak=", + "http://api.map.baidu.com/reverse_geocoding/v3/?ak=", "%s", "&location=", lat,