From 02bb6702773f1a39b7f38e3c6d3ab9a20737ce89 Mon Sep 17 00:00:00 2001 From: ericnewkirk <55846615+ericnewkirk@users.noreply.github.com> Date: Sat, 23 Jul 2022 11:19:08 -0600 Subject: [PATCH 01/10] Specify User Agent * add user-agent to ats_post and ats_get * use ats_post in ats_login * bump version * update ats_conifg for new columns --- DESCRIPTION | 2 +- R/ats_auth.R | 10 +++------- R/fetch_ats.R | 21 +++++++++++++++------ 3 files changed, 19 insertions(+), 14 deletions(-) diff --git a/DESCRIPTION b/DESCRIPTION index 7b3a3cb..7dc180c 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,6 +1,6 @@ Package: collar Title: Utilities for Accessing and Manipulating GPS Data -Version: 0.0.4002 +Version: 0.0.4003 Authors@R: c( person("Josh", "Nowak", email = "josh.nowak@speedgoat.io", role = c("aut", "cre")), person("Forest", "Hayes", email = "forest.hayes@umontana.edu", role = "aut"), diff --git a/R/ats_auth.R b/R/ats_auth.R index 9426b7a..0d56815 100644 --- a/R/ats_auth.R +++ b/R/ats_auth.R @@ -73,19 +73,15 @@ ats_login <- function(usr, pwd) { } # log in to ATS website - httr::RETRY( - "POST", - url = ats_base_url, + ats_post( path = list("Servidor.ashx"), body = list( consulta = "login", user = usr, pass = pwd ), - encode = "form", - quiet = TRUE - ) %>% - httr::stop_for_status("log in") + task = "log in" + ) # check that user cookie exists assertthat::assert_that( diff --git a/R/fetch_ats.R b/R/fetch_ats.R index ba558fb..8688125 100644 --- a/R/fetch_ats.R +++ b/R/fetch_ats.R @@ -125,6 +125,11 @@ ats_get <- function(path, task = "download data", ...) { httr::RETRY( "GET", url = ats_base_url, + httr::user_agent(paste( + "Mozilla/5.0 (Windows NT 10.0; Win64; x64)", + "AppleWebKit/537.36 (KHTML, like Gecko)", + "Chrome/103.0.0.0 Safari/537.36" + )), path = path, ..., quiet = TRUE @@ -645,6 +650,7 @@ ats_parse_txt <- function(resp, ...) { ) httr::content(resp, "text", encoding = "UTF-8") %>% + I() %>% readr::read_csv(...) } @@ -794,6 +800,11 @@ ats_post <- function(path, body = list(), task = "download data", ...) { path = path, body = body, encode = "form", + httr::user_agent(paste( + "Mozilla/5.0 (Windows NT 10.0; Win64; x64)", + "AppleWebKit/537.36 (KHTML, like Gecko)", + "Chrome/103.0.0.0 Safari/537.36" + )), ..., quiet = TRUE ) %>% @@ -971,7 +982,7 @@ fetch_ats_config <- function() { ), task = "download device configurations" ) %>% - ats_parse_txt(col_types = "cccccc") %>% + ats_parse_txt(col_types = "ccccccccccc") %>% dplyr::mutate( CollarSerialNumber = dplyr::if_else( grepl("^00", .data$CollarSerialNumber) & @@ -979,11 +990,9 @@ fetch_ats_config <- function() { substr(.data$CollarSerialNumber, 2, 7), .data$CollarSerialNumber ), - Active = dplyr::if_else(.data$Active == "yes", TRUE, FALSE), - RestEndPoint = dplyr::if_else( - .data$RestEndPoint == "yes", - TRUE, - FALSE + dplyr::across( + c(.data$Active, .data$RestEndPoint:.data$`SMS LowBatt`), + ~ dplyr::if_else(.x == "yes", TRUE, FALSE) ) ) From 917f5ec374b3e30cd2d7e405a5764e3bb344fee8 Mon Sep 17 00:00:00 2001 From: ericnewkirk <55846615+ericnewkirk@users.noreply.github.com> Date: Sat, 23 Jul 2022 11:58:42 -0600 Subject: [PATCH 02/10] Fix login issue * Avoid testing for cookie during login * Update tests * Bump version --- DESCRIPTION | 2 +- R/fetch_ats.R | 2 +- tests/testthat/test-fetch_ats.R | 7 ++++++- 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/DESCRIPTION b/DESCRIPTION index 7dc180c..7f76857 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,6 +1,6 @@ Package: collar Title: Utilities for Accessing and Manipulating GPS Data -Version: 0.0.4003 +Version: 0.0.4004 Authors@R: c( person("Josh", "Nowak", email = "josh.nowak@speedgoat.io", role = c("aut", "cre")), person("Forest", "Hayes", email = "forest.hayes@umontana.edu", role = "aut"), diff --git a/R/fetch_ats.R b/R/fetch_ats.R index 8688125..1875d68 100644 --- a/R/fetch_ats.R +++ b/R/fetch_ats.R @@ -775,7 +775,7 @@ ats_post <- function(path, body = list(), task = "download data", ...) { # check login assertthat::assert_that( - check_cookie(ats_base_url, "user"), + check_cookie(ats_base_url, "user") || "login" %in% unlist(body), msg = "You need to log in first." ) diff --git a/tests/testthat/test-fetch_ats.R b/tests/testthat/test-fetch_ats.R index 488c9ec..f237e19 100644 --- a/tests/testthat/test-fetch_ats.R +++ b/tests/testthat/test-fetch_ats.R @@ -18,7 +18,12 @@ check_data <- function(x, data_type) { "Active", "Phone Num SMS", "FTP Url", - "RestEndPoint" + "RestEndPoint", + # unclear if these columns are present for all accounts + "SMS All", + "SMS Mortality", + "SMS Birth", + "SMS Fawn" ), "events" = c( "CollarSerialNumber", From 2814ef5e70fc208629a464193f11d2b76508b451 Mon Sep 17 00:00:00 2001 From: Eric Newkirk <55846615+ericnewkirk@users.noreply.github.com> Date: Fri, 2 Sep 2022 20:38:06 -0600 Subject: [PATCH 03/10] JSON encoding --- R/fetch_vectronics.R | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/R/fetch_vectronics.R b/R/fetch_vectronics.R index 22c78ee..388a347 100644 --- a/R/fetch_vectronics.R +++ b/R/fetch_vectronics.R @@ -471,7 +471,7 @@ call_vec_api <- function(url, rename_fun = adj_col_nms) { ~{ pb$tick()$print() jsonlite::fromJSON( - httr::content(.x, "text"), + httr::content(.x, type = "text", encoding = "UTF-8"), simplifyVector = TRUE ) } From c7a20c4daa0432e9bf3f852180763146a3d590d4 Mon Sep 17 00:00:00 2001 From: Eric Newkirk <55846615+ericnewkirk@users.noreply.github.com> Date: Fri, 2 Sep 2022 20:55:03 -0600 Subject: [PATCH 04/10] Bump version --- DESCRIPTION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DESCRIPTION b/DESCRIPTION index 7f76857..c587ed1 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,6 +1,6 @@ Package: collar Title: Utilities for Accessing and Manipulating GPS Data -Version: 0.0.4004 +Version: 0.0.4005 Authors@R: c( person("Josh", "Nowak", email = "josh.nowak@speedgoat.io", role = c("aut", "cre")), person("Forest", "Hayes", email = "forest.hayes@umontana.edu", role = "aut"), From dbdbafd8b287846e24a389e030d87656c14c0b0c Mon Sep 17 00:00:00 2001 From: ericnewkirk <55846615+ericnewkirk@users.noreply.github.com> Date: Mon, 10 Jun 2024 18:37:54 -0600 Subject: [PATCH 05/10] Add track tag --- DESCRIPTION | 7 +- NAMESPACE | 5 + R/fetch_trktg.R | 307 +++++++++++++++++++++++++++++++++++ R/trktg_auth.R | 183 +++++++++++++++++++++ man/fetch_trktg_devices.Rd | 34 ++++ man/fetch_trktg_positions.Rd | 95 +++++++++++ man/trktg_login.Rd | 32 ++++ man/trktg_logout.Rd | 27 +++ man/trktg_token.Rd | 24 +++ 9 files changed, 712 insertions(+), 2 deletions(-) create mode 100644 R/fetch_trktg.R create mode 100644 R/trktg_auth.R create mode 100644 man/fetch_trktg_devices.Rd create mode 100644 man/fetch_trktg_positions.Rd create mode 100644 man/trktg_login.Rd create mode 100644 man/trktg_logout.Rd create mode 100644 man/trktg_token.Rd diff --git a/DESCRIPTION b/DESCRIPTION index db3482e..5af2449 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,6 +1,6 @@ Package: collar Title: Utilities for Accessing and Manipulating GPS Data -Version: 0.0.4005 +Version: 0.0.4006 Authors@R: c( person("Josh", "Nowak", email = "josh.nowak@speedgoat.io", role = c("aut", "cre")), person("Forest", "Hayes", email = "forest.hayes@umontana.edu", role = "aut"), @@ -17,7 +17,7 @@ BugReports: https://github.com/Huh/collar/issues Encoding: UTF-8 LazyData: true ByteCompile: true -RoxygenNote: 7.2.1 +RoxygenNote: 7.2.3 Imports: assertthat, curl, @@ -30,12 +30,15 @@ Imports: jsonlite, leaflet, magrittr, + methods, purrr, RCurl, readr, rlang, rvest, sf, + stats, + stringr, tibble, tidyr, xml2, diff --git a/NAMESPACE b/NAMESPACE index 67d19d1..9b89861 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -25,6 +25,8 @@ export(fetch_delim) export(fetch_lotek_alerts) export(fetch_lotek_devices) export(fetch_lotek_positions) +export(fetch_trktg_devices) +export(fetch_trktg_positions) export(fetch_vectronics) export(filter_date_range) export(filter_last_loc) @@ -42,6 +44,9 @@ export(save_map) export(style_scale_color) export(style_scale_fill) export(style_theme) +export(trktg_login) +export(trktg_logout) +export(trktg_token) import(rlang) import(tibble) importFrom(ggplot2,"%+replace%") diff --git a/R/fetch_trktg.R b/R/fetch_trktg.R new file mode 100644 index 0000000..b2d2ae8 --- /dev/null +++ b/R/fetch_trktg.R @@ -0,0 +1,307 @@ +################################################################################ +# +# Track Tag Download Functions +# +################################################################################ + +# 1 - Global Objects ------------------------------------------------------ + +# * 1.1 - trktg_empty_pos ------------------------------------------------- + +# tibble with zero rows matching track tag position file format + +trktg_empty_pos <- tibble::tibble( + device_id = character(0), + Date = as.POSIXct(NA), + Received = as.POSIXct(NA), + Address = character(0), + `Lat/Lng` = character(0), + Speed = character(0), + Heading = character(0), + Altitude = character(0), + Via = character(0), + `Near place(s)` = character(0), + `Inside geofence(s)` = character(0), + Extra = character(0), + `I/O` = character(0) +) + +# 2 - Download Functions -------------------------------------------------- + +# * 2.1 - fetch_trktg_positions ------------------------------------------- + +#' @title Download Position (Fix) Data from track tag website +#' +#' @description Retrieves GPS data optionally filtered by date or collar. +#' +#' @param device_id A single device id, or a list or vector of device ids, +#' or NULL for all devices associated with current account. Device ids +#' can be found on the track tag portal (Device ID/UID), or by examining the +#' `user_id` column in the tibble returned by \code{fetch_trktg_devices}. +#' @param start_date Only fixes at or after start_date will be included +#' in the output. Must be a POSIX date or date/time object. If NULL +#' Jan 1 1970 is used. +#' @param end_date Only fixes at or before end_date are included, +#' analagous to start_date above. If NULL current date/time is used. +#' @param time_zone Time zone used to convert date values to \code{POSIX}. +#' @param as_sf Boolean indicating if the result should be converted to an +#' \code{sf} object. +#' @param sf_crs Coordinate referenece system for converting to \code{sf}. Only +#' CRS 4326 (WGS84) has been tested, coordinates may not be parsed correctly +#' for other systems. +#' +#' @return A tibble or sf object with 21 columns: +#' \describe{ +#' \item{device_id}{User label assigned through track tag portal (character)} +#' \item{Date}{Fix date/time (POSIXct)} +#' \item{Received}{Date/time received via satellite (character)} +#' \item{Address}{Address nearest the GPS fix (character)} +#' \item{Lat/Lng}{GPS coordinates (character)} +#' \item{Speed}{Speed with units (character)} +#' \item{Heading}{Unknown (character)} +#' \item{Altitude}{Unknown (character)} +#' \item{Via}{Transmission method (character)} +#' \item{Near place(s)}{Unknown (character)} +#' \item{Inside geofence(s)}{Unknown (character)} +#' \item{Extra}{Unknown (character)} +#' \item{I/O}{Unknown (character)} +#' } +#' +#' @seealso \code{\link{fetch_trktg_devices}} for downloading a list of +#' transmitters associated with the current account. +#' +#' @export +#' +#' @examples +#' +#' trktg_login("some_user", "some_users_pw") +#' +#' # all fixes for all transmitters in 2024 +#' fixes <- fetch_trktg_positions( +#' start_date = "2024-01-01 00:00:00", +#' end_date = "2025-01-01 00:00:00" +#' ) +#' +#' # all fixes for a single transmitter +#' fixes_single_tr <- fetch_trktg_positions(device_id = "012345678") +#' +#' # all fixes for multiple transmitters +#' fixes_2_devices <- fetch_trktg_positions( +#' device_id = c("012345678", "012345679") +#' ) +#' +#' # fixes from the last week for a single transmitter +#' fixes <- fetch_trktg_positions( +#' device_id = "012345678", +#' start_date = Sys.Date() - 7 +#' ) +#' +#' # fixes from the last week as an sf object +#' fixes <- fetch_trktg_positions( +#' start_date = Sys.Date() - 7, +#' as_sf = TRUE +#' ) +#' +#' trktg_logout() +#' +fetch_trktg_positions <- function(device_id = NULL, + start_date = NULL, + end_date = NULL, + time_zone = Sys.timezone(), + as_sf = FALSE, + sf_crs = 4326) { + + # get login info + # function will exit here if login info is invalid + tkn <- trktg_token() + + body <- list( + `__RequestVerificationToken` = tkn, + IsForAllAssets = is.null(device_id), + IsAppliedToGroups = FALSE, + IsAppliedToAssets = !is.null(device_id) + ) + + if (!is.null(device_id)) { + + dev <- fetch_trktg_devices() %>% + dplyr::filter(.data$user_id %in% device_id) %>% + dplyr::pull(.data$api_id) + + dev <- dev %>% + rep(2) %>% + stats::setNames(c( + rep("CheckAssetIds", length(dev)), + rep("AssetIds", length(dev)) + )) + + body <- c(body, as.list(dev)) + + } + + body$From <- dplyr::if_else( + is.null(start_date), + "1/1/1970 00:00", + format(start_date, "%m/%d/%Y %R") + ) %>% + stringr::str_replace_all("0(\\d/)", "\\1") + + body$To <- dplyr::if_else( + is.null(end_date), + format(Sys.time(), "%m/%d/%Y %R"), + format(end_date, "%m/%d/%Y %R") + ) %>% + stringr::str_replace_all("0(\\d/)", "\\1") + + # send request + resp <- httr::RETRY( + "POST", + url = trktg_base_url, + path = list("Reports", "Position"), + body = body, + encode = "form", + quiet = TRUE + ) + + # verify successful status + assertthat::assert_that( + httr::status_code(resp) == 200, + msg = paste( + "API call failed - device list.", + paste("Status:", httr::status_code(resp)), + paste("Response:", httr::content(resp)), + sep = "\n" + ) + ) + + tbls <- resp %>% + httr::content() %>% + rvest::html_table() + + if (length(tbls)) { + + ids <- resp %>% + httr::content() %>% + xml2::xml_find_all("//div[table]/preceding-sibling::h3") %>% + xml2::xml_text() + + out <- purrr::map2( + ids, + tbls, + function(id, pos) { + tibble::tibble(device_id = id, pos) + } + ) %>% + dplyr::bind_rows() %>% + dplyr::select(dplyr::all_of(names(trktg_empty_pos))) %>% + dplyr::mutate( + dplyr::across( + .data$Date:.data$Received, + lubridate::mdy_hms, + tz = time_zone + ) + ) %>% + purrr::map2( + lapply(trktg_empty_pos, class), + function(col, cls) { + methods::as(col, cls[1]) + } + ) %>% + tibble::as_tibble() + + } else { + + out <- trktg_empty_pos + + } + + if (as_sf) { + + out <- out %>% + dplyr::mutate( + lng = stringr::str_extract(.data$`Lat/Lng`, "[0-9.-]+$"), + lat = stringr::str_extract(.data$`Lat/Lng`, "^[0-9.-]+") + ) %>% + sf::st_as_sf(coords = c("lng", "lat"), crs = sf_crs) + + } + + out + +} + +# * 2.2 - fetch_trktg_devices --------------------------------------------- + +#' @title Download Device List from track tag web portal +#' +#' @description Retrieves a list of devices (transmitters) associated +#' with the account currently logged in via \code{trktg_login}. +#' +#' @return A tibble with 3 character columns: +#' \describe{ +#' \item{api_id}{Six digit internal id used in api calls}, +#' \item{trktg_id}{Nine digit transmitter id (serial number)}, +#' \item{user_id}{User label assigned through track tag portal} +#' } +#' +#' @seealso \code{\link{fetch_trktg_positions}} for downloading GPS data. +#' +#' @export +#' +#' @examples +#' +#' trktg_login("some_user", "some_users_pw") +#' +#' tt_devices <- fetch_trktg_devices() +#' +#' tt_fixes <- fetch_trktg_positions(device_id = tt_devices$user_id[1]) +#' +#' trktg_logout() +#' +fetch_trktg_devices <- function() { + + # get login info + # function will exit here if login info is invalid + tkn <- trktg_token() + + # send request + resp <- httr::RETRY( + "GET", + url = trktg_base_url, + path = list("Reports", "Position"), + body = list( + `__RequestVerificationToken` = tkn + ), + encode = "form", + quiet = TRUE + ) + + # verify successful status + assertthat::assert_that( + httr::status_code(resp) == 200, + msg = paste( + "API call failed - device list.", + paste("Status:", httr::status_code(resp)), + paste("Response:", httr::content(resp)), + sep = "\n" + ) + ) + + # extract device ids from xml + label_nodes <- resp %>% + httr::content() %>% + xml2::xml_find_all("//label[contains(@for, 'asset')]") + + tibble::tibble( + api_id = label_nodes %>% + xml2::xml_attr("for") %>% + stringr::str_extract("\\d{6}"), + trktg_id = label_nodes %>% + xml2::xml_text() %>% + stringr::str_extract("(?<=\\()\\d{9}(?=\\))"), + user_id = label_nodes %>% + xml2::xml_text() %>% + stringr::str_extract("^.+(?= \\(\\d{9}\\))") + ) + +} diff --git a/R/trktg_auth.R b/R/trktg_auth.R new file mode 100644 index 0000000..2040767 --- /dev/null +++ b/R/trktg_auth.R @@ -0,0 +1,183 @@ +################################################################################ +# +# Track Tag Authentication Functions +# +################################################################################ + +# 1 - Global Objects ------------------------------------------------------ + +# * 1.1 - trktg_base_url (base url for track tag website) ----------------- + +trktg_base_url <- "https://www.tracktagllc.com" + +# * 1.2 - trktg.env (environment for managing authentication info) -------- + +trktg.env <- new.env() + +# 2 - Internal Functions -------------------------------------------------- + +# * 2.1 - trktg_token ----------------------------------------------------- + +#' @title Track Tag Request Verification Token +#' +#' @return Character request verification token for http requests. +#' +#' @section Notes: +#' +#' There is also a cookie called \code{__RequestVerificationToken} set when +#' logging in, but it doesn't appear to be used in subsequent requests. The +#' token returned here is generated in a hidden input in the login page, and +#' must be passed as form data in subsequent requests. +#' +#' @export +#' +#' @keywords internal +#' +trktg_token <- function() { + + assertthat::assert_that( + "rvt" %in% ls(envir = trktg.env), + msg = paste( + "No login information available.", + "Use the trktg_login function to log in to your Track Tag account", + sep = "\n" + ) + ) + + trktg.env$rvt + +} + +# 3 - Visible Functions --------------------------------------------------- + +# * 3.1 - trktg_login ----------------------------------------------------- + +#' @title Authenticate to Track Tag website +#' +#' @description Send username and password info to Track Tag website +#' to log in to a user account. +#' +#' @param usr username The username associated with the account +#' @param pwd password The password used with the supplied username +#' +#' @return True if login succeeds, false if not. +#' +#' @seealso \code{\link{trktg_logout}} for closing the session. +#' +#' @export +#' +#' @examples +#' +#' trktg_login("some_user", "some_users_pw") +#' +#' fixes <- fetch_trktg_positions() +#' +#' trktg_logout() +#' +trktg_login <- function(usr, pwd) { + + # clear existing login info + suppressWarnings(rm(rvt, envir = trktg.env)) + + # use get request to obtain request verification token + resp <- httr::RETRY( + "GET", + url = trktg_base_url, + path = list("Login"), + query = list(local = 1) + ) + + assertthat::assert_that( + httr::status_code(resp) == 200, + msg = paste( + "Unable to access track tag website.", + paste("Status:", httr::status_code(resp)), + paste("Response:", httr::content(resp)), + sep = "\n" + ) + ) + + rvt <- resp %>% + httr::content() %>% + xml2::xml_find_first("//input[@name='__RequestVerificationToken']") %>% + xml2::xml_attr("value") + + assertthat::assert_that( + !is.na(rvt), + msg = "Unable to parse track tag token." + ) + + # submit form to authenticate + resp <- httr::RETRY( + "POST", + url = trktg_base_url, + path = list("Login"), + query = list(local = 1), + body = list( + `__RequestVerificationToken` = rvt, + UserName = usr, + Password = pwd, + PrivacyAgree = TRUE, + RememberMe = FALSE + ), + encode = "form", + quiet = TRUE + ) + + # check call was successful + resp_title <- resp %>% + httr::content() %>% + xml2::xml_find_first("//title") %>% + xml2::xml_text() + + assertthat::assert_that( + httr::status_code(resp) == 200 && !grepl("Please Login", resp_title), + msg = paste( + "Login failed.", + paste("Status:", httr::status_code(resp)), + paste("Response:", httr::content(resp)), + sep = "\n" + ) + ) + + trktg.env$rvt <- rvt + + # return true if successful + "rvt" %in% ls(envir = trktg.env) + +} + +# * 3.2 - trktg_logout ---------------------------------------------------- + +#' @title Close Track Tag Session +#' +#' @description Removes authentication info from memory and logs out of +#' Track Tag website. +#' +#' @return True if login info is erased, false if not. +#' +#' @seealso \code{\link{trktg_login}} for starting the session. +#' +#' @export +#' +#' @examples +#' +#' trktg_login("some_user", "some_users_pw") +#' +#' fixes <- fetch_trktg_positions() +#' +#' trktg_logout() +#' +trktg_logout <- function() { + + resp <- httr::RETRY( + "GET", + url = trktg_base_url, + path = list("account", "logoff") + ) + + suppressWarnings(rm("rvt", envir = trktg.env)) + + length(ls(envir = trktg.env)) == 0 && httr::status_code(resp) == 200 + +} diff --git a/man/fetch_trktg_devices.Rd b/man/fetch_trktg_devices.Rd new file mode 100644 index 0000000..14b7e71 --- /dev/null +++ b/man/fetch_trktg_devices.Rd @@ -0,0 +1,34 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/fetch_trktg.R +\name{fetch_trktg_devices} +\alias{fetch_trktg_devices} +\title{Download Device List from track tag web portal} +\usage{ +fetch_trktg_devices() +} +\value{ +A tibble with 3 character columns: +\describe{ + \item{api_id}{Six digit internal id used in api calls}, + \item{trktg_id}{Nine digit transmitter id (serial number)}, + \item{user_id}{User label assigned through track tag portal} +} +} +\description{ +Retrieves a list of devices (transmitters) associated + with the account currently logged in via \code{trktg_login}. +} +\examples{ + +trktg_login("some_user", "some_users_pw") + +tt_devices <- fetch_trktg_devices() + +tt_fixes <- fetch_trktg_positions(device_id = tt_devices$user_id[1]) + +trktg_logout() + +} +\seealso{ +\code{\link{fetch_trktg_positions}} for downloading GPS data. +} diff --git a/man/fetch_trktg_positions.Rd b/man/fetch_trktg_positions.Rd new file mode 100644 index 0000000..e01f02f --- /dev/null +++ b/man/fetch_trktg_positions.Rd @@ -0,0 +1,95 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/fetch_trktg.R +\name{fetch_trktg_positions} +\alias{fetch_trktg_positions} +\title{Download Position (Fix) Data from track tag website} +\usage{ +fetch_trktg_positions( + device_id = NULL, + start_date = NULL, + end_date = NULL, + time_zone = Sys.timezone(), + as_sf = FALSE, + sf_crs = 4326 +) +} +\arguments{ +\item{device_id}{A single device id, or a list or vector of device ids, +or NULL for all devices associated with current account. Device ids +can be found on the track tag portal (Device ID/UID), or by examining the +`user_id` column in the tibble returned by \code{fetch_trktg_devices}.} + +\item{start_date}{Only fixes at or after start_date will be included +in the output. Must be a POSIX date or date/time object. If NULL +Jan 1 1970 is used.} + +\item{end_date}{Only fixes at or before end_date are included, +analagous to start_date above. If NULL current date/time is used.} + +\item{time_zone}{Time zone used to convert date values to \code{POSIX}.} + +\item{as_sf}{Boolean indicating if the result should be converted to an +\code{sf} object.} + +\item{sf_crs}{Coordinate referenece system for converting to \code{sf}. Only +CRS 4326 (WGS84) has been tested, coordinates may not be parsed correctly +for other systems.} +} +\value{ +A tibble or sf object with 21 columns: +\describe{ + \item{device_id}{User label assigned through track tag portal (character)} + \item{Date}{Fix date/time (POSIXct)} + \item{Received}{Date/time received via satellite (character)} + \item{Address}{Address nearest the GPS fix (character)} + \item{Lat/Lng}{GPS coordinates (character)} + \item{Speed}{Speed with units (character)} + \item{Heading}{Unknown (character)} + \item{Altitude}{Unknown (character)} + \item{Via}{Transmission method (character)} + \item{Near place(s)}{Unknown (character)} + \item{Inside geofence(s)}{Unknown (character)} + \item{Extra}{Unknown (character)} + \item{I/O}{Unknown (character)} +} +} +\description{ +Retrieves GPS data optionally filtered by date or collar. +} +\examples{ + +trktg_login("some_user", "some_users_pw") + +# all fixes for all transmitters in 2024 +fixes <- fetch_trktg_positions( + start_date = "2024-01-01 00:00:00", + end_date = "2025-01-01 00:00:00" +) + +# all fixes for a single transmitter +fixes_single_tr <- fetch_trktg_positions(device_id = "012345678") + +# all fixes for multiple transmitters +fixes_2_devices <- fetch_trktg_positions( + device_id = c("012345678", "012345679") +) + +# fixes from the last week for a single transmitter +fixes <- fetch_trktg_positions( + device_id = "012345678", + start_date = Sys.Date() - 7 +) + +# fixes from the last week as an sf object +fixes <- fetch_trktg_positions( + start_date = Sys.Date() - 7, + as_sf = TRUE +) + +trktg_logout() + +} +\seealso{ +\code{\link{fetch_trktg_devices}} for downloading a list of + transmitters associated with the current account. +} diff --git a/man/trktg_login.Rd b/man/trktg_login.Rd new file mode 100644 index 0000000..5e93763 --- /dev/null +++ b/man/trktg_login.Rd @@ -0,0 +1,32 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/trktg_auth.R +\name{trktg_login} +\alias{trktg_login} +\title{Authenticate to Track Tag website} +\usage{ +trktg_login(usr, pwd) +} +\arguments{ +\item{usr}{username The username associated with the account} + +\item{pwd}{password The password used with the supplied username} +} +\value{ +True if login succeeds, false if not. +} +\description{ +Send username and password info to Track Tag website + to log in to a user account. +} +\examples{ + +trktg_login("some_user", "some_users_pw") + +fixes <- fetch_trktg_positions() + +trktg_logout() + +} +\seealso{ +\code{\link{trktg_logout}} for closing the session. +} diff --git a/man/trktg_logout.Rd b/man/trktg_logout.Rd new file mode 100644 index 0000000..e9f908a --- /dev/null +++ b/man/trktg_logout.Rd @@ -0,0 +1,27 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/trktg_auth.R +\name{trktg_logout} +\alias{trktg_logout} +\title{Close Track Tag Session} +\usage{ +trktg_logout() +} +\value{ +True if login info is erased, false if not. +} +\description{ +Removes authentication info from memory and logs out of + Track Tag website. +} +\examples{ + +trktg_login("some_user", "some_users_pw") + +fixes <- fetch_trktg_positions() + +trktg_logout() + +} +\seealso{ +\code{\link{trktg_login}} for starting the session. +} diff --git a/man/trktg_token.Rd b/man/trktg_token.Rd new file mode 100644 index 0000000..b50afad --- /dev/null +++ b/man/trktg_token.Rd @@ -0,0 +1,24 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/trktg_auth.R +\name{trktg_token} +\alias{trktg_token} +\title{Track Tag Request Verification Token} +\usage{ +trktg_token() +} +\value{ +Character request verification token for http requests. +} +\description{ +Track Tag Request Verification Token +} +\section{Notes}{ + + + There is also a cookie called \code{__RequestVerificationToken} set when + logging in, but it doesn't appear to be used in subsequent requests. The + token returned here is generated in a hidden input in the login page, and + must be passed as form data in subsequent requests. +} + +\keyword{internal} From ecc99a4839cac547c81901d25a2b017f08dfdea0 Mon Sep 17 00:00:00 2001 From: ericnewkirk <55846615+ericnewkirk@users.noreply.github.com> Date: Fri, 26 Jul 2024 16:46:13 -0600 Subject: [PATCH 06/10] across syntax update --- R/fetch_ats.R | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/R/fetch_ats.R b/R/fetch_ats.R index ac9b7ad..a9263bd 100644 --- a/R/fetch_ats.R +++ b/R/fetch_ats.R @@ -992,7 +992,7 @@ fetch_ats_config <- function() { ), dplyr::across( c(.data$Active, .data$RestEndPoint:.data$`SMS LowBatt`), - ~ dplyr::if_else(.x == "yes", TRUE, FALSE) + function(x) dplyr::if_else(x == "yes", TRUE, FALSE) ) ) From 206da3cc290b24a2963d11794494796b77da75a6 Mon Sep 17 00:00:00 2001 From: ericnewkirk <55846615+ericnewkirk@users.noreply.github.com> Date: Fri, 26 Jul 2024 16:47:25 -0600 Subject: [PATCH 07/10] minor updates * remove stringr * if_else bug * doc typos --- R/fetch_trktg.R | 73 +++++++++++++++++++++++++++++++------------------ 1 file changed, 47 insertions(+), 26 deletions(-) diff --git a/R/fetch_trktg.R b/R/fetch_trktg.R index ed177ac..ff5ba2c 100644 --- a/R/fetch_trktg.R +++ b/R/fetch_trktg.R @@ -42,11 +42,11 @@ trktg_empty_pos <- tibble::tibble( #' in the output. Must be a POSIX date or date/time object. If NULL #' Jan 1 1970 is used. #' @param end_date Only fixes at or before end_date are included, -#' analagous to start_date above. If NULL current date/time is used. +#' analogous to start_date above. If NULL current date/time is used. #' @param time_zone Time zone used to convert date values to \code{POSIX}. #' @param as_sf Boolean indicating if the result should be converted to an #' \code{sf} object. -#' @param sf_crs Coordinate referenece system for converting to \code{sf}. Only +#' @param sf_crs Coordinate reference system for converting to \code{sf}. Only #' CRS 4326 (WGS84) has been tested, coordinates may not be parsed correctly #' for other systems. #' @@ -139,19 +139,21 @@ fetch_trktg_positions <- function(device_id = NULL, } - body$From <- dplyr::if_else( - is.null(start_date), - "1/1/1970 00:00", - format(start_date, "%m/%d/%Y %R") - ) %>% - stringr::str_replace_all("0(\\d/)", "\\1") + if (is.null(start_date)) { + body$From <- "1/1/1970 00:00" + } else { + body$From <- format(start_date, "%m/%d/%Y %R") + } + + body$From <- gsub("0(\\d/)", "\\1", body$From) + + if (is.null(end_date)) { + body$To <- format(Sys.time(), "%m/%d/%Y %R") + } else { + body$To <- format(end_date, "%m/%d/%Y %R") + } - body$To <- dplyr::if_else( - is.null(end_date), - format(Sys.time(), "%m/%d/%Y %R"), - format(end_date, "%m/%d/%Y %R") - ) %>% - stringr::str_replace_all("0(\\d/)", "\\1") + body$To <- gsub("0(\\d/)", "\\1", body$To) # send request resp <- httr::RETRY( @@ -167,7 +169,7 @@ fetch_trktg_positions <- function(device_id = NULL, assertthat::assert_that( httr::status_code(resp) == 200, msg = paste( - "API call failed - device list.", + "API call failed - position report.", paste("Status:", httr::status_code(resp)), paste("Response:", httr::content(resp)), sep = "\n" @@ -219,8 +221,14 @@ fetch_trktg_positions <- function(device_id = NULL, out <- out %>% dplyr::mutate( - lng = stringr::str_extract(.data$`Lat/Lng`, "[0-9.-]+$"), - lat = stringr::str_extract(.data$`Lat/Lng`, "^[0-9.-]+") + lng = regmatches( + .data$`Lat/Lng`, + regexpr("[0-9.-]+$", .data$`Lat/Lng`) + ), + lat = regmatches( + .data$`Lat/Lng`, + regexpr("^[0-9.-]+", .data$`Lat/Lng`) + ) ) %>% sf::st_as_sf(coords = c("lng", "lat"), crs = sf_crs) @@ -292,16 +300,29 @@ fetch_trktg_devices <- function() { httr::content() %>% xml2::xml_find_all("//label[contains(@for, 'asset')]") + api_id <- label_nodes %>% + xml2::xml_attr("for") + + api_id <- regmatches(api_id, regexpr("\\d{6}", api_id)) + + lbl_txt <- label_nodes %>% + xml2::xml_text() + + trktg_id <- regmatches( + lbl_txt, + regexpr("(?<=\\()\\d{9}(?=\\))", lbl_txt, perl = TRUE) + ) + + user_id <- regmatches( + lbl_txt, + regexpr("^.+(?= \\(\\d{9}\\))", lbl_txt, perl = TRUE) + ) + + # return tibble tibble::tibble( - api_id = label_nodes %>% - xml2::xml_attr("for") %>% - stringr::str_extract("\\d{6}"), - trktg_id = label_nodes %>% - xml2::xml_text() %>% - stringr::str_extract("(?<=\\()\\d{9}(?=\\))"), - user_id = label_nodes %>% - xml2::xml_text() %>% - stringr::str_extract("^.+(?= \\(\\d{9}\\))") + api_id = api_id, + trktg_id = trktg_id, + user_id = user_id ) } From 033015b41786ffa0e19ba3c75b1319f4df17cab9 Mon Sep 17 00:00:00 2001 From: ericnewkirk <55846615+ericnewkirk@users.noreply.github.com> Date: Fri, 26 Jul 2024 16:51:03 -0600 Subject: [PATCH 08/10] minor updates, fix status parser * doc typos * if_else bug * add_lotek_status --- R/fetch_lotek.R | 221 +++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 209 insertions(+), 12 deletions(-) diff --git a/R/fetch_lotek.R b/R/fetch_lotek.R index e4d9e4e..15a6bc6 100644 --- a/R/fetch_lotek.R +++ b/R/fetch_lotek.R @@ -165,7 +165,7 @@ fetch_lotek_devices <- function() { #' in the output. Must be in the format YYYY-MM-DD HH:MM:SS. If NULL #' Jan 1 1970 is used. #' @param end_date Only fixes at or before end_date are included, -#' analagous to start_date above. If NULL current date/time is used. +#' analogous to start_date above. If NULL current date/time is used. #' #' @return A tibble containing position data, or an empty tibble in the #' same format is no rows are returned. @@ -203,21 +203,22 @@ fetch_lotek_positions <- function(device_id = NULL, # function will exit here if login info is invalid tkn <- lotek_token() - st <- dplyr::if_else( - is.null(start_date), - "1970-01-01T00:00:00Z", - start_date) + if (is.null(start_date)) { + st <- "1970-01-01T00:00:00Z" + } else { + st <- start_date + } - end <- dplyr::if_else( - is.null(end_date), - paste0( - gsub(" ", "T", lubridate::now(tzone = "GMT")), - "Z"), - end_date) + if (is.null(end_date)) { + end <- paste0(lubridate::today(tzone = "GMT"), "T23:59:59Z") + } else { + end <- end_date + } dev <- paste0( device_id, - collapse = ",") + collapse = "," + ) # send request resp <- httr::RETRY( @@ -281,3 +282,199 @@ fetch_lotek_positions <- function(device_id = NULL, } } + +#' @title Add Lotek Status +#' +#' @description Parses coded values in RxStatus column of API response. +#' +#' @section Notes: +#' +#' See Lotek Web Service API User Manual Revision 03 (30 MAY 2024) +#' +#' @param lotek_positions A data frame of GPS data matching the format returned +#' by \code{\link{fetch_lotek_positions}}. +#' @param position_type One of 'Litetrack (Standard fix)', +#' 'Litetrack (Swift fix)', or 'Iridium Track'. Determines how the information +#' in the FixType and RxStatus columns is parsed. See API User Manual for +#' details. If you have more than one position type in the same account +#' separate them before passing into this function (see aexamples). +#' +#' @return A tibble containing the original position data with additional +#' columns containing fix status information and in some cases the number of +#' satellites. +#' +#' @seealso \code{\link{fetch_lotek_positions}} +#' +#' @export +#' +#' @examples +#' \dontrun{ +#' +#' lotek_login("demo", "PASSWORD09") +#' +#' # download and parse all data - standard fixes +#' fixes <- fetch_lotek_positions() |> +#' add_lotek_status() +#' +#' # download and parse all data - swift fixes +#' fixes <- fetch_lotek_positions() |> +#' add_lotek_status("Litetrack (Swift fix)") +#' +#' # download and parse all data - iridium +#' fixes <- fetch_lotek_positions() |> +#' add_lotek_status("Iridium Track") +#' +#' # if data contains collars with different position types... +#' standard_dev <- c(34023, 42492) +#' swift_dev <- 32763 +#' +#' # download all, split, add status, and recombine... +#' fixes <- fetch_lotek_positions() +#' standard_fixes <- fixes |> +#' dplyr::filter(DeviceID %in% standard_dev) |> +#' add_lotek_status() +#' swift_fixes <- fixes |> +#' dplyr::filter(DeviceID %in% swift_dev) |> +#' add_lotek_status("Litetrack (Swift fix)") +#' fixes <- standard_fixes |> +#' dplyr::bind_rows(swift_fixes) +#' +#' # or download separately, add status, and combine +#' standard_fixes <- fetch_lotek_positions(device_id = standard_dev) |> +#' add_lotek_status() +#' swift_fixes <- fetch_lotek_positions(device_id = swift_dev) |> +#' add_lotek_status("Litetrack (Swift fix)") +#' fixes <- standard_fixes |> +#' dplyr::bind_rows(swift_fixes) +#' +#' } +add_lotek_status <- function(lotek_positions, + position_type = c("Litetrack (Standard fix)", + "Litetrack (Swift fix)", + "Iridium Track")) { + + pos_type <- match.arg(position_type) + + if (pos_type == "Iridium Track") { + + join_tbl <- tibble::tibble( + RxStatus = c(0L, 3L, 4L, 19L, 20L), + FixStatus = c( + "No satellites", "2D fix", "3D fix", + "2D validated fix", "3D validated fix" + ) + ) + + out <- lotek_positions %>% + dplyr::left_join(join_tbl, by = "RxStatus") + + } + + if (pos_type == "Litetrack (Standard fix)") { + + join_tbl <- tibble::tibble( + StatusCode = 0L:7L, + FixStatus = c( + "No fix", "1_SV KF Solution", "2_SV KF", "3_SV KF", + "4 or more SV KF", "2-D least-squares", "3-D least-squares", "DR" + ) + ) + + out <- lotek_positions %>% + dplyr::mutate( + StatusCode = lotek_status_code(.data$RxStatus), + NumSats = lotek_num_sats(.data$RxStatus) + ) %>% + dplyr::left_join(join_tbl, by = "StatusCode") + + } + + if (pos_type == "Litetrack (Swift fix)") { + + ft_join_tbl <- tibble::tibble( + FixType = 0L:3L, + FixTypeText = c( + "Time out", "Standard fix", "Swift fix", "Iridium position" + ) + ) + + rx_join_tbl <- tibble::tibble( + FixType = c(rep(1L, 8), rep(2L, 3)), + StatusCode = c(0L:7L, 0L:2L), + FixStatus = c( + "No fix", "1_SV KF Solution", "2_SV KF", "3_SV KF", + "4 or more SV KF", "2-D least-squares", "3-D least-squares", "DR", + "Valid fix", "Not enough satellites", "No ephemeris" + ) + ) + + out <- lotek_positions %>% + dplyr::mutate( + StatusCode = lotek_status_code(.data$RxStatus) + ) %>% + dplyr::left_join(ft_join_tbl, by = "FixType") %>% + dplyr::left_join(rx_join_tbl, by = c("FixType", "StatusCode")) + + } + + out + +} + +#' @title Parse Lotek Status Code +#' +#' @description Converts integers in RxStatus column of API response to integer +#' fix status codes. +#' +#' @section Notes: +#' +#' See Lotek Web Service API User Manual Revision 03 (30 MAY 2024) +#' +#' @param int_values Vector of integers from API response +#' +#' @return Vector of integer status codes +#' +#' @seealso \code{\link{lotek_num_sats}} +#' +#' @export +#' +#' @keywords internal +#' +lotek_status_code <- function(int_values) { + + vapply( + int_values, + function(i) sum(as.integer(intToBits(i)[1:3]) * c(1L, 2L, 4L)), + FUN.VALUE = integer(1) + ) + +} + +#' @title Parse Lotek Number of Satellites +#' +#' @description Converts integers in RxStatus column of API response to number +#' of satellites. +#' +#' @section Notes: +#' +#' See Lotek Web Service API User Manual Revision 03 (30 MAY 2024) +#' +#' @param int_values Vector of integers from API response +#' +#' @return Intger vector representing number of satellites for each fix +#' +#' @seealso \code{\link{lotek_status_code}} +#' +#' @export +#' +#' @keywords internal +#' +lotek_num_sats <- function(int_values) { + + vapply( + int_values, + function(i) sum(as.integer(intToBits(i)[4:7]) * c(1L, 2L, 4L, 8L)), + FUN.VALUE = integer(1) + ) + +} From fddd17514d2449ecedf6546690e66a219856b86d Mon Sep 17 00:00:00 2001 From: ericnewkirk <55846615+ericnewkirk@users.noreply.github.com> Date: Fri, 26 Jul 2024 16:51:36 -0600 Subject: [PATCH 09/10] version bump etc --- DESCRIPTION | 3 +- NAMESPACE | 3 ++ man/add_lotek_status.Rd | 80 ++++++++++++++++++++++++++++++++++++ man/fetch_lotek_positions.Rd | 2 +- man/fetch_trktg_positions.Rd | 4 +- man/lotek_num_sats.Rd | 28 +++++++++++++ man/lotek_status_code.Rd | 28 +++++++++++++ 7 files changed, 143 insertions(+), 5 deletions(-) create mode 100644 man/add_lotek_status.Rd create mode 100644 man/lotek_num_sats.Rd create mode 100644 man/lotek_status_code.Rd diff --git a/DESCRIPTION b/DESCRIPTION index 79b1170..36426c1 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,6 +1,6 @@ Package: collar Title: Utilities for Accessing and Manipulating GPS Data -Version: 0.0.4006 +Version: 0.0.4007 Authors@R: c( person("Josh", "Nowak", email = "josh.nowak@speedgoat.io", role = c("aut", "cre")), person("Forest", "Hayes", email = "forest.hayes@umontana.edu", role = "aut"), @@ -39,7 +39,6 @@ Imports: rvest, sf, stats, - stringr, tibble, tidyr, xml2, diff --git a/NAMESPACE b/NAMESPACE index 9b89861..ee330b7 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -1,5 +1,6 @@ # Generated by roxygen2: do not edit by hand +export(add_lotek_status) export(ats_get) export(ats_join_trans) export(ats_login) @@ -35,7 +36,9 @@ export(get_keys) export(get_paths) export(lotek_login) export(lotek_logout) +export(lotek_num_sats) export(lotek_refresh_token) +export(lotek_status_code) export(lotek_token) export(make_gpx) export(make_map) diff --git a/man/add_lotek_status.Rd b/man/add_lotek_status.Rd new file mode 100644 index 0000000..6359b29 --- /dev/null +++ b/man/add_lotek_status.Rd @@ -0,0 +1,80 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/fetch_lotek.R +\name{add_lotek_status} +\alias{add_lotek_status} +\title{Add Lotek Status} +\usage{ +add_lotek_status( + lotek_positions, + position_type = c("Litetrack (Standard fix)", "Litetrack (Swift fix)", "Iridium Track") +) +} +\arguments{ +\item{lotek_positions}{A data frame of GPS data matching the format returned +by \code{\link{fetch_lotek_positions}}.} + +\item{position_type}{One of 'Litetrack (Standard fix)', +'Litetrack (Swift fix)', or 'Iridium Track'. Determines how the information +in the FixType and RxStatus columns is parsed. See API User Manual for +details. If you have more than one position type in the same account +separate them before passing into this function (see aexamples).} +} +\value{ +A tibble containing the original position data with additional + columns containing fix status information and in some cases the number of + satellites. +} +\description{ +Parses coded values in RxStatus column of API response. +} +\section{Notes}{ + + + See Lotek Web Service API User Manual Revision 03 (30 MAY 2024) +} + +\examples{ +\dontrun{ + +lotek_login("demo", "PASSWORD09") + +# download and parse all data - standard fixes +fixes <- fetch_lotek_positions() |> + add_lotek_status() + +# download and parse all data - swift fixes +fixes <- fetch_lotek_positions() |> + add_lotek_status("Litetrack (Swift fix)") + +# download and parse all data - iridium +fixes <- fetch_lotek_positions() |> + add_lotek_status("Iridium Track") + +# if data contains collars with different position types... +standard_dev <- c(34023, 42492) +swift_dev <- 32763 + +# download all, split, add status, and recombine... +fixes <- fetch_lotek_positions() +standard_fixes <- fixes |> + dplyr::filter(DeviceID \%in\% standard_dev) |> + add_lotek_status() +swift_fixes <- fixes |> + dplyr::filter(DeviceID \%in\% swift_dev) |> + add_lotek_status("Litetrack (Swift fix)") +fixes <- standard_fixes |> + dplyr::bind_rows(swift_fixes) + +# or download separately, add status, and combine +standard_fixes <- fetch_lotek_positions(device_id = standard_dev) |> + add_lotek_status() +swift_fixes <- fetch_lotek_positions(device_id = swift_dev) |> + add_lotek_status("Litetrack (Swift fix)") +fixes <- standard_fixes |> + dplyr::bind_rows(swift_fixes) + +} +} +\seealso{ +\code{\link{fetch_lotek_positions}} +} diff --git a/man/fetch_lotek_positions.Rd b/man/fetch_lotek_positions.Rd index 72ec2b8..545d06a 100644 --- a/man/fetch_lotek_positions.Rd +++ b/man/fetch_lotek_positions.Rd @@ -15,7 +15,7 @@ in the output. Must be in the format YYYY-MM-DD HH:MM:SS. If NULL Jan 1 1970 is used.} \item{end_date}{Only fixes at or before end_date are included, -analagous to start_date above. If NULL current date/time is used.} +analogous to start_date above. If NULL current date/time is used.} } \value{ A tibble containing position data, or an empty tibble in the diff --git a/man/fetch_trktg_positions.Rd b/man/fetch_trktg_positions.Rd index 7ef7eb6..7dfd21a 100644 --- a/man/fetch_trktg_positions.Rd +++ b/man/fetch_trktg_positions.Rd @@ -24,14 +24,14 @@ in the output. Must be a POSIX date or date/time object. If NULL Jan 1 1970 is used.} \item{end_date}{Only fixes at or before end_date are included, -analagous to start_date above. If NULL current date/time is used.} +analogous to start_date above. If NULL current date/time is used.} \item{time_zone}{Time zone used to convert date values to \code{POSIX}.} \item{as_sf}{Boolean indicating if the result should be converted to an \code{sf} object.} -\item{sf_crs}{Coordinate referenece system for converting to \code{sf}. Only +\item{sf_crs}{Coordinate reference system for converting to \code{sf}. Only CRS 4326 (WGS84) has been tested, coordinates may not be parsed correctly for other systems.} } diff --git a/man/lotek_num_sats.Rd b/man/lotek_num_sats.Rd new file mode 100644 index 0000000..4410cf0 --- /dev/null +++ b/man/lotek_num_sats.Rd @@ -0,0 +1,28 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/fetch_lotek.R +\name{lotek_num_sats} +\alias{lotek_num_sats} +\title{Parse Lotek Number of Satellites} +\usage{ +lotek_num_sats(int_values) +} +\arguments{ +\item{int_values}{Vector of integers from API response} +} +\value{ +Intger vector representing number of satellites for each fix +} +\description{ +Converts integers in RxStatus column of API response to number + of satellites. +} +\section{Notes}{ + + + See Lotek Web Service API User Manual Revision 03 (30 MAY 2024) +} + +\seealso{ +\code{\link{lotek_status_code}} +} +\keyword{internal} diff --git a/man/lotek_status_code.Rd b/man/lotek_status_code.Rd new file mode 100644 index 0000000..92aea6f --- /dev/null +++ b/man/lotek_status_code.Rd @@ -0,0 +1,28 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/fetch_lotek.R +\name{lotek_status_code} +\alias{lotek_status_code} +\title{Parse Lotek Status Code} +\usage{ +lotek_status_code(int_values) +} +\arguments{ +\item{int_values}{Vector of integers from API response} +} +\value{ +Vector of integer status codes +} +\description{ +Converts integers in RxStatus column of API response to integer + fix status codes. +} +\section{Notes}{ + + + See Lotek Web Service API User Manual Revision 03 (30 MAY 2024) +} + +\seealso{ +\code{\link{lotek_num_sats}} +} +\keyword{internal} From d6ae39959d7cf91ffde354f566f7c2019f4063e8 Mon Sep 17 00:00:00 2001 From: ericnewkirk <55846615+ericnewkirk@users.noreply.github.com> Date: Fri, 26 Jul 2024 16:56:28 -0600 Subject: [PATCH 10/10] tt demo creds --- R/fetch_trktg.R | 4 ++-- R/trktg_auth.R | 4 ++-- man/fetch_trktg_devices.Rd | 2 +- man/fetch_trktg_positions.Rd | 2 +- man/trktg_login.Rd | 2 +- man/trktg_logout.Rd | 2 +- 6 files changed, 8 insertions(+), 8 deletions(-) diff --git a/R/fetch_trktg.R b/R/fetch_trktg.R index ff5ba2c..2cc801a 100644 --- a/R/fetch_trktg.R +++ b/R/fetch_trktg.R @@ -74,7 +74,7 @@ trktg_empty_pos <- tibble::tibble( #' #' @examples #' \dontrun{ -#' trktg_login("some_user", "some_users_pw") +#' trktg_login("WyoDemo", "WYODEMO2024") #' #' # all fixes for all transmitters in 2024 #' fixes <- fetch_trktg_positions( @@ -258,7 +258,7 @@ fetch_trktg_positions <- function(device_id = NULL, #' #' @examples #' \dontrun{ -#' trktg_login("some_user", "some_users_pw") +#' trktg_login("WyoDemo", "WYODEMO2024") #' #' tt_devices <- fetch_trktg_devices() #' diff --git a/R/trktg_auth.R b/R/trktg_auth.R index 4d7fda9..934a6b1 100644 --- a/R/trktg_auth.R +++ b/R/trktg_auth.R @@ -68,7 +68,7 @@ trktg_token <- function() { #' #' @examples #' \dontrun{ -#' trktg_login("some_user", "some_users_pw") +#' trktg_login("WyoDemo", "WYODEMO2024") #' #' fixes <- fetch_trktg_positions() #' @@ -162,7 +162,7 @@ trktg_login <- function(usr, pwd) { #' #' @examples #' \dontrun{ -#' trktg_login("some_user", "some_users_pw") +#' trktg_login("WyoDemo", "WYODEMO2024") #' #' fixes <- fetch_trktg_positions() #' diff --git a/man/fetch_trktg_devices.Rd b/man/fetch_trktg_devices.Rd index 20f1d69..8d3ecd1 100644 --- a/man/fetch_trktg_devices.Rd +++ b/man/fetch_trktg_devices.Rd @@ -20,7 +20,7 @@ Retrieves a list of devices (transmitters) associated } \examples{ \dontrun{ -trktg_login("some_user", "some_users_pw") +trktg_login("WyoDemo", "WYODEMO2024") tt_devices <- fetch_trktg_devices() diff --git a/man/fetch_trktg_positions.Rd b/man/fetch_trktg_positions.Rd index 7dfd21a..a8fd4ee 100644 --- a/man/fetch_trktg_positions.Rd +++ b/man/fetch_trktg_positions.Rd @@ -58,7 +58,7 @@ Retrieves GPS data optionally filtered by date or collar. } \examples{ \dontrun{ -trktg_login("some_user", "some_users_pw") +trktg_login("WyoDemo", "WYODEMO2024") # all fixes for all transmitters in 2024 fixes <- fetch_trktg_positions( diff --git a/man/trktg_login.Rd b/man/trktg_login.Rd index 5c673f2..3caf839 100644 --- a/man/trktg_login.Rd +++ b/man/trktg_login.Rd @@ -20,7 +20,7 @@ Send username and password info to Track Tag website } \examples{ \dontrun{ -trktg_login("some_user", "some_users_pw") +trktg_login("WyoDemo", "WYODEMO2024") fixes <- fetch_trktg_positions() diff --git a/man/trktg_logout.Rd b/man/trktg_logout.Rd index d55947d..1f2e7f2 100644 --- a/man/trktg_logout.Rd +++ b/man/trktg_logout.Rd @@ -15,7 +15,7 @@ Removes authentication info from memory and logs out of } \examples{ \dontrun{ -trktg_login("some_user", "some_users_pw") +trktg_login("WyoDemo", "WYODEMO2024") fixes <- fetch_trktg_positions()