Main Content

Read Historical OPC UA Server Data

This example shows you how to read historical data from an OPC UA server.

This example reads data from a Prosys OPC UA Simulation Server v4.0.2. For other Prosys server versions, you might have to modify this code.

To run this example in your MATLAB® session, you must install and start the Prosys OPC UA Simulation Server. For further information, see the Getting Started section of the Industrial Communication Toolbox™ documentation.

Create a Client and Connect to the Server

You create client objects using the results of a query to the Local Discovery Service using opcuaserverinfo, or directly using the host name and port number of the server you are connecting to. In this case, connect directly to the OPC UA server on port 53530.

uaClient = opcua('localhost',53530);
connect(uaClient);
uaClient.Status
ans =

    'Connected'

Define Nodes to Read Historical Data

The Prosys OPC UA Simulation Server provides simulated signals for nodes in the "Simulation" branch. By default the Simulation Server updates the values each second. Define these nodes using the opcuanode function.

simNodeIds = {'Random';
                 'Triangle';
                 'Sinusoid'};
simNodes = opcuanode(3,simNodeIds,uaClient)
simNodes = 

1×3 OPC UA Node array:
    index    Name    NsInd  Identifier  NodeType
    -----  --------  -----  ----------  --------
      1    Random    3      Random      Variable
      2    Triangle  3      Triangle    Variable
      3    Sinusoid  3      Sinusoid    Variable

Read Historical Data from Nodes

Use the readHistory function to read the history of a node. You must pass a time range in which to read historical data. For the Prosys server, read the most recent 30 seconds of data.

dataSample = readHistory(uaClient,simNodes,datetime('now')-seconds(30),datetime('now'))
dataSample = 

1-by-3 OPC UA Data object array:

           Timestamp                   Random                     Triangle                    Sinusoid           
    -----------------------  --------------------------  --------------------------  --------------------------  
    2019-12-20 01:18:14.000        1.402465 [Good (Raw)]        0.266667 [Good (Raw)]        0.415823 [Good (Raw)]  
    2019-12-20 01:18:15.000        1.044139 [Good (Raw)]        0.000000 [Good (Raw)]        0.000000 [Good (Raw)]  
    2019-12-20 01:18:16.000       -1.857952 [Good (Raw)]       -0.266667 [Good (Raw)]       -0.415823 [Good (Raw)]  
    2019-12-20 01:18:17.000        1.783723 [Good (Raw)]       -0.533333 [Good (Raw)]       -0.813473 [Good (Raw)]  
    2019-12-20 01:18:18.000       -1.095435 [Good (Raw)]       -0.800000 [Good (Raw)]       -1.175570 [Good (Raw)]  
    2019-12-20 01:18:19.000       -1.178567 [Good (Raw)]       -1.066667 [Good (Raw)]       -1.486290 [Good (Raw)]  
    2019-12-20 01:18:20.000       -1.548359 [Good (Raw)]       -1.333333 [Good (Raw)]       -1.732051 [Good (Raw)]  
    2019-12-20 01:18:21.000       -0.438983 [Good (Raw)]       -1.600000 [Good (Raw)]       -1.902113 [Good (Raw)]  
    2019-12-20 01:18:22.000       -0.785842 [Good (Raw)]       -1.866667 [Good (Raw)]       -1.989044 [Good (Raw)]  
    2019-12-20 01:18:23.000        1.419149 [Good (Raw)]       -1.866667 [Good (Raw)]       -1.989044 [Good (Raw)]  
    2019-12-20 01:18:24.000        1.049357 [Good (Raw)]       -1.600000 [Good (Raw)]       -1.902113 [Good (Raw)]  
    2019-12-20 01:18:25.000       -1.932999 [Good (Raw)]       -1.333333 [Good (Raw)]       -1.732051 [Good (Raw)]  
    2019-12-20 01:18:26.000        1.720142 [Good (Raw)]       -1.066667 [Good (Raw)]       -1.486290 [Good (Raw)]  
    2019-12-20 01:18:27.000       -1.170482 [Good (Raw)]       -0.800000 [Good (Raw)]       -1.175571 [Good (Raw)]  
    2019-12-20 01:18:28.000       -1.540274 [Good (Raw)]       -0.533333 [Good (Raw)]       -0.813473 [Good (Raw)]  
    2019-12-20 01:18:29.000       -0.430899 [Good (Raw)]       -0.266667 [Good (Raw)]       -0.415823 [Good (Raw)]  
    2019-12-20 01:18:30.000       -0.869489 [Good (Raw)]       -0.000000 [Good (Raw)]       -0.000000 [Good (Raw)]  
    2019-12-20 01:18:31.000       -1.630916 [Good (Raw)]        0.266667 [Good (Raw)]        0.415823 [Good (Raw)]  
    2019-12-20 01:18:32.000        1.999292 [Good (Raw)]        0.533333 [Good (Raw)]        0.813473 [Good (Raw)]  
    2019-12-20 01:18:33.000       -0.891333 [Good (Raw)]        0.800000 [Good (Raw)]        1.175570 [Good (Raw)]  
    2019-12-20 01:18:34.000       -1.238192 [Good (Raw)]        1.066667 [Good (Raw)]        1.486290 [Good (Raw)]  
    2019-12-20 01:18:35.000       -0.220548 [Good (Raw)]        1.333333 [Good (Raw)]        1.732051 [Good (Raw)]  
    2019-12-20 01:18:36.000       -0.590339 [Good (Raw)]        1.600000 [Good (Raw)]        1.902113 [Good (Raw)]  
    2019-12-20 01:18:37.000        0.519036 [Good (Raw)]        1.866667 [Good (Raw)]        1.989044 [Good (Raw)]  
    2019-12-20 01:18:38.000        0.172177 [Good (Raw)]        1.866667 [Good (Raw)]        1.989044 [Good (Raw)]  
    2019-12-20 01:18:39.000       -0.589250 [Good (Raw)]        1.600000 [Good (Raw)]        1.902113 [Good (Raw)]  
    2019-12-20 01:18:40.000       -0.959042 [Good (Raw)]        1.333333 [Good (Raw)]        1.732051 [Good (Raw)]  
    2019-12-20 01:18:41.000        0.425527 [Good (Raw)]        1.066667 [Good (Raw)]        1.486290 [Good (Raw)]  
    2019-12-20 01:18:42.000        0.078668 [Good (Raw)]        0.800000 [Good (Raw)]        1.175571 [Good (Raw)]  
    2019-12-20 01:18:43.000        1.188043 [Good (Raw)]        0.533333 [Good (Raw)]        0.813473 [Good (Raw)]  

Read Historical Data at Specific Times

You can ask the server to retrieve data at specific times. If the server does not have an archived value for that specific time, an interpolated (or extrapolated) value is returned. Use the readAtTime function to retrieve data each minute for the last 10 minutes.

timesToReturn = datetime('now')-minutes(10):minutes(1):datetime('now');
dataRegular = readAtTime(uaClient,simNodes,timesToReturn)
dataRegular = 

1-by-3 OPC UA Data object array:

           Timestamp                   Random                     Triangle                    Sinusoid           
    -----------------------  --------------------------  --------------------------  --------------------------  
    2019-12-20 01:08:44.000       -0.083361 [Good (Raw)]        0.266667 [Good (Raw)]        0.415823 [Good (Raw)]  
    2019-12-20 01:09:44.000        0.043744 [Good (Raw)]        0.266667 [Good (Raw)]        0.415823 [Good (Raw)]  
    2019-12-20 01:10:44.000        1.199272 [Good (Raw)]        0.266667 [Good (Raw)]        0.415823 [Good (Raw)]  
    2019-12-20 01:11:44.000        1.259184 [Good (Raw)]        0.266667 [Good (Raw)]        0.415823 [Good (Raw)]  
    2019-12-20 01:12:44.000        0.193783 [Good (Raw)]        0.266667 [Good (Raw)]        0.415823 [Good (Raw)]  
    2019-12-20 01:13:44.000       -1.585967 [Good (Raw)]        0.266667 [Good (Raw)]        0.415823 [Good (Raw)]  
    2019-12-20 01:14:44.000        1.073438 [Good (Raw)]        0.266667 [Good (Raw)]        0.415823 [Good (Raw)]  
    2019-12-20 01:15:44.000        0.099768 [Good (Raw)]        0.266667 [Good (Raw)]        0.415823 [Good (Raw)]  
    2019-12-20 01:16:44.000       -1.368735 [Good (Raw)]        0.266667 [Good (Raw)]        0.415823 [Good (Raw)]  
    2019-12-20 01:17:44.000        1.791922 [Good (Raw)]        0.266667 [Good (Raw)]        0.415823 [Good (Raw)]  
    2019-12-20 01:18:44.000        0.818252 [Good (Raw)]        0.266667 [Good (Raw)]        0.415823 [Good (Raw)]  

Read Processed Data from the Server

OPC UA Servers provide aggregate functions for returning preprocessed data to clients. This is most useful when you need to query data over a large period of time.

Query the AggregateFunctions property of a connected client to find out what aggregate functions the server supports.

uaClient.AggregateFunctions
ans =

  14×1 cell array

    {'Interpolative'    }
    {'Average'          }
    {'Minimum'          }
    {'Maximum'          }
    {'MinimumActualTime'}
    {'MaximumActualTime'}
    {'Range'            }
    {'Count'            }
    {'Start'            }
    {'End'              }
    {'Delta'            }
    {'WorstQuality'     }
    {'StartBound'       }
    {'EndBound'         }

Read the Average value for each 30 second period over the last 10 minutes.

dataAverage = readProcessed(uaClient,simNodes,'Average',seconds(30),datetime('now')-minutes(10),datetime('now'))
dataAverage = 

1-by-3 OPC UA Data object array:

           Timestamp                      Random                            Triangle                           Sinusoid               
    -----------------------  ---------------------------------  ---------------------------------  ---------------------------------  
    2019-12-20 01:08:44.000       -0.008396 [Good (Calculated)]       -0.000000 [Good (Calculated)]        0.000000 [Good (Calculated)]  
    2019-12-20 01:09:14.000        0.071422 [Good (Calculated)]       -0.000000 [Good (Calculated)]       -0.000000 [Good (Calculated)]  
    2019-12-20 01:09:44.000        0.034084 [Good (Calculated)]       -0.000000 [Good (Calculated)]       -0.000000 [Good (Calculated)]  
    2019-12-20 01:10:14.000        0.190256 [Good (Calculated)]       -0.000000 [Good (Calculated)]        0.000000 [Good (Calculated)]  
    2019-12-20 01:10:44.000        0.088148 [Good (Calculated)]       -0.000000 [Good (Calculated)]       -0.000000 [Good (Calculated)]  
    2019-12-20 01:11:14.000        0.065122 [Good (Calculated)]        0.000000 [Good (Calculated)]       -0.000000 [Good (Calculated)]  
    2019-12-20 01:11:44.000       -0.057444 [Good (Calculated)]        0.000000 [Good (Calculated)]        0.000000 [Good (Calculated)]  
    2019-12-20 01:12:14.000       -0.047782 [Good (Calculated)]        0.000000 [Good (Calculated)]       -0.000000 [Good (Calculated)]  
    2019-12-20 01:12:44.000        0.253328 [Good (Calculated)]        0.000000 [Good (Calculated)]       -0.000000 [Good (Calculated)]  
    2019-12-20 01:13:14.000       -0.018746 [Good (Calculated)]        0.000000 [Good (Calculated)]        0.000000 [Good (Calculated)]  
    2019-12-20 01:13:44.000        0.103775 [Good (Calculated)]        0.000000 [Good (Calculated)]       -0.000000 [Good (Calculated)]  
    2019-12-20 01:14:14.000        0.010857 [Good (Calculated)]        0.000000 [Good (Calculated)]       -0.000000 [Good (Calculated)]  
    2019-12-20 01:14:44.000       -0.370672 [Good (Calculated)]        0.000000 [Good (Calculated)]        0.000000 [Good (Calculated)]  
    2019-12-20 01:15:14.000       -0.198687 [Good (Calculated)]       -0.000000 [Good (Calculated)]       -0.000000 [Good (Calculated)]  
    2019-12-20 01:15:44.000       -0.025481 [Good (Calculated)]       -0.000000 [Good (Calculated)]       -0.000000 [Good (Calculated)]  
    2019-12-20 01:16:14.000        0.067565 [Good (Calculated)]       -0.000000 [Good (Calculated)]        0.000000 [Good (Calculated)]  
    2019-12-20 01:16:44.000        0.085904 [Good (Calculated)]       -0.000000 [Good (Calculated)]       -0.000000 [Good (Calculated)]  
    2019-12-20 01:17:14.000        0.018061 [Good (Calculated)]       -0.000000 [Good (Calculated)]       -0.000000 [Good (Calculated)]  
    2019-12-20 01:17:44.000       -0.033414 [Good (Calculated)]       -0.000000 [Good (Calculated)]        0.000000 [Good (Calculated)]  
    2019-12-20 01:18:14.000       -0.205573 [Good (Calculated)]       -0.000000 [Good (Calculated)]       -0.000000 [Good (Calculated)]  

Read the Average value for each half second period over the last 5 seconds. Note how the quality of the data includes Good quality, and Bad quality where there is no data available to perform the calculation.

dataMixedQuality = readProcessed(uaClient,simNodes,'Average',seconds(0.5),datetime('now')-seconds(5),datetime('now'))
dataMixedQuality = 

1-by-3 OPC UA Data object array:

           Timestamp                      Random                            Triangle                           Sinusoid               
    -----------------------  ---------------------------------  ---------------------------------  ---------------------------------  
    2019-12-20 01:18:39.000        0.000000 [Bad:NoData (Raw)]         0.000000 [Bad:NoData (Raw)]         0.000000 [Bad:NoData (Raw)]   
    2019-12-20 01:18:39.500       -0.589250 [Good (Calculated)]        1.600000 [Good (Calculated)]        1.902113 [Good (Calculated)]  
    2019-12-20 01:18:40.000        0.000000 [Bad:NoData (Raw)]         0.000000 [Bad:NoData (Raw)]         0.000000 [Bad:NoData (Raw)]   
    2019-12-20 01:18:40.500       -0.959042 [Good (Calculated)]        1.333333 [Good (Calculated)]        1.732051 [Good (Calculated)]  
    2019-12-20 01:18:41.000        0.000000 [Bad:NoData (Raw)]         0.000000 [Bad:NoData (Raw)]         0.000000 [Bad:NoData (Raw)]   
    2019-12-20 01:18:41.500        0.425527 [Good (Calculated)]        1.066667 [Good (Calculated)]        1.486290 [Good (Calculated)]  
    2019-12-20 01:18:42.000        0.000000 [Bad:NoData (Raw)]         0.000000 [Bad:NoData (Raw)]         0.000000 [Bad:NoData (Raw)]   
    2019-12-20 01:18:42.500        0.078668 [Good (Calculated)]        0.800000 [Good (Calculated)]        1.175571 [Good (Calculated)]  
    2019-12-20 01:18:43.000        0.000000 [Bad:NoData (Raw)]         0.000000 [Bad:NoData (Raw)]         0.000000 [Bad:NoData (Raw)]   
    2019-12-20 01:18:43.500        1.188043 [Good (Calculated)]        0.533333 [Good (Calculated)]        0.813473 [Good (Calculated)]  

Filter the quality of the data to return only the Good data.

dataGood = filterByQuality(dataMixedQuality,'good')
dataGood = 

1-by-3 OPC UA Data object array:

           Timestamp                      Random                            Triangle                           Sinusoid               
    -----------------------  ---------------------------------  ---------------------------------  ---------------------------------  
    2019-12-20 01:18:39.500       -0.589250 [Good (Calculated)]        1.600000 [Good (Calculated)]        1.902113 [Good (Calculated)]  
    2019-12-20 01:18:40.500       -0.959042 [Good (Calculated)]        1.333333 [Good (Calculated)]        1.732051 [Good (Calculated)]  
    2019-12-20 01:18:41.500        0.425527 [Good (Calculated)]        1.066667 [Good (Calculated)]        1.486290 [Good (Calculated)]  
    2019-12-20 01:18:42.500        0.078668 [Good (Calculated)]        0.800000 [Good (Calculated)]        1.175571 [Good (Calculated)]  
    2019-12-20 01:18:43.500        1.188043 [Good (Calculated)]        0.533333 [Good (Calculated)]        0.813473 [Good (Calculated)]  

Disconnect from Server

When you have finished communicating with the server, disconnect the client from the server. This is also automatically performed when the client variable goes out of scope in MATLAB®.

disconnect(uaClient);