Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions DESCRIPTION
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,7 @@ LazyData: true
Depends: R6,
httr,
rjson
Imports:
data.table
RoxygenNote: 6.0.1

6 changes: 6 additions & 0 deletions NAMESPACE
Original file line number Diff line number Diff line change
@@ -1 +1,7 @@
importFrom(data.table,rbindlist)
importFrom(data.table,set)
importFrom(data.table,setattr)
importFrom(data.table,setcolorder)
importFrom(data.table,setnames)
importFrom(R6, R6Class)
exportPattern("^[[:alpha:]]+")
121 changes: 20 additions & 101 deletions R/dataApi.r
Original file line number Diff line number Diff line change
Expand Up @@ -33,49 +33,19 @@ dataApi <- R6Class("dataApi",
return(as.vector(webIds))
},
convertToDataFrame = function(items) {
itemsLength <- length(items)
value <- array(1:itemsLength)
timestamp <- array(1:itemsLength)
unitsAbbreviation <- array(1:itemsLength)
good <- array(1:itemsLength)
questionable <- array(1:itemsLength)
substituted <- array(1:itemsLength)
for (i in 1:itemsLength) {
if (is.null(items[[i]]$Value) == FALSE)
{
if (is.numeric(items[[i]]$Value) == TRUE)
{
value[i] <- items[[i]]$Value
}
else
{
value[i] <- items[[i]]$Value$Name
}
}
if (is.null(items[[i]]$Timestamp) == FALSE)
{
timestamp[i] <- items[[i]]$Timestamp
}
if (is.null(items[[i]]$UnitsAbbreviation) == FALSE)
{
unitsAbbreviation[i] <- items[[i]]$UnitsAbbreviation
}
if (is.null(items[[i]]$Good) == FALSE)
{
good[i] <- items[[i]]$Good
}
if (is.null(items[[i]]$Questionable) == FALSE)
{
questionable[i] <- items[[i]]$Questionable
}
if (is.null(items[[i]]$Substituted) == FALSE)
{
substituted[i] <- items[[i]]$Substituted
# check if value is tagged
for (i in seq_along(items)) {
if (!is.numeric(items[[i]]$Value) && is.list(items[[i]]$Value)) {
items[[i]]$Value <- items[[i]]$Value$Name
}
}


resDataFrame <- data.frame(value, timestamp, unitsAbbreviation, good, questionable, substituted)
resDataFrame <- data.table::rbindlist(items, fill = TRUE)[, lapply(.SD, unlist, use.names = FALSE)]
data.table::setnames(resDataFrame,
c("timestamp", "value", "unitsAbbreviation", "good", "questionable", "substituted", "annotated")
)
data.table::set(resDataFrame, NULL, "annotated", NULL)
data.table::setcolorder(resDataFrame, "value")
return(resDataFrame)
},
calculateItemsIndex = function(webId, items, originalIndex){
Expand All @@ -90,72 +60,21 @@ dataApi <- R6Class("dataApi",
return(originalIndex)
},
convertMultipleStreamsToDataFrame = function(items, gatherInOneDataFrame, webIds, paths = NULL) {
streamsLength <- length(items)
resDataFrame <- lapply(items, function (item) self$convertToDataFrame(item$Items))
data.table::setattr(resDataFrame, "names", paths)

if (gatherInOneDataFrame == TRUE) {
itemsLength <- length(items[[1]]$Items)
order <- 1:itemsLength
resDataFrame <- data.frame(order)
for (i in 1:streamsLength) {
k = self$calculateItemsIndex (webIds[i], items, i);
value <- array(1:itemsLength)
timestamp <- array(1:itemsLength)
unitsAbbreviation <- array(1:itemsLength)
good <- array(1:itemsLength)
questionable <- array(1:itemsLength)
substituted <- array(1:itemsLength)
for (j in 1:itemsLength) {
if (is.null(items[[k]]$Items[[j]]$Value) == FALSE)
{
if (is.numeric(items[[k]]$Items[[j]]$Value) == TRUE)
{
value[j] <- items[[k]]$Items[[j]]$Value
}
else
{
value[j] <- items[[k]]$Items[[j]]$Value$Name
}
}
if (is.null(items[[k]]$Items[[j]]$Timestamp) == FALSE)
{
timestamp[j] <- items[[k]]$Items[[j]]$Timestamp
}
if (is.null(items[[k]]$Items[[j]]$UnitsAbbreviation) == FALSE)
{
unitsAbbreviation[j] <- items[[k]]$Items[[j]]$UnitsAbbreviation
}
if (is.null(items[[k]]$Items[[k]]$Good) == FALSE)
{
good[j] <- items[[k]]$Items[[k]]$Good
}
if (is.null(items[[k]]$Items[[j]]$Questionable) == FALSE)
{
questionable[j] <- items[[k]]$Items[[j]]$Questionable
}
if (is.null(items[[k]]$Items[[j]]$Substituted) == FALSE)
{
substituted[j] <- items[[k]]$Items[[j]]$Substituted
}
}
if (i == 1) {
resDataFrame <- data.frame(timestamp)
}
timestamp <- resDataFrame[[1]][, .SD, .SDcols = "timestamp"]

resDataFrame[[paste0("value", i)]] = as.vector(value)
resDataFrame[[paste0("unitsAbbreviation", i)]] = as.vector(unitsAbbreviation)
resDataFrame[[paste0("good", i)]] = as.vector(good)
resDataFrame[[paste0("questionable", i)]] = as.vector(questionable)
resDataFrame[[paste0("substituted", i)]] = as.vector(substituted)
}
}
else {
resDataFrame <- list()
for (i in 1:streamsLength) {
key <- paste0(paths[i])
df <- self$convertToDataFrame(items[[i]]$Items)
resDataFrame[[key]] = df
for (i in seq_along(resDataFrame)) {
data.table::setnames(resDataFrame[[i]], NULL, "timestamp", NULL)
data.table::setnames(resDataFrame[[i]], paste0(names(resDataFrame[[1]]), "i"))
}

resDataFrame <- Reduce(cbind, c(list(timestamp), resDataFrame))

}

return(resDataFrame)
},

Expand Down
11 changes: 8 additions & 3 deletions R/piwebapi.r
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
library(R6)
library(httr)
library(rjson)
.onLoad <- function(libname, pkgname) {
require("httr")
require("rjson")
}

.onAttach <- function(libname, pkgname) {
require("httr")
require("rjson")
}

piwebapi <- R6Class("piwebapi",
private = list(),
Expand Down
38 changes: 24 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,26 +3,32 @@ PI Web API client R package (2018)

## Introduction

This is an R package that integrates the PI System with R through PI Web API. With this package, you can retrieve PI data without having to generate the URL for each request. This version was developed on top of the PI Web API 2018 swagger specification.
This is an R package that integrates the PI System with R through PI Web API.
With this package, you can retrieve PI data without having to generate the URL
for each request. This version was developed on top of the PI Web API 2018
swagger specification.

## Requirements.

- PI Web API 2018 installed within your domain using Kerberos or Basic Authentication. If you are using an older version, some methods might not work.
- PI Web API 2018 installed within your domain using Kerberos or Basic
Authentication. If you are using an older version, some methods might not
work.
- R 3.4.3+

## Installation

This R package is not available on CRAN. You should download it directly from this GitHub repository by using the devtools R package. If you don't have it installed, please use the command below:
This R package is not available on CRAN. You should download it directly from
this GitHub repository by using the `remotes` R package. If you don't have it
installed, please use the command below:

```r
install.packages("devtools")
install.packages("remotes")
```

Then, load the library and install the PI Web API R package with the install_github method:
Then, load the library and install the PI Web API R package with the `install_github` method:

```r
library(devtools)
install_github("osimloeff/PI-Web-API-Client-R")
remotes::install_github("hongyuanjia/piwebapi")
```

If the installation is successful, the command below will load the package:
Expand All @@ -42,17 +48,20 @@ remove.packages("piwebapi")
All the methods and classes from this R package are described on its documentation, which can be opened by typing on the R console:

```r
help(package="piwebapi")
help(package="piwebapi")
```

## Notes

- Is is highly recommended to turn debug mode on in case you are using PI Web API 2017 R2+ in order to receive more detailed exception errors. This can be achieved by creating or editing the DebugMode attribute's value to TRUE from the System Configuration element.
- Is is highly recommended to turn debug mode on in case you are using PI Web
API 2017 R2+ in order to receive more detailed exception errors. This can be
achieved by creating or editing the DebugMode attribute's value to TRUE from
the System Configuration element.
- The X-Requested-With header is added to work with CSRF defences.

## Examples

Please refer to the following examples to understand how to use this library:
Please refer to the following examples to understand how to use this library:


### Create an intance of the piwebapi top level object.
Expand All @@ -77,9 +86,9 @@ debug <- TRUE
piWebApiService <- piwebapi$new("https://webserver/piwebapi", useKerberos, username, password, validateSSL, debug)
```

If you want to use basic authentication instead of Kerberos, set useKerberos to FALSE.
If you are having issues with your SSL certificate and you want to ignore this error, set validateSSL to FALSE.
If you want to receive a log about each HTTP request, set debug to TRUE.
* If you want to use basic authentication instead of Kerberos, set useKerberos to FALSE.
* If you are having issues with your SSL certificate and you want to ignore this error, set validateSSL to FALSE.
* If you want to receive a log about each HTTP request, set debug to TRUE.

### Retrieve data from the main PI Web API endpoint

Expand Down Expand Up @@ -247,6 +256,7 @@ response17 <- piWebApiService$streamSet$retrieveStreamSetUpdates(markers);


## Licensing

Copyright 2018 OSIsoft, LLC.

Licensed under the Apache License, Version 2.0 (the "License");
Expand All @@ -260,5 +270,5 @@ Copyright 2018 OSIsoft, LLC.
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

Please see the file named [LICENSE.md](LICENSE.md).