Main Content

Update Invalid Data of Tag in AVEVA PI Data Archive

R2026b

This example shows you how to manage invalid data present in a tag in the AVEVA® PI Data Archive by updating data with the correct values from the OPC UA server.

This workflow is useful when sensor outages or communication failures produce bad data in your historian archive. For this example, consider any data with status Bad as invalid. You fetch the correct data for the invalid data instances from the backup data stored in an OPC UA server. You then write the correct values in the AVEVA PI Data Archive at the required time instances.

Running this example requires a PI Data Archive available for connection and the Prosys OPC UA Simulation Server installed and running. The demo tags used in this example were provided by AVEVA and can be downloaded from AVEVA sharefile.

Create Client Connection and Retrieve Required Tags

Connect to the PI Data Archive using the piclient function. This example uses the Windows® computer name as the PI Data Archive name, which might vary depending on the PI System configuration.

host = getenv("COMPUTERNAME");
client = piclient(host);

Find a list of tag names that start with "Flynn I" using the tags function. For more information, see Get Started Accessing a PI Data Archive.

tagsFlynnI = tags(client,Name="Flynn I.*")
tagsFlynnI = 3×1 table
             "Flynn I.Active Power Generated.4780df36-9354-5eda-28b0-f7a67582c48f"
    "Flynn I.Hydro Unit Attention Percentage.fb72102e-7bae-5b4d-0c63-1a95b1062dab"
               "Flynn I.Hydro Unit Condition.eabe7033-cd1c-5fe8-36cc-3d172e7ca0dd"

Read Value of Tag

Read the data recorded in a tag using the read function. To read data over a specific time period, specify a starting and ending datetime using the DateRange name-value argument. For example, to read the data from 09-Dec-2023 in UTC timezone:

startDate = datetime("09-12-2023",InputFormat="dd-MM-uuuu",TimeZone="UTC");
endDate = startDate + days(1);
activePowerGenFlynnI = read(client,tagsFlynnI.Tags(1),DateRange=[startDate endDate])
activePowerGenFlynnI = 8×3 timetable
    09-Dec-2023 04:40:00 UTC    "Flynn I.Active Power Generated.4780df36-9354-5eda-28b0-f7a67582c48f"        NaN     Bad
    09-Dec-2023 05:35:00 UTC    "Flynn I.Active Power Generated.4780df36-9354-5eda-28b0-f7a67582c48f"        NaN     Bad
    09-Dec-2023 06:09:00 UTC    "Flynn I.Active Power Generated.4780df36-9354-5eda-28b0-f7a67582c48f"        NaN     Bad
    09-Dec-2023 13:23:22 UTC    "Flynn I.Active Power Generated.4780df36-9354-5eda-28b0-f7a67582c48f"    95.1400    Good
    09-Dec-2023 14:23:22 UTC    "Flynn I.Active Power Generated.4780df36-9354-5eda-28b0-f7a67582c48f"    96.2200    Good
    09-Dec-2023 15:23:22 UTC    "Flynn I.Active Power Generated.4780df36-9354-5eda-28b0-f7a67582c48f"    98.2360    Good
    09-Dec-2023 16:23:22 UTC    "Flynn I.Active Power Generated.4780df36-9354-5eda-28b0-f7a67582c48f"    99.1100    Good
    09-Dec-2023 17:23:22 UTC    "Flynn I.Active Power Generated.4780df36-9354-5eda-28b0-f7a67582c48f"    95.3000    Good

In this example, the data in rows 1, 2 and 3 are considered as invalid because of the Bad status.

Retrieve Correct Value from OPC UA Server

Create a client object using the endpoint URL of the OPC UA server that you are connecting to and the opcua function. Connect the client to the server using the connect function. For more information, see Access Data from OPC UA Servers.

uaClient = opcua("opc.tcp://localhost:53530/OPCUA/SimulationServer");
connect(uaClient);

Get the handle to the node containing the backup data using the findNodeById function.

nodeOfInterest = findNodeById(uaClient.Namespace,3,1005);

Retrieve the time instances where invalid data is present in the PI tag.

invalidDataTimestamp = activePowerGenFlynnI.Time(activePowerGenFlynnI.Status == "Bad")
invalidDataTimestamp = 3×1 datetime array
    "09-Dec-2023 04:40:00 UTC"
    "09-Dec-2023 05:35:00 UTC"
    "09-Dec-2023 06:09:00 UTC"

Retrieve the values of the node at the specific time instances from the OPC UA server using the readAtTime function.

correctValue = readAtTime(uaClient,nodeOfInterest,invalidDataTimestamp)
correctValue = 
1-by-1 OPC UA Data object array:

           Timestamp                  Sinusoid           
    -----------------------  --------------------------  
    2023-12-09 10:10:00.000       88.535900 [Good (Raw)]  
    2023-12-09 11:05:00.000       90.000000 [Good (Raw)]  
    2023-12-09 11:39:00.000       95.236070 [Good (Raw)]  

Update Invalid Value of Tag

Update the invalid data using the write function. You can overwrite the invalid data with correct data by setting the Overwrite name-value argument to true. You can write data to a tag at a specific timestamp by setting the TimeInstance name-value argument to the required datetime.

write(client,tagsFlynnI.Tags(1),correctValue.Value,TimeInstance=invalidDataTimestamp,Overwrite=true)

Wait briefly for the server to process the update, then verify the values using the read function.

pause(1);
activePowerGenFlynnI = read(client,tagsFlynnI.Tags(1),DateRange=[startDate endDate])
activePowerGenFlynnI = 8×3 timetable
    09-Dec-2023 04:40:00 UTC    "Flynn I.Active Power Generated.4780df36-9354-5eda-28b0-f7a67582c48f"    88.5359    Good
    09-Dec-2023 05:35:00 UTC    "Flynn I.Active Power Generated.4780df36-9354-5eda-28b0-f7a67582c48f"         90    Good
    09-Dec-2023 06:09:00 UTC    "Flynn I.Active Power Generated.4780df36-9354-5eda-28b0-f7a67582c48f"    95.2361    Good
    09-Dec-2023 13:23:22 UTC    "Flynn I.Active Power Generated.4780df36-9354-5eda-28b0-f7a67582c48f"    95.1400    Good
    09-Dec-2023 14:23:22 UTC    "Flynn I.Active Power Generated.4780df36-9354-5eda-28b0-f7a67582c48f"    96.2200    Good
    09-Dec-2023 15:23:22 UTC    "Flynn I.Active Power Generated.4780df36-9354-5eda-28b0-f7a67582c48f"    98.2360    Good
    09-Dec-2023 16:23:22 UTC    "Flynn I.Active Power Generated.4780df36-9354-5eda-28b0-f7a67582c48f"    99.1100    Good
    09-Dec-2023 17:23:22 UTC    "Flynn I.Active Power Generated.4780df36-9354-5eda-28b0-f7a67582c48f"    95.3000    Good

You can see that the invalid data in rows 1, 2, and 3 is replaced with the correct data from the OPC UA server.

See Also

Functions

Topics