In this blog post I will show how to write a machine learning output, that was produced in Python, back to the PI System.

 

This blog post is preceeded by this blog post: Machine Learning Pipeline 1: Importing PI System Data into Python

 

Output of machine learning

The output of machine learning is expected to be a numpy array. The output features and output length determine the dimension of this numpy array.

 

Dimension: (output length, output features)

 

With

output length = number of predicted timesteps

output features = number of predicted features (for example: Temperature, Humdity,..)

 

Example:

Dimensions of this numpy array are: (192, 9)

9 columns and 192 rows

 

These values do not yet have a timestamp.

 

Generating a timestamp

Depending on how these predicted values were generated, a timestamp for these must be generated before they can be written to the PI System.

The timestamp format for the PI System is:

 

"YYYY-MM-DDThh:mm:ssZ"

 

Pythons datetime package can be used to generate timestamps:

 

from datetime import datetime
from datetime import timedelta

timestamp = datetime.now()

print(timestamp)

now = datetime.now() # current date and time

year = now.strftime("%Y")
print("year:", year)

month = now.strftime("%m")
print("month:", month)

day = now.strftime("%d")
print("day:", day)

time = now.strftime("%H:%M:%S")
print("time:", time)

date_time = now.strftime("%Y-%m-%dT%H:%M:%SZ")
print("date and time:",date_time)

(This is just an example how the parts of the timestamp can be generated)

 

Pythons timedelta can be used to add time to a timestamp. We will use timedelta to generate the timestamps for our predicted values. In our case we know that the sampling time of our values is 1h. (This is by design, as we earlier imported events with the same sampling frequency)

 

Posting output to the PI System

 

The following code will use the Python requests library to send a HTTP POST request to the PI Web API endpoint:

Requests: HTTP for Humans™ — Requests 2.21.0 documentation

 

for event in predict:

#build timestamp of format "YYYY-MM-DDThh:mm:ssZ"
timestamp = timestamp + timedelta(hours=1)#as we have 1h delta in between each predicted event
pi_timestamp = timestamp.strftime("%Y-%m-%dT%H:%M:%SZ")

#take only first column
value = event[0]

#Writing back to PI System
response = requests.post('https://<PIWebAPI_host>/piwebapi/streams/<webID_of_target_PIPoint>/value?updateOption=InsertNoCompression', data={'Timestamp': pi_timestamp, 'UnitsAbbreviation': '', 'Good': 'true' , 'Questionable': 'false', 'Value': value}, headers={"Authorization": "Basic %s" % b64Val}, verify=True)

(Sorry for the wrong intendation)

 

Here the UpdateValue method of PI Web API is used:

UpdateValue POST streams/{webId}/value

 

The efficiency can be enhanced by first creating all JSON objects for the events that are supposed to pe posted to the PI System, per PIPoint, and send them in bulk, using the UpdateValues method:

UpdateValues POST streams/{webId}/recorded