This example shows you how to read historical data from an OPC UA server. Specifically, this example reads data from a Prosys OPC UA Simulation Server v4.0.0 or later.
To run this example in your MATLAB session, you will need to install the Prosys OPC UA Simulation Server. Read the Getting Started section of the OPC Toolbox documentation for further information.
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'
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
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)]
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)]
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)]
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);