andreas

C++ and PI - PI SDK - UpdateValues

Blog Post created by andreas Employee on May 9, 2012

As a follow up to this post, today I will write a value with annotations to PI.

 

In order to do this, we need the usual preparation. In other words, I need to get my imports:

 
//need to import sdk  
#pragma warning( disable : 4786 4146 )    
#import "E:\PIPC\PISDK\PISDKCommon.dll"    no_namespace 
#import "E:\PIPC\PISDK\PITimeServer.dll"   no_namespace 
#import "E:\PIPC\PISDK\PISDK.dll"          rename("Connected", "PISDKConnected") no_namespace

and some pointers and strings:

 
/* PISDK */
IPISDKPtr       spPISDK = NULL;                /* the PISDK */
ServerPtr       spServer = NULL;               /* the server */
PIPointPtr      spPIPoint = NULL;              /* the pi point */
_bstr_t         bstrServer = "SCHREMMERAVMPI"; /* the pi servername*/
_bstr_t         bstrPointName = "MyLabTag";      /* the tagname */  

now let's start with the initialization:

 
// 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(bstrServer);     
// get the PI point 
spPIPoint = spServer->PIPoints->GetItem(bstrPointName);       

to make my life easier I am going to use a Float32 tag, and I am assuming it does not have a bad value now. I get the snapshot:

 
// get the current value
_PIValuePtr _pv = spPIPoint->Data->GetSnapshot();

and now I need some annotations:

 
// the PI Annotations 
_PIAnnotationsPtr spPIAnns;
spPIAnns.CreateInstance(__uuidof(PIAnnotations));
     
// a string annotation
spPIAnns->Add(L"Test",L"StringAnnotation",L"MyTest",false,VT_BSTR);
// an integer annotation
spPIAnns->Add(L"Test",L"IntegerAnnotation",(int)1,false,VT_I4);
// a float annotation
spPIAnns->Add(L"Test",L"FloatAnnotation",(float)1.23,false,VT_R4);

As usual we have to deal with VARIANTs:

 
// We need a variant to pass
_variant_t vAnns;
VariantInit (&vAnns);
// the type is VT_DISPATCH
V_VT (&vAnns) = VT_DISPATCH;
// assign the annotations to the variant
V_DISPATCH(&vAnns) = spPIAnns;

Now that there is a VARIANT that refers to my annotations. I am going to use UpdateValues to send my value to PI, and to pass the annotations I will need a named values collection, containing the VARIANT:

 
// named values :-)
_NamedValuesPtr spNVValAttr;
spNVValAttr.CreateInstance(__uuidof(NamedValues));
// add the annotations to the named values
spNVValAttr->Add("Annotations", &vAnns);

almost there now. The remaining part is as simple as creating my PIValues collection, adding my PIValue to it, and sending it to PI. Remember, I am assuming my tag is a Float32 and has no bad value :

 
// PI Values
_PIValuesPtr spPIValues;
spPIValues.CreateInstance(__uuidof(PIValues)); 

// make the PI values writeable
spPIValues->put_ReadOnly(false);
// add a new value with current time, new float value and annotations
spPIValues->Add("*",_pv->Value.fltVal + 1,spNVValAttr);
// make the PI values readonly
spPIValues->put_ReadOnly(true);
// write the value to PI
HRESULT hr = spPIPoint->Data->UpdateValues(spPIValues, dmInsertDuplicates, NULL);

cleaning up: 

 
// we don't need the variant anymore
V_VT (&vAnns) = VT_EMPTY;

spNVValAttr.Release();
spPIAnns.Release();
_pv.Release();spPIPoint.Release();
spServer.Release();
spPISDK.Release();
     
// Closes the COM library
::CoUninitialize();

and leaving:

 
if (hr < 0)         
     return hr;     
else        
     return 0;  

 hope you had as much fun reading as I had writing !

Outcomes