Marcos Vainer Loeff

Developing a PHP application using PI Web API client library

Blog Post created by Marcos Vainer Loeff Employee on May 23, 2017

Introduction

 

In 2014, I have written a blog post about Developing a PHP application using PI Web API. At that time, it was necessary to build the URL with strings concatenation in order to make HTTP request against PI Web API. With the Swagger specification that comes with PI Web API 2017 release, I was able to generate a PI Web API Client library for PHP. On this blog post, I will rewrite this PHP application in order to use this library instead of writing some lines of code to generate the URLs. Let's see how this work.

 

The source code package of this PHP application with PI Web API client is available on this GitHub repository.

 

Adding the library to the project

 

Download the PHP files from the  PI Web API Client library for PHP GitHub repository, extract the files and copy the lib folder to the root of your PHP application folder.

 

 

Comparing the piwebapi_wrapper.php files

 

Let's compare both piwebapi_wrapper.php files. The first one is from the 2014 blog post and second one is related to this blog post which uses the PI Web API client library.

 

piwebapi_wrapper.php with no client library.

 

<?php
class PIWebAPI
{
  public static function CheckIfPIServerExists($piServerName)
  {
  $base_service_url = "https://cross-platform-lab-uc2017.osisoft.com/piwebapi/";
  $url = $base_service_url . "dataservers";
  $obj = PIWebAPI::GetJSONObject($url);
  foreach($obj->Items as $myServer)
  {
  if(strtolower($myServer->Name)==strtolower($piServerName))
  {
  return(true);
  }
  }
  return (false);
  }

  public static function CheckIfPIPointExists($piServerName, $piPointName)
  {
  $base_service_url = "https://cross-platform-lab-uc2017.osisoft.com/piwebapi/";
  $url = $base_service_url . "points?path=\\\\" . $piServerName . "\\" . $piPointName;
  $obj1 = PIWebAPI::GetJSONObject($url);
  try {
  if(($obj1->Name)!=null)
  {
  return (true);
  }
  return (false);
  }
  catch (Exception $e)
  {

  }
  }

  public static function GetSnapshot($piServerName, $piPointName)
  {
  $base_service_url = "https://cross-platform-lab-uc2017.osisoft.com/piwebapi/";
  $service_url = $base_service_url . "points?path=\\\\" . $piServerName . "\\" . $piPointName;
  $obj_pipoint = PIWebAPI::GetJSONObject($service_url);
  $url = $obj_pipoint->Links->Value;
  $obj_snapshot = PIWebAPI::GetJSONObject($url);
  return ($obj_snapshot);

  }

  public static function GetRecordedValues($piServerName, $piPointName,$startTime,$endTime)
  {
  $base_service_url = "https://cross-platform-lab-uc2017.osisoft.com/piwebapi/";
  $service_url = $base_service_url . "points?path=\\\\" . $piServerName . "\\" . $piPointName;
  $obj_pipoint = PIWebAPI::GetJSONObject($service_url);
  $url = $obj_pipoint->Links->{'RecordedData'} ."?starttime=" . $startTime . "&endtime=" . $endTime;
  $obj_rec = PIWebAPI::GetJSONObject($url);
  return ($obj_rec);

  }

  public static function  GeInterpolatedValues($piServerName, $piPointName,$startTime,$endTime,$interval)
  {
  $base_service_url = "https://cross-platform-lab-uc2017.osisoft.com/piwebapi/";
  $service_url = $base_service_url . "points?path=\\\\" . $piServerName . "\\" . $piPointName;
  $obj_pipoint = PIWebAPI::GetJSONObject($service_url);
  $url = $obj_pipoint->Links->{'InterpolatedData'} ."?starttime=" . $startTime . "&endtime=" . $endTime . "&interval=" . $interval;
  $obj_int = PIWebAPI::GetJSONObject($url);
  return ($obj_int);

  }

  private static function GetJSONObject($url)
  {
  $username = "username";
  $password= "password";
  $ch = curl_init($url);
  curl_setopt($ch, CURLOPT_HEADER, false);
  curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
  curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
  curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
  curl_setopt($ch, CURLOPT_USERPWD, $username.":".$password); 
  $result = curl_exec($ch);
  $json_o=json_decode($result);
  return ($json_o);
  }
}

 

 

piwebapi_wrapper.php with PHP client library.

 

 

<?php
include_once ( __DIR__ . "\\lib\\PIWebApiLoader.php");
use \PIWebAPI\Client\PIWebApiClient;
class PIWebAPI
{
  public $piwebapi= NULL;
  public function __construct()
  {
  $this->piwebapi = new PIWebApiClient("https://cross-platform-lab-uc2017.osisoft.com/piwebapi","username", "password", "BASIC", FALSE, TRUE);
  }


  public function checkIfPIServerExists($piServerName)
  {

  try 
  {
  $response = $this->piwebapi->dataServer->dataServerGetByNameWithHttpInfo($piServerName);
  if($response[1] == 200)
  {
  return true;
  }
  else {
  return false;
  }
  } 
  catch (Exception $e) {
  return false;
  }


  }

  public function getPIPoint($piServerName, $piPointName)
  {
  try
  {
  $path = "\\\\" . $piServerName . "\\" . $piPointName;
  $response = $this->piwebapi->point->pointGetByPathWithHttpInfo($path);
  if($response[1] == 200)
  {
  return $response;
  }
  else {
  return null;
  }
  }
  catch (Exception $e) {
  return null;
  }
  }

  public function getSnapshot($webId)
  {
  return $this->piwebapi->stream->streamGetEnd($webId);
  }

  public function getRecordedValues($webId, $startTime, $endTime)
  {
  return $this->piwebapi->stream->streamGetRecorded($webId, null, null, $endTime, null, null, null, null, $startTime);
  }

  public function  getInterpolatedValues($webId, $startTime, $endTime, $interval)
  {
  return $this->piwebapi->stream->streamGetInterpolated($webId, null, $endTime, null, null, $interval, null, $startTime);
  }
}

 

The readme.rd from the GitHub repository provides information about how to use this library within a PHP application. Look how easy it is to switch from Basic to Kerberos authentication. Just change the value for $authMethod (which is an input of the PIWebAPIClient constructor) from  "BASIC" to "KERBEROS".

 

 

Updating index.php

 

The objects returned by the methods from the PIWebAPI class are different when compared to the older project. The reason is that the Swagger Code generation will generate classes basic on the specification Json description. As a result, the way you extract the values on the index.php file to render on the tables is a little different:

 

function displaySnapValues($SinusoidSnap) {
  ?>
  <h2>Snapshot Value of Sinusoid</h2>
  <br />
  <table style="width: 20em; border: 1px solid #666;">
  <tr>
  <th>Value</th>
  <th>Timestamp</th>
  </tr>
  <tr>
  <td><?php echo $SinusoidSnap['value'][0]; ?></td>
  <td><?php echo $SinusoidSnap['timestamp']->format('Y-m-d H:i:s'); ?></td>
  </tr>
  </table>
  <br />
  <br />
  <?php
}
function displayRecValues($SinusoidRec) {
  ?>

  <h2>Recorded Values of Sinusoid</h2>
  <br />
  <table style="width: 20em; border: 1px solid #666;">
  <tr>
  <th>Value</th>
  <th>Timestamp</th>
  </tr><?php
  foreach ( $SinusoidRec['items'] as $item) {
  echo "\n<tr>";
  echo "\n\t<td>" . $item['value'][0] . '</td>';
  echo "\n\t<td>" . $item['timestamp']->format('Y-m-d H:i:s') . "</td>";
  echo "\n</tr>";
  }
  ?>

  </table>


  <br />
  <br />
  <?php
}
function displayIntValues($SinusoidInt) {
  ?>
  <h2>Interpolated Values of Sinusoid</h2>
  <br />
  <table style="width: 20em; border: 1px solid #666;">
  <tr>
  <th>Value</th>
  <th>Timestamp</th>
  </tr>
  <?php
  foreach ( $SinusoidInt['items'] as $item) {
  echo "\n<tr>";
  echo "\n\t<td>" . $item['value'][0] . '</td>';
  echo "\n\t<td>" . $item['timestamp']->format('Y-m-d H:i:s') . "</td>";
  echo "\n</tr>";
  }
  ?>
  </table>
  <?php
}

 

Conclusion

 

Although PHP is not my favorite language for web development, I have seen some questions on PI Square about using PHP to retrieve PI data through PI Web API. As a result, I think this library will be very useful for those PHP developers who wants to add value to their application by integrating it with the PI System.

Outcomes