Create stations, receptors and link them
station_and_receptors.Rmd
Initial Setup and Api Credentials
This setup is consistent across all vignettes and has been copied
over for demonstration purposes. If you run the entire vignette at once,
a new R session will start each time, so make sure to install the
temploapiclient
package beforehand. You can do this by
using install.packages
, renv::install
for
virtual environments, or pkgdown::build_site
if you want to
generate local documentation. The last command will also temporarily
install the R package being showcased to make it available in the
vignettes.
Alternatively, if you’d like to run each section individually, load
temploapiclient
with devtools::load_all
and
set the working directory to temploapiclient/vignettes
using setwd()
.
Last but not least, if you have already installed this package none of the above is necessary.
project_folder <- dirname(getwd())
path_to_env <- file.path(project_folder, ".env")
readRenviron(path_to_env)
api_base_url <- Sys.getenv("API_BASE_URL")
api_headers <- list("Accept" = "application/json", "Content-type" = "application/json")
api_auth_token <- Sys.getenv("AUTH_TOKEN")
if (!length(api_auth_token)) {
api_auth_token <- NULL
}
Then let’s instantiate the client to query the TEMPLO api
templo_client <- temploapiclient::TemploApiClient$new(api_base_url, api_headers, api_auth_token)
library("magrittr") # Make '%>%' available throughout the vignette
Creating stations, receptors and linking both
Stations and receptors have a 1:N relationship where one station could be associated to multiple receptors. In order to build such relationship the following steps need to be taken in chronological order:
- Add a station if it is not already created.
- Add as many receptors, one by one, as required.
- Link the station with all its potential associated receptors.
- Repeat 1 to 4 for as many stations as required.
Creating stations
Create a new receptor and give it the name “Cies 2”. If something
unexpected happens, an error will be outputted. The code is commented
out because a record can only be inserted once. Tough not shown here,
when successful, the api call return the record just inserted with a new
generated id
. This chunk has been set not to run anymore as
it can only run once. Set eval=TRUE
if you want to run it
again, however remember to provide a different unique name.
ret <- templo_client$add_single_record_and_fetch_id(end_point = "stations/", data = list(
name = "Cies 2",
description = "Western area of cies"
))
Ensure that such receptor was sent and stored in the database by retrieving it from the API.
api_data <- templo_client$get_dataframe_end_point(end_point = "stations/")
#> INFO [2024-11-14 17:08:14] Fetching data from api... This may take a few seconds
#> INFO [2024-11-14 17:08:15] --->Finished
api_data %>%
dplyr::filter(name == "Cies 2") %>%
assertr::verify(nrow(.) == 1) # It will halt the execution and print an error if such record does not exist
#> name id description
#> 1 Cies 2 198 Western area of cies
Creating receptors
Receptors, besides a name, requires a unique string that identify
them and that is stored in serial_id
. As for receptors, a
new generated id
is returned when successful. Otherwise, an
error is printed.eval=FALSE
prevents the chunk from
running.
serial_id <- stringi::stri_rand_strings(1, 10)
ret <- templo_client$add_single_record_and_fetch_id(end_point = "receptors/", data = list(
name = "Buoy C21",
serial_id = serial_id,
description = "Receptor set up on a buoy"
))
Ensure that such station was sent and stored in the database by retrieving it from the API.
api_data <- templo_client$get_dataframe_end_point(end_point = "receptors/")
#> INFO [2024-11-14 17:08:15] Fetching data from api... This may take a few seconds
#> INFO [2024-11-14 17:08:15] --->Finished
api_data %>%
dplyr::filter(name == "Buoy C21") %>%
assertr::verify(nrow(.) == 1)
#> description name id serial_id
#> 1 Receptor set up on a buoy Buoy C21 9 sTMPrWTY6C
Associating receptors to stations
Once we have created receptors and stations separately, we may
associate them by using a table that relate the two, represented by the
endpoint stations_receptors
. Notice that you’ve got to do
that by picking the ids returned from earlier
calls.eval=FALSE
prevents the chunk from running.
data <- list(
stations_id = 198, # station that we just created by the name of "Cies 2"
receptors_id = 9, # receptor stored as "Buoy C21"
is_active = TRUE, # it indicates the receptor is active
latitude = 42.2134,
longitude = -8.8987,
deployment_date = "2024-11-07 08:25:00" # Notice that dates are in yms_hms format
)
ret <- templo_client$add_single_record_and_fetch_id(end_point = "stations_receptors/", data = data)
Again, and for demonstrative purposes, we ensure that the association was successfully implemented by querying the API.
api_data <- templo_client$get_dataframe_end_point(end_point = "stations_receptors/")
#> INFO [2024-11-14 17:08:15] Fetching data from api... This may take a few seconds
#> INFO [2024-11-14 17:08:16] --->Finished
api_data %>%
dplyr::filter(stations_id == 198 & receptors_id == 9) %>%
assertr::verify(nrow(.) == 1)
#> receptors_id id stations_id latitude notes is_active deployment_date
#> 1 9 7 198 42.2134 <NA> TRUE 2024-11-07T08:25:00
#> longitude
#> 1 -8.8987
Errors while sending
A record can only exist once in a relational database so if trying twice an error will be prompted.
ret <- templo_client$add_single_record_and_fetch_id(end_point = "stations/", data = list(
name = "Cies 2", # name is an unique field and already exists in the database
description = "Western area of cies"
))
#> INFO [2024-11-14 17:08:16] Sending data to stations/ ...
#> ERROR [2024-11-14 17:08:16] Detected a 'duplicate' keyword. You may have inserted a record that already exist in the database. See error below.
#> {
#> "error": ["IntegrityError"],
#> "details": ["(MySQLdb.IntegrityError) (1062, \"Duplicate entry 'Cies 2' for key 'stations.name_UNIQUE'\")"]
#> }ERROR [2024-11-14 17:08:16] Data could not be send
… Or you could miss a required field such name
and get a
“field required” error
ret <- templo_client$add_single_record_and_fetch_id(end_point = "stations/", data = list(
description = "Western area of cies"
))
#> INFO [2024-11-14 17:08:16] Sending data to stations/ ...
#> ERROR [2024-11-14 17:08:16] Detected a 'field required' keyword. You may be missing an essential field in your query. Look 'loc' section for clues
#> {
#> "detail": [
#> {
#> "type": ["missing"],
#> "loc": [
#> ["body"],
#> ["name"]
#> ],
#> "msg": ["Field required"],
#> "input": {
#> "description": ["Western area of cies"]
#> }
#> }
#> ]
#> }ERROR [2024-11-14 17:08:16] Data could not be send
Deleting a record
Let’s create a new station and then delete it right away.
new_record <- templo_client$add_single_record_and_fetch_id(end_point = "stations/", data = list(
name = "Cies 3",
description = "Eastern area of cies"
))
#> INFO [2024-11-14 17:08:16] Sending data to stations/ ...
#> INFO [2024-11-14 17:08:16] --->Finished
new_record
#> $name
#> [1] "Cies 3"
#>
#> $id
#> [1] 398
#>
#> $description
#> [1] "Eastern area of cies"
Let’s ensure that the record was inserted in the database.
api_data <- templo_client$get_dataframe_end_point(end_point = "stations/")
#> INFO [2024-11-14 17:08:16] Fetching data from api... This may take a few seconds
#> INFO [2024-11-14 17:08:16] --->Finished
api_data %>%
dplyr::filter(name == "Cies 3") %>%
assertr::verify(nrow(.) == 1)
#> description id name
#> 1 Eastern area of cies 398 Cies 3
Now let’s deleted…
ret <- templo_client$delete_single_record(end_point = "stations/", data = list(
id = new_record$id
))
#> INFO [2024-11-14 17:08:16] Deleting data from stations/ ...
#> INFO [2024-11-14 17:08:17] --->Finished
ret
#> [1] TRUE
… And once again, ensure that such record no longer exists
api_data <- templo_client$get_dataframe_end_point(end_point = "stations/")
#> INFO [2024-11-14 17:08:17] Fetching data from api... This may take a few seconds
#> INFO [2024-11-14 17:08:17] --->Finished
api_data %>%
dplyr::filter(name == "Cies 3") %>%
assertr::verify(nrow(.) == 0)
#> [1] name id description
#> <0 rows> (or 0-length row.names)