3 Replies Latest reply on Dec 3, 2015 3:40 PM by Marcos Vainer Loeff

    Reading ONLY Raw values using PI SDK

    Salman@GE

      In my application which is developed using C++, I am trying to read PI point values periodically in a polling fashion i.e., for every x seconds I will check is there any raw data sample available for a PI point. If so, I will add that raw data sample to my application.

       

      I am using RecordedValues PI SDK API to read the value. Following is the code snippet

       

      //pServerPtr is the PI Server connection pointer.

      _PointListPtr pts = pServerPtr->GetPoints(_T("pointid = '3' "),NULL);

      _variant_t tempIndex = 1;

      PIPointPtr pt = pts->GetItem(&tempIndex);

      _variant_t vStartTime = UTCStartTime;

      _variant_t vEndTime = UTCEndTime;

       

      _PIValuesPtr pVals = pt->Data->RecordedValues(vStartTime,vEndTime,btInside,"",fvUseExpressionTimes,NULL); 

       

      Is this the right API to read Raw values?

       

      I am using the Archive Editor in the PI SMT tool to cross check the PI Raw samples against the data stored in my application. They are not matching. I am seeing some extra data samples in my application.

       

      Is there a chance that RecordedValues API returns interpolated value even if the raw sample is not available for the given time frame (between vStartTime & vEndTime)?

      Is Archive Editor (PI-SMT) is the right tool to be consider as the source of truth to cross check for raw values?

        • Re: Reading ONLY Raw values using PI SDK
          Marcos Vainer Loeff

          Hello Mohammed,

           

          I want to clarify that there are two different libraries PI SDK and PI API. PI SDK is more recent library than PI API. This is why the term PI SDK API is confusing.

          I guess that the problem you are seeing different values is that the RecordedValues method will get the values stored on the archive and the snapshot as the end time parameter is now (‘*’). As a result of the compression and exception tests, not all the new snapshot values are archived. Some of them are lost due to the fact that they don’t add much value. As you might be comparing the values from both applications when the PI Point has different snapshots, this might reason why you are seeing different values.

           

          Concerning the RecordedValue method, I would use EventPipe instead. According to the Programming Reference:

           

          “An EventPipe contains items that have changed on the server for its parent (see Applies To). When an EventPipe property is retrieved through the parent it will return a unique event pipe that while kept in scope will receive all the changed items for that parent. Multiple pipes on a single source will all receive each event. Internally the PI-SDK will handle retrieving changed events from the server and scatter them to the instantiated event pipes appropriately.”

           

          This way your application can be notified when a PI Point has received a new value.

           

          Hope it helps!

            • Re: Reading ONLY Raw values using PI SDK
              Salman@GE

              In that case, is there a way I can force RecordedValue method to read data from the archive and not from snapshot.

               

              Also It would be great if you share some sample code snippet in C++ on how to use EventPipe from my requiremnt.

                • Re: Reading ONLY Raw values using PI SDK
                  Marcos Vainer Loeff

                  Hello Mohammed,

                   

                  I believe that if your endTime is '*', the last value of the collection will always be the snapshot.

                   

                  Here is an example of using event pipe in C++:

                   

                  // eventpipe-cpp.cpp : Defines the entry point for the console application.
                  //
                  
                  
                  #include "stdafx.h"
                  #include <iostream>
                  #include <string>
                  #include <Windows.h>
                  #include "ATLComTime.h" // for COleDateTime
                  #import "C:\Program Files\PIPC\pisdk\PISDKCommon.dll"    no_namespace
                  #import "C:\Program Files\PIPC\pisdk\PITimeServer.dll" no_namespace
                  #import "C:\Program Files\PIPC\pisdk\PISDK.dll"  no_namespace
                  
                  
                  
                  
                  IPISDKPtr       spPISDK = NULL;            /* The PISDK */
                  ServerPtr       spServer = NULL;           /* The Server */
                  PIPointPtr      spPIPoint = NULL;          /* The PI Point */
                  
                  
                  
                  
                  int _tmain(int argc, _TCHAR* argv[])
                  {
                    // initialize the COM library  
                    ::CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
                  
                  
                    // Create an instance of the PISDK  
                    spPISDK.CreateInstance(__uuidof(PISDK));
                    // get the PI server   
                    spServer = spPISDK->GetServers()->GetItem("MARC-PI2014");
                    // get the PI point   
                    spPIPoint = spServer->PIPoints->GetItem("SINUSOID");
                  
                  
                    EventPipePtr spEventPipe = spPIPoint->Data->EventPipe;
                  
                  
                  
                  
                    std::cout << "Created EventPipe for PIPoints";
                    char value = 'A';
                    while ('Q' != value)
                    {
                  
                  
                  
                  
                    for (int i = 0; i < spEventPipe->Count; i++)
                    {
                    _PIEventObjectPtr spPIEvent = spEventPipe->Take();
                    PointValuePtr pointValue = (PointValuePtr)spPIEvent->EventData;
                  
                  
                    COleDateTime codtTimeStamp = pointValue->PIValue->TimeStamp->LocalDate;
                    _bstr_t bstrTimeStamp = (_bstr_t)codtTimeStamp.Format(_T("%d-%b-%Y %H:%M:%S"));
                    _variant_t vT = pointValue->PIValue->Value;
                  
                  
                    double  dblValue;
                    int     intValue;
                    _bstr_t bstrValue;
                  
                    switch (vT.vt) {
                    case VT_I4:
                    // Int32
                    intValue = vT.lVal;
                    dblValue = intValue;
                    bstrValue = (_bstr_t)intValue;
                    break;
                    case VT_I2:
                    // Int16
                    intValue = vT.iVal;
                    dblValue = intValue;
                    bstrValue = (_bstr_t)intValue;
                    break;
                    case VT_R8:
                    // Float64
                    dblValue = vT.dblVal;
                    intValue = (int)dblValue;
                    bstrValue = (_bstr_t)dblValue;
                    break;
                    case VT_R4:
                    // Float16/Float32
                    dblValue = vT.fltVal;
                    intValue = (int)dblValue;
                    bstrValue = (_bstr_t)dblValue;
                    break;
                    case VT_BSTR:
                    // String
                    bstrValue = vT.bstrVal;
                    dblValue = 0;
                    intValue = 0;
                    break;
                    default:
                    dblValue = 0.0;
                    intValue = 0;
                    bstrValue = "n/a";
                    break;
                    }
                  
                  
                    std::cout << "\n" + pointValue->PIPoint->Name;
                    std::cout << "\n" + bstrValue;
                    std::cout << "\n" + bstrTimeStamp;
                  
                  
                    std::cout << "\nPress 'Q' to quit or any other key to continue: ";
                    std::cin >> value;
                    }
                    }
                  
                  
                    spEventPipe.Release();
                    spPIPoint.Release();
                    spServer.Release();
                    spPISDK.Release();
                  
                  
                  
                  
                    spEventPipe = NULL;
                    spPIPoint = NULL;
                    spServer = NULL;
                    spPISDK = NULL;
                  
                  
                    // Closes the COM library
                    ::CoUninitialize();
                    return 0;
                  }
                  
                  

                   

                   

                  Remember that we always recommend migrating your applications from PI SDK to PI AF SDK since PI SDK will soon be deprecated. PI AF SDK is a pure .NET library and, therefore, you will gain performance compared to PI SDK. Besides, all the new features (including future PI Points) are being added only to PI AF SDK.

                   

                  Hope it helps!