Introduction

 

I have already published a blog post about using PI Web API client library for AngularJS in PI Vision 2016 R2 and PI Vision 2017. Nevertheless, it was needed to modify the PI Vision source code, which was an important factor for our customers and partners not to use this great feature.

 

On this blog post, I will show you a new way to use PI Web API client library for AngularJS without changing the PI Vision 3 source code. This approach was tested in PI Vision 2017 and PI Vision 2017 R2.

 

Creating a custom symbol using the piwebapi service

 

First of all, open the browser and go to this GitHub repository. Download the source code package to a zip file. Within this file, copy the \dist\angular-piwebapi-kerberos.min.js file to %PIHOME64%\PIVision\Scripts\app\editor folder.

 

Since the PI Vision 3 source code won't be modified, we need to find a new way to:

  1. Detect if the library was already loaded
  2. If not, load the angular-piwebapi-kerberos.min.js script.
  3. Add the ngPIWebApi as a dependency of PI Vision.

 

As a result, all custom libraries using the PI Web API client library needs to start with the method below:

 

function loadPIWebApiModule() {
    var app = angular.module(APPNAME);
    var hasPiWebApiLoaded = (app.requires.indexOf("ngPIWebApi") > -1);


    if (hasPiWebApiLoaded == false) {
        var xhrObj = new XMLHttpRequest();
        xhrObj.open('GET', "/PIVision/Scripts/app/editor/symbols/ext/libraries/angular-piwebapi-kerberos.min.js", false);
        xhrObj.send('');
        var se = document.createElement('script');
        se.type = "text/javascript";
        se.text = xhrObj.responseText;
        document.getElementsByTagName('head')[0].appendChild(se);
        piWebApiApp = angular.module('ngPIWebApi');
        var app = angular.module(APPNAME);
        app.requires.push('ngPIWebApi');
    }
}

 

 

As soon as the custom library starts to load, it needs to call loadPIWebApiModule() method. The reason for that is we want to make sure that the script (angular-piwebapi-kerberos.min.js) is loaded before the symbolVis.prototype.init() method is called as the third input of this method is the PI Web API service (piwebapi Angular service variable). Let's take a look at the example provide in my previous blog post.

 

Create a new file name sym-piwebapi-basic-sample.js on the %PIHOME64%\PIVision\Scripts\app\editor\symbols\ext folder with the following content:

 

function loadPIWebApiModule() {
    var app = angular.module(APPNAME);
    var hasPiWebApiLoaded = (app.requires.indexOf("ngPIWebApi") > -1);


    if (hasPiWebApiLoaded == false) {
        var xhrObj = new XMLHttpRequest();
        xhrObj.open('GET', "/PIVision/Scripts/app/editor/symbols/ext/libraries/angular-piwebapi-kerberos.min.js", false);
        xhrObj.send('');
        var se = document.createElement('script');
        se.type = "text/javascript";
        se.text = xhrObj.responseText;
        document.getElementsByTagName('head')[0].appendChild(se);
        piWebApiApp = angular.module('ngPIWebApi');
        var app = angular.module(APPNAME);
        app.requires.push('ngPIWebApi');
    }
}




(function (PV) {
    function symbolVis() { }


    loadPIWebApiModule();
    PV.deriveVisualizationFromBase(symbolVis);


    var definition = {
        typeName: 'piwebapi-basic-sample',
        displayName: 'PI Web API Client library basic sample',
        datasourceBehavior: PV.Extensibility.Enums.DatasourceBehaviors.Multiple,
        inject: ['piwebapi'],
        getDefaultConfig: function () {
            return {
                DataShape: 'Table',
                Height: 400,
                Width: 400,
                MarkerColor: 'rgb(255,0,0)'
            };
        },
        visObjectType: symbolVis
    };


    symbolVis.prototype.init = function init(scope, elem, piwebapi) {
        piwebapi.ConfigureInstance("https://marc-web-sql.marc.net/piwebapi", true);
        
        console.log('Starting init scope: ' + scope);
        console.log('Starting init scope: ' + elem);


        this.onDataUpdate = dataUpdate;
        this.onConfigChange = configChanged;
        this.onResize = resize;
        
        function configChanged(config, oldConfig) {
            console.log('configChange called');
        };


        function resize(width, height) {
            console.log('resized called');
        }


        function dataUpdate(data) {
            piwebapi.home.get().then(function (response) {
                scope.data = response.data;
            });
        }
    }
    PV.symbolCatalog.register(definition);
})(window.PIVisualization);

 

Create a new file name sym-piwebapi-basic-sample-template.html on the %PIHOME64%\PIVision\Scripts\app\editor\symbols\ext folder with the following content:

 

<center>
    <br /><br />
    <p style="color: white;">{{data}}</p>
</center>

 

You can find more custom PI Vision symbols samples that inject piwebapi service here.

 

Time to test our custom library. Dragging any element and dropping it on the screen, we can see that JSON response from the main PI Web API endpoint.

 

 


Conclusions

 

I hope that using the PI Web API client library without changing the PI Vision 3 source code will make our customers and partners use this library even more. On my next update, the library will be able to build WebIDs client side.