#' Get measurement data from a senseBox
#'
#' If the arguments `fromDate` and `toDate` are NOT given, the measurements from the last 48 h from
#' now are downloaded. The maximum numbers of downloaded measurements are 10,000.
#' The maximum time frame is one month.
#' It is possible to download the data directly as a csv file, when argument `CSV` is `TRUE`.
#'
#' @param senseBoxId [character]or [vector] of [character] (**required**): senseBoxId or a [vector] of [character] of senseBoxIds
#' @param sensorId [character] or [list] of [character] (**optional**): sensorId or a [list] of senseBoxIds. When no sensorIds are
#' submitted, all sensorIds from this sensebox are requested.
#' @param fromDate [character] (**optional**): Just show data with from date in format YYYY-mm-dd HH:MM:SS
#' @param toDate [character] (**optional**): Just show data with up to date in format YYYY-mm-dd HH:MM:SS
#' @param parallel [logical] (**optional**): Should the calculations be executed on multiple cores? At least 4 cores
#' are necessary to use this feature.
#' @param CSV [logical] (**optional**): Download data as csv file? NOT SUPPORTED UNTIL NOW!
#' @param POSIXct [logical] (**optional**): Should the timestamp be translated into POSIXct?
#' @return A [list] with every entry is a sensBoxId. Every list entry inherits a [data.frame] with values and dates.
#'
#' @section Function version: 0.0.1
#' @author Johannes Friedrich
#'
#' @examples
#'
#' ##=====================================
#' ## Example: get data from sensorId
#' ##=====================================
#'
#' get_senseBox_data(
#' senseBoxId = "5957b67494f0520011304cc1",
#' sensorId = "5957b67494f0520011304cc4",
#' fromDate = "2017-11-25-12:00:00",
#' toDate = "2017-11-25 12:30:00")
#'
#'\dontrun{
#' get_senseBox_data(
#' senseBoxId = c("5957b67494f0520011304cc1","5957b67494f0520011304cc1") ,
#' sensorId = "all",
#' fromDate = "2017-11-25-12:00:00",
#' toDate = "2017-11-26-12:00:00")
#'
#' get_senseBox_data(
#' senseBoxId = "5957b67494f0520011304cc1",
#' sensorId = "5957b67494f0520011304cc4",
#' fromDate = "2017-11-25-12:00:00",
#' toDate = "2017-11-26-12:00:00")
#'}
#'
#' @md
#' @export
get_senseBox_data <- function(
senseBoxId,
sensorId = rep("all", times = length(unlist(senseBoxId))),
fromDate = NULL,
toDate = NULL,
parallel = FALSE,
CSV = FALSE,
POSIXct = TRUE){
##=======================================##
## ERROR HANDLING
##=======================================##
if (missing(senseBoxId))
stop("[get_senseBox_data()] Argument 'senseBoxId' is missing", call. = FALSE)
if (class(unlist(senseBoxId)) != "character")
stop("[get_senseBox_data()] Argument 'senseBoxId' has to be a character", call. = FALSE)
if (class(unlist(sensorId)) != "character")
stop("[get_senseBox_data()] Argument 'sensorId' has to be a character", call. = FALSE)
if (class(parallel) != "logical")
stop("[get_senseBox_data()] Argument 'parallel' has to be logical", call. = FALSE)
if (class(CSV) != "logical")
stop("[get_senseBox_data()] Argument 'CSV' has to be logical", call. = FALSE)
if (class(POSIXct) != "logical")
stop("[get_senseBox_data()] Argument 'POSIXct' has to be logical", call. = FALSE)
##==== END ERROR HANDLING
if (length(sensorId) < length(senseBoxId) && sensorId == "all") {
sensorId <- rep(sensorId[1], times = length(senseBoxId))
}
Ids_loop <- lapply(1:length(senseBoxId), function(x){
sensor_info <- get_senseBox_sensor_info(senseBoxId[x], tidy = TRUE)
## return NULL, if return value from 'get_senseBox_sensor_info()' is NULL
if (is.null(sensor_info)){
return(NULL)
}
for (i in 1:length(sensorId[[x]])) {
if (all(sensorId[[x]] != "all")) {
##check if sensorId is really part of the senseBox
if (!all(sensorId[[x]] %in% sensor_info$sensorIds)) {
stop("[get_senseBox_data()] SensorId is not part of the senseBox.
Check argument 'sensorId' with function 'get_senseBox_sensor_info()'.", call. = TRUE)
} else {
sensor_index <- which(sensor_info$sensorIds %in% sensorId[[x]])
sensorId_new <- sensor_info$sensorIds[sensor_index]
}
} else {## sensorId = "all"
sensor_index <- 1:length(sensor_info$sensorIds)
sensorId_new <- sensor_info$sensorIds
}
}
## check number of cores to use
if (parallel) {
if (parallel::detectCores() <= 2) {
warning("[get_senseBox_data()] For the multicore auto mode at least 4 cores are needed.
Use 1 core to calculate results.", call. = FALSE)
cores <- 1
} else {
cores <- parallel::detectCores() - 2
}
} else {
cores <- 1
}
cl <- parallel::makeCluster(cores)
on.exit(parallel::stopCluster(cl))
parsed <- parallel::parLapply(cl, 1:length(sensorId_new), function(y){
## check arguments `fromDate`, `toDate`
path_from_date <- ifelse(is.null(fromDate), "", paste0("&from-date=", format.POSIXct(as.POSIXct(fromDate), "%Y-%m-%dT%H:%M:%SZ")))
path_to_date <- ifelse(is.null(toDate), "", paste0("&to-date=", format.POSIXct(as.POSIXct(toDate), "%Y-%m-%dT%H:%M:%SZ")))
path_CSV <- ifelse(CSV, "&download=false", "&download=false")
url <- paste0("https://api.opensensemap.org/boxes/", senseBoxId[x], "/data/", sensorId_new[y], "?",
path_from_date, path_to_date, path_CSV)
resp <- httr::GET(url)
if (httr::http_type(resp) != "application/json") {
stop("[get_senseBox_data()] API did not return json\n", call. = FALSE)
}
if (!httr::http_error(resp$status_code)) {
parsed_single <- jsonlite::fromJSON(httr::content(resp, "text"))
if (length(parsed_single) != 0) {
parsed_single$value <- as.numeric(parsed_single$value)
if (POSIXct)
parsed_single$createdAt <- as.POSIXct(parsed_single$createdAt, tz = Sys.timezone(), format = "%Y-%m-%dT%H:%M:%OSZ")
} else {
warning(paste0("[get_senseBox_data()] Sensor data for senseBoxId ",senseBoxId[x], "sensorId ", sensorId_new[y])," not available!", call. = FALSE)
parsed_single <- "Sensor data not available"
}
##remove coloumn 'location'
parsed_single$location <- NULL
return(parsed_single)
} else {
warning(paste0("[get_senseBox_data()] HTTP-error for senseBoxId ",senseBoxId[x]), call. = FALSE)
return(NULL)
} ## end else
}) ## end parsed <- parallel::parLapply ...
names(parsed) <- paste0(sensor_info$phenomena[sensor_index], " [",sensor_info$unit[sensor_index], "]")
return(parsed)
}) ## end Ids_loop <- lapply
## name the list
names(Ids_loop) <- senseBoxId
## check if senseBoxId was not available
## https://stackoverflow.com/questions/33004238/r-removing-null-elements-from-a-list/33004339#33004339
Ids_loop[sapply(Ids_loop, is.null)] <- NULL
return(Ids_loop)
}
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.