Introduction

 

I've recently published a blog post about generating the WebID on the client with the PI Web API client library for .NET Standard. It explains how the user can access the webIdHelper class in order to generate a WebID 2.0 on the client, without having to make an HTTP request. This class with the same methods and logic were added to the PI Web API client libraries for jQuery, Angular and AngularJS. This updated client library for AngularJS can also be used in PI Vision 3. As a result, the WebID 2.0 client generation feature is available when developing a custom PI Vision 3 symbol.

 

Note that those methods will only work if you are using PI Web API 2017 R2+.

 

Example in JavaScript (jQuery and AngularJS)

 

    var point1webId = piwebapi.webIdHelper.generateWebIdByPath("\\\\MARC-PI2016\\SINUSOID", "PIPoint");
    var point2webId = piwebapi.webIdHelper.generateWebIdByPath("\\\\MARC-PI2016\\CDT158", "PIPoint");
    var point3webId = piwebapi.webIdHelper.generateWebIdByPath("\\\\MARC-PI2016\\SINUSOIDU", "PIPoint");
    var piAttributeWebId = piwebapi.webIdHelper.generateWebIdByPath("\\\\MARC-PI2016\\CrossPlatformLab\\marc.adm|Heading", "PIAttribute", "PIElement");
    var piElementWebId = piwebapi.webIdHelper.generateWebIdByPath("\\\\MARC-PI2016\\CrossPlatformLab\\marc.adm", "PIElement");
    var piDataServerWebId = piwebapi.webIdHelper.generateWebIdByPath("\\\\MARC-PI2016", "PIDataServer");


    var piDataServer = null;
    var piAttribute = null;
    var piElement = null;
    piwebapi.dataServer.get(piDataServerWebId).then(function (response) {
        piDataServer = response.data;
    });
    piwebapi.attribute.get(piAttributeWebId).then(function (response) {
        piAttribute = response.data;
    });
    piwebapi.element.get(piElementWebId).then(function (response) {
        piElement = response.data;
    });




    var piAttributeWebIdInfo = piwebapi.webIdHelper.getWebIdInfo(piAttributeWebId);
    var piElementWebIdInfo = piwebapi.webIdHelper.getWebIdInfo(piElementWebId);
    var piDataServerWebIdInfo = piwebapi.webIdHelper.getWebIdInfo(piDataServerWebId); 

 

 

 

Example in TypeScript (Angular)

 

    let point1webId = this.piWebApiHttpService.webIdHelper.generateWebIdByPath("\\\\PISRV1\\SINUSOID", PIPoint.name, null);
    let point2webId = this.piWebApiHttpService.webIdHelper.generateWebIdByPath("\\\\PISRV1\\CDT158", PIPoint.name, null);
    let point3webId = this.piWebApiHttpService.webIdHelper.generateWebIdByPath("\\\\PISRV1\\SINUSOIDU", PIPoint.name, null);
    let piAttributeWebId = this.piWebApiHttpService.webIdHelper.generateWebIdByPath("\\\\PISRV1\\Universities\\UC Davis\\Buildings\\Academic Surge Building|Electricity Totalizer", PIAttribute.name, PIElement.name);
    let piElementWebId = this.piWebApiHttpService.webIdHelper.generateWebIdByPath("\\\\PISRV1\\Universities\\UC Davis\\Buildings\\Academic Surge Building", PIElement.name, null);
    let piDataServerWebId = this.piWebApiHttpService.webIdHelper.generateWebIdByPath("\\\\PISRV1", PIDataServer.name, null);


    let piDataServer: PIDataServer = null;
    let piAttribute: PIAttribute = null;
    let piElement: PIElement = null;
    this.piWebApiHttpService.dataServer.get(piDataServerWebId).subscribe(res => {
        piDataServer = res;
    });
    this.piWebApiHttpService.attribute.get(piAttributeWebId).subscribe(res => {
        piAttribute = res;
    });
    this.piWebApiHttpService.element.get(piElementWebId).subscribe(res => {
        piElement = res;
    });




    let piAttributeWebIdInfo = this.piWebApiHttpService.webIdHelper.getWebIdInfo(piAttributeWebId);
    let piElementWebIdInfo = this.piWebApiHttpService.webIdHelper.getWebIdInfo(piElementWebId);
    let piDataServerWebIdInfo = this.piWebApiHttpService.webIdHelper.getWebIdInfo(piDataServerWebId);  

 

 

The workflow of both examples above is:

  • Use the generateWebIdByPath method from the webIdHelper class to generate the WebID 2.0 of a PI object. You need to define the type of the object on the second input of this function. According to the PI object, the third input might be necessary to define the owner's type.
  • By calling the Get() method from Attribute, Element and DataServer controllers and reviewing the response, we will make sure that PI Web API understands the generated WebIDs. Otherwise, it will return an exception or an error status code in their response.
  • Finally, we call the getWebIdInfo() method from the webIdHelper class to get useful information about the WebID such as Path, ObjectID, ServerID, WebID Version and WebIDType.

 

You can learn more about those methods and the logic in the background in the .NET version of this blog post.

 

Example in a PI Vision 3 custom symbol

 

In this example we are creating a custom symbol on top of the PI Web API client library for AngularJS according to this blog post. This symbol gets the path of the element which is used to generate the WebID. Then the symbol calls the getSummary() method using the generated WebID from the Calculation controller. This method is returns the result of evaluating the expression over the time range. The JSON response is shown directly on the screen since our goal is to show the WebID generation.

 

Do not forget to update the angular-piwebapi-kerberos.js to version 1.1.1.

 

Please refer to the full code snippet 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');
    }
}




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


    loadPIWebApiModule();
    PV.deriveVisualizationFromBase(symbolVis);


    var definition = {
        typeName: 'piwebapi-adv-sample',
        displayName: 'PI Web API Client library advanced 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);




        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');
        }


        scope.streamWebId = null;


        function dataUpdate(data) {
            if ((data == null) || (data.Rows.length == 0)) {
                return;
            }


            var firstDataRow = data.Rows[0];
            if (firstDataRow.Path) {
                var path = firstDataRow.Path.substring(3, firstDataRow.Path.length);
                if (firstDataRow.Path.substring(0, 2) == "pi") {
                    path = "\\\\" + path.split("\\")[2]
                    scope.streamWebId = piwebapi.webIdHelper.generateWebIdByPath(path, "PIDataServer");
                }
                if (firstDataRow.Path.substring(0, 2) == "af") {
                    path = path.split("|")[0];
                    scope.streamWebId = piwebapi.webIdHelper.generateWebIdByPath(path, "PIElement");
                }


            }


            if (scope.streamWebId != null) {


                calculationBasis = 'TimeWeighted';
                endTime = "*";
                expression = "2*'Latitude'";
                sampleInterval = undefined;
                sampleType = undefined;
                selectedFields = undefined;
                startTime = "*-1d";
                summaryDuration = undefined;
                summaryType = "total";
                timeType = undefined;
                webId = scope.streamWebId;
                piwebapi.calculation.getSummary(calculationBasis, endTime, expression, sampleInterval, sampleType, selectedFields, startTime, summaryDuration, summaryType, timeType, webId, null).then(function (response) {
                    scope.data = response.data;
                });
            }
        }
    }
    PV.symbolCatalog.register(definition);
})(window.PIVisualization);

 

 

 

 

Conclusions

 

Generating the Web ID 2.0 on the client provides a great performance improvement on your web application and PI Vision 3 custom symbols. Use this feature whenever is possible making sure your PI Web API version is compatible with this great feature.

 

Please share your comments and thoughts below!