zzoldan

Building a PI AF hierarchy using the PI Connector for UFL

Blog Post created by zzoldan Employee on Aug 19, 2016

This post is based on a summer internship project, undertaken at the OSIsoft Montreal office. For more details, check out "Monitoring Smart City Assets with the PI System"

 

Building a PI AF hierarchy using the PI Connector for UFL

In this post, we will present a sample of the PI Connector for UFL’s ability to interact with a PI AF structure. Unlike the PI Interface for UFL, the PI Connector for UFL can communicate with the PI AF server and create PI AF elements. These PI AF elements can be crated based on templates to include static attributes and PI point data references.

 

Why create PI AF elements using the PI connector for UFL?

In the past, if there was a need to roll out a large number of AF elements, this had to be done either manually or using Excel/PI Builder. With the PI Connector for UFL, we can create AF elements, assign AF attributes, and create an AF hierarchy automatically. The process remains the same for 10 elements or 10,000 elements.  Should a new PI AF element appear in your data file, the PI Connector for UFL will add it automatically to the PI AF hierarchy. Under certain conditions, the Connector can therefore function under a “set and forget” mentality where the user can configure the Connector and walk away.

 

Building an element hierarchy based on data available in the input file:

When building an element hierarchy, the PI Connector for UFL will primarily rely on hierarchy data present in the data file being read. Anything not present in the data must be hardcoded in the connector’s configuration INI file, which will be demonstrated in the next section.

For example, take this excerpt from a live data feed showing a bike rental station in San Francisco. Each public bike rental station will have live, dynamic attributes such as the number of bikes available and number of docks available, and static attributes such as station ID, station name, and latitude/longitude positioning.

 

{      "id": 2,
      "stationName": "San Jose Diridon Caltrain Station",
      "availableDocks": 16,
      "totalDocks": 27,
      "latitude": 37.329732,
      "longitude": -121.901782,
      "statusValue": "In Service",
      "statusKey": 1,
      "availableBikes": 11,
      "stAddress1": "San Jose Diridon Caltrain Station",
      "stAddress2": "",
      "city": "San Jose",
      "postalCode": "",
      "location": "Crandall Street",
      "altitude": "",
      "testStation": false,
      "lastCommunicationTime": null,
      "landMark": "San Jose",
      "renting": true,
      "is_renting": true
 },

 

 

Say we wanted to build an PI AF hierarchy that looked something like this:

  • San Francisco Bike Share
    • CITY A
      • Station A
      • Station B
    • CITY B
      • Station C
      • Station D

 

 

Using our Connector’s message statements, we can extract the variables we’re interested in. These include the longitude/latitude, station name, station ID, city location, available docks and available bikes.

We can then call the STOREEVENT function to store our PI points, and then add them to a dynamic attribute collection. Similarly, we can store static data in our static attribute collection.

 

StoreEvent("SF." + StationID + ".AvailDocks", "Docks Available", UpdateTime, DocksAvail)
StoreEvent("SF." + StationID + ".AvailBikes", "Bikes Available", UpdateTime, BikesAvail)
DynAttrCol = Add("SF." + StationID + ".AvailDocks")
DynAttrCol = Add("SF." + StationID + ".AvailBikes")
StatAttrCol = Add("Longitude", Long)
StatAttrCol = Add("Latitude", Lat)
StatAttrCol = Add("Station ID", StationID)
StatAttrCol = Add("City", City)

 

 

Now that our collections are fully set up, we can more on to storing our AF elements with the desired hierarchy. We have to start by storing the root of our hierarchy first, and then drill down to each level. We can use CHAR(92) to designate the backslash “\” character in the name of the path.

 

StoreElement("Bay Area Bike Share (SF)")
StoreElement("Bay Area Bike Share (SF)" + CHAR(92) + City, "SF_Borough")
StoreElement("Bay Area Bike Share (SF)" + CHAR(92) + City + CHAR(92) + StationName, "SF_Station", DynAttrCol, StatAttrCol)

 

Notice on the final line, we store the individual AF element with the desired static and dynamic attribute collection (StatAttrCol, DynAttrCol)

 

This is the resulting PI AF structure, fully built using the PI Connector for UFL.

 

 

The INI configuration file for this method is included below, named "Config file - Automatically build hierarchy.ini"

 

Building an element hierarchy based on data not available in the input file:

 

In this case, we would like to build a detailed hierarchy based on information which is not present in the source data file. We have two options – either build the hierarchy using PI Builder in Excel and then use the Connector to populate the PI points. Or we can hardcode the Connector’s INI Configuration file to include logic to create the desired hierarchy.

 

Say we wanted to build a similar hierarchy to the one listed in the section above, but we did not have access to a station’s city location in the data file. We still had all the other variables, just not in which city the station is located. We have access to another file containing this information. The INI configuration file can be hardcoded with this information.

 

Similar to the procedure above, we have to first store the individual PI points and add any attributes we want to their respective collection. We start off by storing the parent element for every city:

 

StoreElement("Toronto Bike Share Stations" + CHAR(92) + "Brockton", "TO_Borough")
StoreElement("Toronto Bike Share Stations" + CHAR(92) + "Cabbagetown", "TO_Borough")
StoreElement("Toronto Bike Share Stations" + CHAR(92) + "Chinatown", "TO_Borough")

 

We then need logic statements linking stations to their cities, based on the station ID.

 

IF(StationID == 7056 OR StationID == 7113) THEN
StoreElement("Toronto Bike Share Stations" + CHAR(92) + "Cabbagetown" + CHAR(92) + StationName, "TO_Stations", DynAttrCol, StatAttrCol)
ENDIF

 

We repeat these IF statements until we have assigned all stations to their respective cities. In our case, this is the only way to perform the assignment. If the Station ID had fallen into a known range for each city, then we could store it based on that logic too.

 

The INI configuration file for this method is included below, named "Config file - manually build hierarchy.ini"

Outcomes