Skip navigation
All Places > PI Developers Club > Blog > 2017 > October
2017

Introduction

 

Today we release our first version of the PI Web API client library for Angular 4 (the newest version of AngularJS) . The purpose of using this library is to make it easier the integration of an Angular web application with the PI System through PI Web API. This library is a client RESTful web service. All server methods from PI Web API 2017 are available on the library. As a result, you don't need to generate the URL in order to make an HTTP request. The library will generate for you automatically!

 

You can visit the GitHub repository of this library here.

 

You can visit the web page about this npm package here.

 

Although this library was tested with Angular 4, it should also be compatible with Angular 2.

 

The version for AngularJS was already released.

 

What is Angular?

 

According to the Angular official documentation:

 

"Angular is a platform that makes it easy to build applications with the web. Angular combines declarative templates, dependency injection, end to end tooling, and integrated best practices to solve development challenges. Angular empowers developers to build applications that live on the web, mobile, or the desktop."

 

Requirements

 

  • NodeJS (npm is going to be used to download the library)
  • Text Editor (Visual Studio Code is recommended)
  • Angular 4+

 

Installation

 

To install this library, run:

 

npm install angular-piwebapi --save

 

Consuming your library

 

Update your Angular AppModule by adding the PIWebAPIService as a provider:

 

import { PIWebAPIService } from 'angular-piwebapi';
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { HttpModule } from '@angular/http';
import { AppComponent } from './app.component';

@NgModule({
  declarations: [
   AppComponent
  ],
  imports: [
   BrowserModule,
   FormsModule,
   HttpModule
  ],
  providers: [PIWebAPIService],
  bootstrap: [AppComponent]
})
export class AppModule { }

 

 

Documentation

 

All classes and methods are described on the DOCUMENTATION.

 

Examples

Please check the sample_main.ts from this repository. Below there are also code snippets written in Angular 4 for you to get started using this library:

 

Set up the instance of the PI Web API top level object.

If you want to use basic authentication instead of Kerberos, set useKerberos to false and set the username and password as shown below:

 

Basic authentication

 

    this.piWebApiHttpService.configureInstance("https://devdata.osisoft.com/piwebapi/", false, "username", "password");

 

Kerberos authentication

 

    this.piWebApiHttpService.configureInstance("https://devdata.osisoft.com/piwebapi/", true);

 

If you want to test if it connects, just execute the code below:

 

    this.piWebApiHttpService.home.get().subscribe(res => {
        console.log(res);
    }, error => {
        console.log(error.json());
    });

 

Get the PI Data Archive WebId

 

    this.piWebApiHttpService.dataServer.getByPath('\\\\SERVERNAME').subscribe(res => {
        console.log(res); 
    }, error => {
        console.log(error.json());
    });

 

Create a new PI Point

 

    var pointName = "SINUSOID_TEST74" + Math.trunc(100000*Math.random());
    var newPoint = new PIPoint(null, null, pointName, null, "Test PI Point for Angular PI Web API Client", "classic", "float32", null, null, null, false);    
    this.piWebApiHttpService.dataServer.createPoint(res.WebId, newPoint).subscribe(res => {
console.log(res);
}, error => {
console.log(error.json());
});     

 

 

Get PI Point WebId

 

    this.piWebApiHttpService.point.getByPath("\\\\MARC-PI2016\\sinusoid").subscribe(res => {
        console.log(res);
    }, error => {
        console.log(error.json());
    });

 

Get recorded values in bulk using the StreamSet/GetRecordedAdHoc

 

    var point1webId = "P0QuorgJ0MskeiLb6TmEmH5gAQAAAATUFSQy1QSTIwMTZcU0lOVVNPSUQ";
    var point2webId = "P0QuorgJ0MskeiLb6TmEmH5gAgAAAATUFSQy1QSTIwMTZcU0lOVVNPSURV";
    var point3webId = "P0QuorgJ0MskeiLb6TmEmH5g9AQAAATUFSQy1QSTIwMTZcQ0RUMTU4";




    var webIds = []
    webIds.push(point1webId);
    webIds.push(point2webId);
    webIds.push(point3webId);


    this.piWebApiHttpService.streamSet.getRecordedAdHoc(webIds, null, "*", null, true, 1000, null, "*-3d", null).subscribe(res => {
        console.log(res);
    }, error => {
        console.log(error.json());
    }); 

 

Send values in bulk using the StreamSet/UpdateValuesAdHoc

 

    let streamValuesItems : PIItemsStreamValues = new PIItemsStreamValues()
    let streamValue1 : PIStreamValues = new PIStreamValues()
    let streamValue2 : PIStreamValues = new PIStreamValues()
    let streamValue3 : PIStreamValues = new PIStreamValues()


    let value1 : PITimedValue = new PITimedValue()
    let value2 : PITimedValue = new PITimedValue()
    let value3 : PITimedValue = new PITimedValue()
    let value4 : PITimedValue = new PITimedValue()
    let value5 : PITimedValue = new PITimedValue()
    let value6 : PITimedValue = new PITimedValue()


    value1.Value = 2
    value1.Timestamp = "*-1d"
    value2.Value = 3
    value2.Timestamp = "*-2d"
    value3.Value = 4
    value3.Timestamp = "*-1d"
    value4.Value = 5
    value4.Timestamp = "*-2d"
    value5.Value = 6
    value5.Timestamp = "*-1d"
    value6.Value = 7
    value6.Timestamp = "*-2d"


    streamValue1.WebId = point1webId
    streamValue2.WebId = point2webId
    streamValue3.WebId = point3webId


    var values1 = [];
    values1.push(value1)
    values1.push(value2)
    streamValue1.Items = values1


    var values2 = [];
    values2.push(value3)
    values2.push(value4)
    streamValue2.Items = values2


    var values3 = [];
    values3.push(value5)
    values3.push(value6)
    streamValue3.Items = values3


    var streamValues = []
    streamValues.push(streamValue1)
    streamValues.push(streamValue2)
    streamValues.push(streamValue3)
    this.piWebApiHttpService.streamSet.updateValuesAdHoc(streamValues, null, null).subscribe(res => {
        console.log(res);
    }, error => {
        console.log(error.json());
    });

 

Using PI Web API Batch

 

 var pirequest = {};
    pirequest["4"] = {
        "Method": "GET",
        "Resource": "https://marc-web-sql.marc.net/piwebapi/points?path=\\\\MARC-PI2016\\sinusoid",
        "Headers": {
            "Cache-Control": "no-cache"
        }
    };
    pirequest["5"] = {
        "Method": "GET",
        "Resource": "https://marc-web-sql.marc.net/piwebapi/points?path=\\\\MARC-PI2016\\cdt158",
        "Headers": {
            "Cache-Control": "no-cache"
        }
    };
    pirequest["6"] = {
        "Method": "GET",
        "Resource": "https://marc-web-sql.marc.net/piwebapi/streamsets/value?webid={0}&webid={1}",
        "Parameters": [
            "$.4.Content.WebId",
            "$.5.Content.WebId"
        ],
        "ParentIds": [
            "4",
            "5"
        ]
    };
    this.piWebApiHttpService.batch.execute(pirequest).subscribe(res => {
        console.log(res);
    }, error => {
        console.log(error.json());
    }); 

 

 

If you know the name of the action and controller, you probably need to make a call similar to:

 

PIWebAPIService.{controllerName}.{actionName}(inputs);

 

Please read the PI Web API programming reference to find out the names of the actions, controllers and inputs.

 

If you want to find out the order of the inputs, please refer to DOCUMENTATION and search for the method you want to use.

 

Developing a modern app with PI Web API client library for Angular

 

Do you remember my old blog post about Using PI Web API with Angular 2?

 

On that blog post, we have created a PIWebAPIService class in order to make HTTP requests against PI Web API.

 

This time let's rewrite the file app.component.ts in order to use the library methods instead. This is a good example about how this library should be used after downloading it with npm and updating the file app.module.ts.

 

import { Component } from '@angular/core';
import { PIWebAPIService, PIItemsStreamValues, PIPoint, PITimedValue, PIStreamValues } from 'angular-piwebapi';




export class ComboboxOption {
  value: boolean;
  name: string;
}


@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  requestMode = true;
  piServerName: string;
  piPointName: string;
  startTime: string;
  endTime: '*';
  interval: '1h';
  yesOrNoOptions: ComboboxOption[] = [{ 'value': true, 'name': 'Yes' }, { 'value': false, 'name': 'No' }];
  getSnap: ComboboxOption = this.yesOrNoOptions[0];
  getRec: ComboboxOption = this.yesOrNoOptions[0];
  getInt: ComboboxOption = this.yesOrNoOptions[0];
  piServerData: any;
  piServerExistsValue: boolean;
  piServerError: any;
  piPointData: any;
  piPointExistsValue: boolean;
  webId: string;
  snapshotData: any;
  snapshotError: any;
  recordedData: any;
  interpolatedData: any;
  recordedError: any;
  interpolatedError: any;
  piPointError: any;


  constructor(private piWebApiHttpService: PIWebAPIService) { }


  defaultValues(): void {
    this.piServerName = 'PISRV1';
    this.piPointName = 'SINUSOID';
    this.startTime = '*-1d';
    this.endTime = '*';
    this.interval = '1h';
    this.getSnap = this.yesOrNoOptions[0];
    this.getRec = this.yesOrNoOptions[0];
    this.getInt = this.yesOrNoOptions[0];
  }
  
  // get data by making http calls
  getData(): void {
    this.piWebApiHttpService.configureInstance("https://devdata.osisoft.com/piwebapi", false, "webapiuser", "!try3.14webapi!");


    // switch div to display the results
    this.requestMode = false;
    // all HTTP requests are done through the  piWebApiHttpService factory object
    this.piWebApiHttpService.dataServer.getByPath('\\\\' + this.piServerName)  
      .subscribe(res => {
        this.piServerData = res;
        this.piServerExistsValue = true;
      },
      error => {
        this.piServerError = error;
        this.piServerExistsValue = false;
      });




      this.piWebApiHttpService.point.getByPath('\\\\' + this.piServerName + '\\' + this.piPointName, null, null).subscribe(res => {
        this.piPointData = res
        this.piPointExistsValue = true
        //in case of success, we will get the webId of the PI Point which will be used by other requests
        this.webId = res.WebId;
        this.piWebApiHttpService.stream.getValue(this.webId).subscribe(res => {
            //Response of the snapshot is stored on the snapshotData
            this.snapshotData = res
        }, error => {
            this.snapshotError = error


        });


        this.piWebApiHttpService.stream.getRecorded(this.webId, null, null, this.endTime, null, null, null, null, this.startTime).subscribe(res => {
            this.recordedData = res
          }, error => {
            this.recordedError = error
        });
        this.piWebApiHttpService.stream.getInterpolated(this.webId, null, this.endTime, null, null, this.interval, null, this.startTime, null).subscribe(res => {
            this.interpolatedData = res
          }, error => {
            this.interpolatedError = error.json();
        });
      }, error => {
        this.piPointError = error.data
        this.piPointExistsValue = false
    });
  }
}

 

 

Final Remarks

 

It is a great enhancement the fact that you can download this library through npm. I hope that with this new release, developing modern apps on top of the PI System will become even easier!

 

Please share your comments and suggestions below!

We celebrated the 3 winning teams already during the Awards Ceremony at the EMEA UC 2017 TechCon opening last Thursday. It's about time to do this publicly and to share some impressions with you.

 

It was again a big pleasure for me to see the participants of our Hackathon taking the challenge with great energy. I was very impressed by the solutions presented during the judging session.

 

Our Data Sponsor this time was Vitens N.V., the largest drinking water supplier in the Netherlands. Accordingly, the theme was Innovation for better drinking water.

Vitens offered flow, pressure and water quality data from their distribution network at Friesland province. Because Vitens is a non-profit company they defined the challenge around providing customers reliably with water at a constantly good quality.

 

Statistics

We saw 24 hackers forming 7 teams and enjoying our 23 hours event.

 

Hackathon Impressions

Please find the team names underneath the pictures.

 

Team The Three Triers

 

Team Living on the edge

 

Team blueDogPants

 

Team Diet Coke

 

Team Aperio

 

Team werusys Cologne

 

     Team connectPoint

 

Judging criteria

  • Creativity and Originality (5 points)
  • Potential Business Impact (5 points)
  • Technical Implementation (5 points)
  • Data Analysis and Insight (5 points)
  • User Experience (5 points)

 

Pitch Panel

This year we pulled the idea of having a Pitch Panel over the ocean.

The Pitch Panel is a business oriented session where the top teams present their work in the hackathon to a panel of business leaders from the data sponsor and OSIsoft. The goal is for the hackers to have a chance to show their work in a different environment more aligned with business visibility and opportunity. The business leaders can see the novel creations and decide if they like to pursue any of the hackers in a more advanced commercial capacity.

 

Besides the 3 winning Teams, judges decided to offer team Aperio to present in front of the Pitch Panel.

The Pitch Panel was recorded. We will be sharing a link to the video, as soon as it is ready.

 

The winning teams

 

 

 

 

 

 

Please see attached for additional impressions captured by our professional conference photographer. Thank you Sebastian!

Filter Blog

By date: By tag: