For this you will have to use a mix of the AF SDK and the PI SDK, using the AFAttribute's RawPIPoint property as a bridge between the two. Then you can use the PIPoint's PointAttributes collection to query its "descriptor" attribute.
PISDK.PIPoint pt = (PISDK.PIPoint)someAFAttribute.RawPIPoint
Thank you for your response.
I forget one thing. My AfAttribute object is attached to a pipoint array. In this case the RawPiPoint is null.
Is there another way?
Oh, then that is completely different... At this time there is no direct way to interact with the PI Point(s) in a "PI Point Array" attribute, as you would with a regular "PI Point" attribute using its RawPIPoint property or the AFAttributeList.GetRawPIPoint() method.
Instead, one has to parse the attribute's ConfigString and obtain the PI Point(s) manually...
Please do not hesitate to let me know if you need an example of how to accomplish this.
Do you mean i have to reteive the pipoint names and i connet to the pi server (via pisdk) and then i retreive the descriptor for each pi point.
string piServerName = "servername";
// connect to the server and throw arg exception if this fails
PISDK.Servers servers = piSDK.Servers;
server = servers[piServerName]; // use defined sever
server.Open(connectionString); // connect
//for each pipoint name i reteive the descriptor..
string descriptor = server.PIPoints["a point"].PointAttributes["descriptor"].Value.ToString();
Is there another way to do that?
That is correct: you need to read your AF Attribute's ConfigString, parse it to discover the various PI Point names (a.k.a. tags), and then retrieve their "descriptor" via PI SDK (your last line of code, essentially).
I dont like this way..
Well, you don't have many other choices in this case... that's just a matter of what is implemented in the AF SDK and what is not. Things can't always be as simple as 1-method-does-it-all - life would be too easy
Anyhow, if that may help here is an example of how you would parse a ConfigString to resolve its PI Point(s) and ultimately do something with their descriptors. One unsupported scenario here is if you have something like %Element% configured... then these won't resolve. But I'm sure you can adapt this code if you need to support those dynamic placeholders - I think you got a pretty good starting point here.
string configString = myAttribute.ConfigString;
// remove trailing settings
int indexOfSemicolon = configString.IndexOf(';');
if (indexOfSemicolon > 0)
configString = configString.Substring(0, indexOfSemicolon);
// get server portion
int endOfServerName = configString.IndexOf('\\', 2);
if (endOfServerName < 0)
string serverNameWithSlashes = configString.Substring(0, endOfServerName + 1 );
// get tag names
string tagNames = configString.Substring(endOfServerName+1).Split('|');
if (tagNames.Length <= 0)
Console.WriteLine("No Tags Found");
// now build list of tag paths
string fullTagNames = newstring[tagNames.Length];
for (int j = 0; j < tagNames.Length; j++)
fullTagNames[j] = serverNameWithSlashes + tagNames[j];
// Now use attribute list to resolve the tag paths (AFAttributeList understands the embedded ServerID and TagIDs).
// This results in the creation of "dynamic" attribute's, one per PI Point, each configured as a regular PIPointDR
AFAttributeList alist = newAFAttributeList(fullTagNames, AFDB);
object pipoints = alist.GetRawPIPoint();
for (int j = 0; j < pipoints.Length; j++)
PISDK.PIPoint point = pipoints[j] as PISDK.PIPoint;
if (point != null)
MessageBox.Show(fullTagNames[j].ToString() + " NOT FOUND");
Hope this helps!