Learn the Basics of PI Programming - Developing a Web Application With jQuery and PI Web API

Version 1

    Activity Objectives:

    • Make a simple web application in order to send values to the PI System using PI Web API in order to update selected cities attributes.
    • Determine the REST method used to send data to the PI System.



    We are going to develop a web application that will enable a user to manually write to the PI Server, to update weather data for a few cities around the USA. But first, we'll take a look at the PI AF Database we'll be working with. Open up PI System Explorer, click on the “Database” button in the top left of the window, select the USAWeather database and click OK. If the database is not present, check the attachments to this document to set it up. You should see the following structure:


    As you can see, the USAWeather database element hierarchy has a “Cities” element with five child elements named “Chicago”, “Los Angeles”, “New York”, “San Francisco” and “Washington”. Each city element is derived from the “City” element template which has five attribute templates: “Cloud cover”, “Humidity”, ”Pressure”, ”Temperature”, ”Visibility” and “Wind Speed”.

    1.     Open Visual Studio and create a new ASP.NET Web Application project.


    2.     Create two folders called “js” and “css”. Copy the default.css file that your instructor will provide into the css folder. Create a new JavaScript file called sending_data_to_pi.js under the js folder and a HTML file sending_data_to_pi.html under the root folder.


    3.     Open the file sending_data_to_pi.html and paste the following content:


    <!DOCTYPE html>

    <html xmlns="http://www.w3.org/1999/xhtml">


        <!--Adding references to jQuery, Cascade Style Sheet and JavaScript libraries -->

        <script src="http://code.jquery.com/jquery-1.11.1.js"></script>

        <script src="js/sending_data_to_pi.js"></script>

        <link href="css/default.css" rel="stylesheet" />

        <title>Sending Value to the PI System through PI Web API</title>



        <h1>Sending Value to the PI System through PI Web API</h1>

        <p>Select the element and attribute that you want to send your value:</p>

        <!--Adding one drop down list for cities, one for attributes, a text value for the value to be sent and a button to submit -->

        <!--When the button is clicked it will trigger the SendValue() JavaScript function -->

        <label for="city_name">Select city</label>

        <select name="city_name" id="city_name" size="1"></select>

        <label for="attribute_name">Select attribute:</label>

        <select name="attribute_name" id="attribute_name" size="1"></select>

        <label for="value">Value to send:</label>

        <input type="text" name="value" id="value" value="" />

        <br />

        <input type="button" id="UpdateBtn" value="Send Value" onclick="SendValue()" />




    4.     Take a look at the HTML code snippet. The drop down lists for the cities and attributes are currently empty. We will fill the lists using jQuery by getting the values from PI Web API. Therefore, when the page is loaded, jQuery will make two REST calls against PI Web API to fill the drop down list options. After clicking on the “Send Value” button, the value typed on the corresponding the field that will be sent to the PI System.

    5.     It is time to edit the sending_data_to_pi.js file, which is currently empty. First, let’s define the MakeAjaxRequest() function responsible for making calls against the PI Web API. This method has four inputs:

      • Type: HTTP Method: GET, POST, PATCH, PUT or DELETE
      • Url: Address of the resource
      • successCallBack: Variable function to be executed in case the request is successful.
      • Data: Data used on POST and PUT request. The GET and DELETE methods do not use it.

    Double-click on sending_data_to_pi.js and paste the following code into it:


    function MakeAjaxRequest(type, url, SuccessCallBack, data) {


            type: type,

            url: url,

            cache: false,

            async: true,

            data: data,

            contentType: "application/json",

            success: SuccessCallBack,

      xhrFields: {

                withCredentials: true


            error: (function (error, variable) {

                alert('There was an error with the request');





    6.     We now need functions to populate the drop down lists on our page. The following functions GetCitiesName() and GetAttributesName() add the proper items to the drop down lists by calling the MakeAjaxRequest function with the appropriate URL. You will need to replace both URLs in the below functions with URLs appropriate to your system. Use Postman to get a URL that finds:

      • All elements underneath the “Cities” element in the USAWeather Database and use it in the GetCitiesName() function.
      • The attributes of the “City” element template and use it in the GetAttributesName() function.


    function GetCitiesName() {

        var url = "https://Your-Web-Server-Name/piwebapi/elements/Your-WebId/elements";

        MakeAjaxRequest('GET', url, function (data) {

            for (var i = 0; i < data.Items.length; i++) {

                $('#city_name').append($('<option>', {

                    value: data.Items[i].Name,

                    text: data.Items[i].Name






    function GetAttributesName() {

        var url = "https://Your-Web-Server-Name/piwebapi/elementtemplates/Your-WebId/attributetemplates";


        MakeAjaxRequest('GET', url, function (data) {

            for (var i = 0; i < data.Items.length; i++) {

                $('#attribute_name').append($('<option>', {

                    value: data.Items[i].Name,

                    text: data.Items[i].Name

                }), null);





    7.     There’s one thing missing concerning loading the drop down list options. We need to call both GetCitiesName() and GetAttributesName() functions once the HTML page is loaded.  This is achieved by using the $(document).ready function.  Add the following to your code:


    $(document).ready(function () {





    8.     The SendValue() function will send the value to the PI System. It stores the value to be sent, the name of the city and the name of the attribute to write to all in JavaScript variables. Make a GET request in order to receive the response with the URL related to the value of the selected attribute from the selected city. Make a POST request to update the value to the PI System. As we are making asynchronous calls, the variable sendValueFunction contains the function for updating the value for a given URL and data. This variable is the successCallBack variable for the MakeAjaxRequest to get the value URL before making the POST request. The function is below:


    function SendValue() {

        var value = $("#value")[0].value;

        var cityName = $("#city_name")[0].value;

        var attributeName = $("#attribute_name")[0].value;

        var url = "https://Your-Web-Server-Name/piwebapi/attributes?path=\\\\MasterPI\\USAWeather\\Cities\\" + cityName + "|" + attributeName;

        var sendValueFunction = function (data) {

            var valueUrl = data["Links"]["Value"];

            MakeAjaxRequest('POST', valueUrl, function () {

                alert("Value has being sent successfully");

            }, "{'Value': " + value + " }");


        MakeAjaxRequest('GET', url, sendValueFunction, null);



    9.     Click the “debug” button, and a browser should pop up and go to your HTML page. Select one of the cities, and one of the attributes, and use the application to write a value back to the PI Data Archive. Use any client tool to check if you were successful.


    The most common issue with this exercise is security. If you tried running this web application and got errors, post them below and we'll discuss options. The security configuration assumed by this exercise is that there are no cross-domain connections, and Kerberos security is used.