complete documentation
parent
a2d71ac3e8
commit
0f80075bf5
@ -0,0 +1,13 @@
|
|||||||
|
# Generated by roxygen2: do not edit by hand
|
||||||
|
|
||||||
|
S3method(osem_measurements,bbox)
|
||||||
|
S3method(osem_measurements,default)
|
||||||
|
S3method(osem_measurements,sensebox)
|
||||||
|
S3method(osem_phenomena,sensebox)
|
||||||
|
export(osem_box)
|
||||||
|
export(osem_boxes)
|
||||||
|
export(osem_counts)
|
||||||
|
export(osem_measurements)
|
||||||
|
export(osem_phenomena)
|
||||||
|
importFrom(graphics,plot)
|
||||||
|
importFrom(magrittr,"%>%")
|
@ -0,0 +1,125 @@
|
|||||||
|
# ==============================================================================
|
||||||
|
#
|
||||||
|
#' Get a set of senseBoxes from the openSenseMap
|
||||||
|
#'
|
||||||
|
#' Boxes can be selected by a set of filters.
|
||||||
|
#' Note that some filters do not work together:
|
||||||
|
#' \enumerate{
|
||||||
|
#' \item \code{phenomenon} can only be applied together with \code{date} or
|
||||||
|
#' \code{from / to}
|
||||||
|
#' \item \code{date} and \code{from / to} cannot be specified together
|
||||||
|
#' }
|
||||||
|
#'
|
||||||
|
#' @param exposure Only return boxes with the given exposure ('indoor', 'outdoor', 'mobile')
|
||||||
|
#' @param model Only return boxes with the given model
|
||||||
|
#' @param grouptag Only return boxes with the given grouptag
|
||||||
|
#' @param date Only return boxes that were measuring within ±4 hours of the given time
|
||||||
|
#' @param from Only return boxes that were measuring later than this time
|
||||||
|
#' @param to Only return boxes that were measuring earlier than this time
|
||||||
|
#' @param phenomenon Only return boxes that measured the given phenomenon in the
|
||||||
|
#' time interval as specified through \code{date} or \code{from / to}
|
||||||
|
#' @param endpoint The URL of the openSenseMap API instance
|
||||||
|
#' @return A \code{sensebox data.frame} containing a box in each row
|
||||||
|
#'
|
||||||
|
#' @seealso \href{https://docs.opensensemap.org/#api-Measurements-findAllBoxes}{openSenseMap API documentation (web)}
|
||||||
|
#' @seealso \code{\link{osem_phenomena}}
|
||||||
|
#' @export
|
||||||
|
#' @examples
|
||||||
|
#' # TODO
|
||||||
|
osem_boxes = function (exposure = NA, model = NA, grouptag = NA,
|
||||||
|
date = NA, from = NA, to = NA, phenomenon = NA,
|
||||||
|
endpoint = 'https://api.opensensemap.org') {
|
||||||
|
|
||||||
|
# error, if phenomenon, but no time given
|
||||||
|
if (!is.na(phenomenon) && is.na(date) && is.na(to) && is.na(from))
|
||||||
|
stop('Parameter "phenomenon" can only be used together with "date" or "from"/"to"')
|
||||||
|
|
||||||
|
# error, if date and from/to given
|
||||||
|
if (!is.na(date) && (!is.na(to) || !is.na(from)))
|
||||||
|
stop('Parameter "date" cannot be used together with "from"/"to"')
|
||||||
|
|
||||||
|
# error, if only one of from/to given
|
||||||
|
if (
|
||||||
|
(!is.na(to) && is.na(from)) ||
|
||||||
|
(is.na(to) && !is.na(from))
|
||||||
|
) {
|
||||||
|
stop('Parameter "from"/"to" must be used together')
|
||||||
|
}
|
||||||
|
|
||||||
|
query = list(endpoint = endpoint)
|
||||||
|
if (!is.na(exposure)) query$exposure = exposure
|
||||||
|
if (!is.na(model)) query$model = model
|
||||||
|
if (!is.na(grouptag)) query$grouptag = grouptag
|
||||||
|
if (!is.na(phenomenon)) query$phenomenon = phenomenon
|
||||||
|
|
||||||
|
if (!is.na(to) && !is.na(from)) {
|
||||||
|
# error, if from is after to
|
||||||
|
# convert dates to commaseparated UTC ISOdates
|
||||||
|
query$date = parse_dateparams(from, to) %>% paste(collapse = ',')
|
||||||
|
|
||||||
|
} else if (!is.na(date)) {
|
||||||
|
query$date = utc_date(date) %>% date_as_isostring()
|
||||||
|
}
|
||||||
|
|
||||||
|
do.call(get_boxes_, query)
|
||||||
|
}
|
||||||
|
|
||||||
|
# ==============================================================================
|
||||||
|
#
|
||||||
|
#' Get a single senseBox by its ID
|
||||||
|
#'
|
||||||
|
#' @param boxId A string containing a senseBox ID
|
||||||
|
#' @param endpoint The URL of the openSenseMap API instance
|
||||||
|
#' @return A \code{sensebox data.frame} containing a box in each row
|
||||||
|
#'
|
||||||
|
#' @seealso \href{https://docs.opensensemap.org/#api-Measurements-findAllBoxes}{openSenseMap API documentation (web)}
|
||||||
|
#' @seealso \code{\link{osem_phenomena}}
|
||||||
|
#' @export
|
||||||
|
#' @examples
|
||||||
|
#' # TODO
|
||||||
|
osem_box = function (boxId, endpoint = 'https://api.opensensemap.org') {
|
||||||
|
get_box_(boxId, endpoint = endpoint)
|
||||||
|
}
|
||||||
|
|
||||||
|
# ==============================================================================
|
||||||
|
#
|
||||||
|
#' Construct a senseBox data.frame
|
||||||
|
#'
|
||||||
|
#' Parses the fields of a \code{/boxes} response from the openSenseMap API
|
||||||
|
#'
|
||||||
|
#' @param boxdata A named \code{list} containing the data for a box
|
||||||
|
#' @return A \code{data.frame} with an attached class \code{sensebox}.
|
||||||
|
#' @noRd
|
||||||
|
parse_senseboxdata = function (boxdata) {
|
||||||
|
# extract nested lists for later use & clean them from the list
|
||||||
|
# to allow a simple data.frame structure
|
||||||
|
sensors = boxdata$sensors
|
||||||
|
location = boxdata$loc
|
||||||
|
boxdata[c('loc', 'sensors', 'image', 'boxType')] <- NULL
|
||||||
|
thebox = as.data.frame(boxdata, stringsAsFactors = F)
|
||||||
|
|
||||||
|
# parse timestamps (updatedAt might be not defined)
|
||||||
|
thebox$createdAt = as.POSIXct(strptime(thebox$createdAt, format='%FT%T', tz = 'GMT'))
|
||||||
|
if (!is.null(thebox$updatedAt))
|
||||||
|
thebox$updatedAt = as.POSIXct(strptime(thebox$updatedAt, format='%FT%T', tz = 'GMT'))
|
||||||
|
|
||||||
|
# extract metadata from sensors
|
||||||
|
thebox$phenomena = list(unlist(lapply(sensors, function(s) { s$title })))
|
||||||
|
# FIXME: if one sensor has NA, max() returns bullshit
|
||||||
|
thebox$lastMeasurement = max(lapply(sensors, function(s) {
|
||||||
|
if (!is.null(s$lastMeasurement))
|
||||||
|
as.POSIXct(strptime(s$lastMeasurement$createdAt, format = '%FT%T', tz = 'GMT'))
|
||||||
|
else
|
||||||
|
NA
|
||||||
|
})[[1]])
|
||||||
|
|
||||||
|
# extract coordinates & transform to simple feature object
|
||||||
|
thebox$lon = location[[1]]$geometry$coordinates[[1]]
|
||||||
|
thebox$lat = location[[1]]$geometry$coordinates[[2]]
|
||||||
|
if (length(location[[1]]$geometry$coordinates) == 3)
|
||||||
|
thebox$height = location[[1]]$geometry$coordinates[[3]]
|
||||||
|
|
||||||
|
# attach a custom class for methods
|
||||||
|
class(thebox) = c('sensebox', class(thebox))
|
||||||
|
thebox
|
||||||
|
}
|
@ -1,43 +0,0 @@
|
|||||||
`%>%` = magrittr::`%>%`
|
|
||||||
|
|
||||||
osem_boxes = function (exposure = NA, model = NA, grouptag = NA,
|
|
||||||
date = NA, from = NA, to = NA, phenomenon = NA,
|
|
||||||
endpoint = 'https://api.opensensemap.org') {
|
|
||||||
|
|
||||||
# error, if phenomenon, but no time given
|
|
||||||
if (!is.na(phenomenon) && is.na(date) && is.na(to) && is.na(from))
|
|
||||||
stop('Parameter "phenomenon" can only be used together with "date" or "from"/"to"')
|
|
||||||
|
|
||||||
# error, if date and from/to given
|
|
||||||
if (!is.na(date) && (!is.na(to) || !is.na(from)))
|
|
||||||
stop('Parameter "date" cannot be used together with "from"/"to"')
|
|
||||||
|
|
||||||
# error, if only one of from/to given
|
|
||||||
if (
|
|
||||||
(!is.na(to) && is.na(from)) ||
|
|
||||||
(is.na(to) && !is.na(from))
|
|
||||||
) {
|
|
||||||
stop('Parameter "from"/"to" must be used together')
|
|
||||||
}
|
|
||||||
|
|
||||||
query = list(endpoint = endpoint)
|
|
||||||
if (!is.na(exposure)) query$exposure = exposure
|
|
||||||
if (!is.na(model)) query$model = model
|
|
||||||
if (!is.na(grouptag)) query$grouptag = grouptag
|
|
||||||
if (!is.na(phenomenon)) query$phenomenon = phenomenon
|
|
||||||
|
|
||||||
if (!is.na(to) && !is.na(from)) {
|
|
||||||
# error, if from is after to
|
|
||||||
# convert dates to commaseparated UTC ISOdates
|
|
||||||
query$date = parse_dateparams(from, to) %>% paste(collapse = ',')
|
|
||||||
|
|
||||||
} else if (!is.na(date)) {
|
|
||||||
query$date = utc_date(date) %>% date_as_isostring()
|
|
||||||
}
|
|
||||||
|
|
||||||
do.call(get_boxes_, query)
|
|
||||||
}
|
|
||||||
|
|
||||||
osem_box = function (boxId, endpoint = 'https://api.opensensemap.org') {
|
|
||||||
get_box_(boxId, endpoint = endpoint)
|
|
||||||
}
|
|
@ -1,40 +0,0 @@
|
|||||||
parse_senseboxdata = function (boxdata) {
|
|
||||||
# extract nested lists for later use & clean them from the list
|
|
||||||
# to allow a simple data.frame structure
|
|
||||||
sensors = boxdata$sensors
|
|
||||||
location = boxdata$loc
|
|
||||||
boxdata[c('loc', 'sensors', 'image', 'boxType')] <- NULL
|
|
||||||
thebox = as.data.frame(boxdata, stringsAsFactors = F)
|
|
||||||
|
|
||||||
# parse timestamps (updatedAt might be not defined)
|
|
||||||
thebox$createdAt = as.POSIXct(strptime(thebox$createdAt, format='%FT%T', tz = 'GMT'))
|
|
||||||
if (!is.null(thebox$updatedAt))
|
|
||||||
thebox$updatedAt = as.POSIXct(strptime(thebox$updatedAt, format='%FT%T', tz = 'GMT'))
|
|
||||||
|
|
||||||
# extract metadata from sensors
|
|
||||||
thebox$phenomena = list(unlist(lapply(sensors, function(s) { s$title })))
|
|
||||||
# FIXME: if one sensor has NA, max() returns bullshit
|
|
||||||
thebox$lastMeasurement = max(lapply(sensors, function(s) {
|
|
||||||
if (!is.null(s$lastMeasurement))
|
|
||||||
as.POSIXct(strptime(s$lastMeasurement$createdAt, format = '%FT%T', tz = 'GMT'))
|
|
||||||
else
|
|
||||||
NA
|
|
||||||
})[[1]])
|
|
||||||
|
|
||||||
# extract coordinates & transform to simple feature object
|
|
||||||
thebox$lon = location[[1]]$geometry$coordinates[[1]]
|
|
||||||
thebox$lat = location[[1]]$geometry$coordinates[[2]]
|
|
||||||
if (length(location[[1]]$geometry$coordinates) == 3)
|
|
||||||
thebox$height = location[[1]]$geometry$coordinates[[3]]
|
|
||||||
|
|
||||||
# attach a custom class for methods
|
|
||||||
class(thebox) = c('sensebox', class(thebox))
|
|
||||||
thebox
|
|
||||||
}
|
|
||||||
|
|
||||||
get_phenomena = function (x, ...) UseMethod('get_phenomena')
|
|
||||||
get_phenomena.default = function (x, ...) stop('not implemented')
|
|
||||||
get_phenomena.sensebox = function (x, ...) {
|
|
||||||
# FIXME: only returns first box for get_boxes!
|
|
||||||
x$phenomena[[1]]
|
|
||||||
}
|
|
@ -0,0 +1,16 @@
|
|||||||
|
# ==============================================================================
|
||||||
|
#
|
||||||
|
#' Get count statistics of the openSenseMap Instance
|
||||||
|
#'
|
||||||
|
#' Provides information on number of senseBoxes, measurements, and measurements per minute.
|
||||||
|
#'
|
||||||
|
#' @details Note that the API caches these values for 5 minutes.
|
||||||
|
#'
|
||||||
|
#' @param endpoint The URL of the openSenseMap API
|
||||||
|
#' @return A named \code{list} containing the counts
|
||||||
|
#'
|
||||||
|
#' @export
|
||||||
|
#' @seealso \href{https://docs.opensensemap.org/#api-Misc-getStatistics}{openSenseMap API documentation (web)}
|
||||||
|
osem_counts = function (endpoint = 'https://api.opensensemap.org') {
|
||||||
|
get_stats_(endpoint)
|
||||||
|
}
|
@ -1,3 +0,0 @@
|
|||||||
osem_counts = function (endpoint = 'https://api.opensensemap.org') {
|
|
||||||
get_stats_(endpoint)
|
|
||||||
}
|
|
@ -0,0 +1,29 @@
|
|||||||
|
#' opensensemap: Work with sensor data from opensensemap.org
|
||||||
|
#'
|
||||||
|
#' The opensensemap package provides three categories functions:
|
||||||
|
#' \enumerate{
|
||||||
|
#' \item retrieval of senseBoxes
|
||||||
|
#' \item retrieval of measurements
|
||||||
|
#' \item general stats about the opensensemap database
|
||||||
|
#' }
|
||||||
|
#'
|
||||||
|
#' @section Retrieving senseBox metadata:
|
||||||
|
#' TODO
|
||||||
|
#'
|
||||||
|
#' @section Retrieving measurements:
|
||||||
|
#' TODO
|
||||||
|
#'
|
||||||
|
#' @section Retrieving statistics:
|
||||||
|
#' TODO
|
||||||
|
#'
|
||||||
|
#' @section Working with spatial data from openSenseMap:
|
||||||
|
#' TODO
|
||||||
|
#'
|
||||||
|
#' @docType package
|
||||||
|
#' @name opensensemap
|
||||||
|
'_PACKAGE'
|
||||||
|
|
||||||
|
#' @importFrom graphics plot
|
||||||
|
|
||||||
|
#' @importFrom magrittr %>%
|
||||||
|
`%>%` = magrittr::`%>%`
|
@ -0,0 +1,35 @@
|
|||||||
|
# ==============================================================================
|
||||||
|
#
|
||||||
|
#' Get the counts of sensors for each observed phenomenon.
|
||||||
|
#'
|
||||||
|
#' @param boxes A \code{sensebox data.frame} of boxes
|
||||||
|
#' @return An \code{data.frame} containing the count of sensors observing a
|
||||||
|
#' phenomenon per column.
|
||||||
|
#' @export
|
||||||
|
osem_phenomena = function (boxes) UseMethod('osem_phenomena')
|
||||||
|
|
||||||
|
# ==============================================================================
|
||||||
|
#
|
||||||
|
#' @describeIn osem_phenomena Get counts of sensors observing each phenomenon
|
||||||
|
#' from a set of senseBoxes.
|
||||||
|
#' @export
|
||||||
|
#' @seealso \code{\link{osem_boxes}}
|
||||||
|
#' @examples
|
||||||
|
#' # get the phenomena for a single senseBox
|
||||||
|
#' osem_phenomena(osem_box('593bcd656ccf3b0011791f5a'))
|
||||||
|
#'
|
||||||
|
#' # get the phenomena for a group of senseBoxes
|
||||||
|
#' osem_phenomena(
|
||||||
|
#' osem_boxes(grouptag = 'ifgi', exposure = 'outdoor', date = Sys.time())
|
||||||
|
#' )
|
||||||
|
#'
|
||||||
|
#' # get phenomena with at least 10 sensors on opensensemap
|
||||||
|
#' phenoms = osem_phenomena(osem_boxes())
|
||||||
|
#' colnames(dplyr::select_if(phenoms, function(v) v > 9))
|
||||||
|
#'
|
||||||
|
osem_phenomena.sensebox = function (boxes) {
|
||||||
|
Reduce(`c`, boxes$phenomena) %>% # get all the row contents in a single vector
|
||||||
|
table() %>% # get count for each phenomenon
|
||||||
|
t() %>% # transform the table to a df
|
||||||
|
as.data.frame.matrix()
|
||||||
|
}
|
Loading…
Reference in New Issue