Visualize and Preprocess OPC UA Data
This example shows you how to work with OPC UA Data objects.
You create OPC UA Data objects when you read historical data from an OPC UA server. OPC UA Data objects allow you to store, visualize, and manipulate historical data before converting that data to builtin data types for further processing in MATLAB®.
For more information on generating OPC UA Data objects, see the example Read Historical OPC UA Server Data.
Load Sample OPC UA Data Set
Load the sample data into the workspace.
load demoUA_SampleData
Display OPC UA Data Objects
Examine the workspace to see what variables have been loaded.
whos
Name Size Bytes Class Attributes dataSample 1x3 5459 opc.ua.Data
Display a summary of the sample data.
summary(dataSample)
1-by-3 OPC UA Data object: Name Value Start Timestamp End Timestamp Quality ------ ---------------- ----------------------- ----------------------- ------------------ Double 9 double values 2015-04-22 09:00:10.000 2015-04-22 09:01:30.000 3 unique qualities Float 12 single values 2015-04-22 09:00:02.000 2015-04-22 09:01:30.000 3 unique qualities Int32 12 int32 values 2015-04-22 09:00:02.000 2015-04-22 09:01:30.000 3 unique qualities
The data object contains three data sets. The first element Double
contains 9 values, the second and third have 12 values each.
See whether the Float
and Int32
data sets have the same timestamp.
arrayHasSameTimestamp(dataSample(2:3))
ans = logical 1
Display the Float
and Int32
data sets together. Because all the elements have the same timestamp, a table of values can be displayed.
dataSample(2:3)
ans = 1-by-2 OPC UA Data object array: Timestamp Float Int32 ----------------------- ------------------------------- -------------------------------- 2015-04-22 09:00:02.000 10.000000 [Good (Raw)] 10 [Good (Raw)] 2015-04-22 09:00:25.000 20.000000 [Good (Raw)] 20 [Good (Raw)] 2015-04-22 09:00:28.000 25.000000 [Good (Raw)] 25 [Good (Raw)] 2015-04-22 09:00:40.000 30.000000 [Good (Raw)] 30 [Good (Raw)] 2015-04-22 09:00:42.000 0.000000 [Bad (Raw)] 0 [Bad (Raw)] 2015-04-22 09:00:48.000 4.000000 [Good (Raw)] 40 [Good (Raw)] 2015-04-22 09:00:52.000 50.000000 [Good (Raw)] 50 [Good (Raw)] 2015-04-22 09:01:12.000 60.000000 [Good (Raw)] 60 [Good (Raw)] 2015-04-22 09:01:17.000 70.000000 [Uncertain (Raw)] 70 [Uncertain (Raw)] 2015-04-22 09:01:23.000 70.000000 [Good (Raw)] 70 [Good (Raw)] 2015-04-22 09:01:26.000 80.000000 [Good (Raw)] 80 [Good (Raw)] 2015-04-22 09:01:30.000 90.000000 [Good (Raw)] 90 [Good (Raw)]
Change the Date Display Format
Get the current date display format using opc.getDateDisplayFormat
.
origFormat = opc.getDateDisplayFormat;
Change the display format to standard US date format and display the value again.
opc.setDateDisplayFormat('mm/dd/yyyy HH:MM AM');
dataSample(2:3)
ans = 1-by-2 OPC UA Data object array: Timestamp Float Int32 ------------------- ------------------------------- -------------------------------- 04/22/2015 9:00 AM 10.000000 [Good (Raw)] 10 [Good (Raw)] 04/22/2015 9:00 AM 20.000000 [Good (Raw)] 20 [Good (Raw)] 04/22/2015 9:00 AM 25.000000 [Good (Raw)] 25 [Good (Raw)] 04/22/2015 9:00 AM 30.000000 [Good (Raw)] 30 [Good (Raw)] 04/22/2015 9:00 AM 0.000000 [Bad (Raw)] 0 [Bad (Raw)] 04/22/2015 9:00 AM 4.000000 [Good (Raw)] 40 [Good (Raw)] 04/22/2015 9:00 AM 50.000000 [Good (Raw)] 50 [Good (Raw)] 04/22/2015 9:01 AM 60.000000 [Good (Raw)] 60 [Good (Raw)] 04/22/2015 9:01 AM 70.000000 [Uncertain (Raw)] 70 [Uncertain (Raw)] 04/22/2015 9:01 AM 70.000000 [Good (Raw)] 70 [Good (Raw)] 04/22/2015 9:01 AM 80.000000 [Good (Raw)] 80 [Good (Raw)] 04/22/2015 9:01 AM 90.000000 [Good (Raw)] 90 [Good (Raw)]
Reset the display format to the default.
opc.setDateDisplayFormat('default')
ans = 'yyyy-mm-dd HH:MM:SS.FFF'
Reset the display format to the original value.
opc.setDateDisplayFormat(origFormat);
Visualize OPC UA Data
Visualize OPC UA Data using the plot
and stairs
function on the data object.
figure; axH1 = subplot(2,1,1); plot(dataSample); title('Plot of sample data'); axH2 = subplot(2,1,2); stairs(dataSample); title('Stairstep plot of sample data'); legend('Location', 'NorthWest')
Resample OPC UA Data
The data in the dataSample
set has different timestamps.
arrayHasSameTimestamp(dataSample)
ans = logical 0
Attempt to convert the data to a double array. The conversion will fail.
try vals = double(dataSample); catch exc disp(exc.message) end
Conversion to double failed. All elements of the OPC Data object must have the same time stamp. Consider using 'TSUNION', 'TSINTERSECT' or 'RESAMPLE' on the Data object.
The intersection of the data timestamps results in a smaller data set containing the common timestamps from all elements.
dataIntersect = tsintersect(dataSample)
dataIntersect = 1-by-3 OPC UA Data object array: Timestamp Double Float Int32 ----------------------- -------------------------- -------------------------- --------------------------- 2015-04-22 09:00:40.000 40.000000 [Bad (Raw)] 30.000000 [Good (Raw)] 30 [Good (Raw)] 2015-04-22 09:01:30.000 90.000000 [Good (Raw)] 90.000000 [Good (Raw)] 90 [Good (Raw)]
Convert the data object into a double array.
vals = double(dataIntersect)
vals = 40 30 30 90 90 90
Use tsunion
to return the union of time series in a Data object. New values are interpolated using the method supplied (or linear interpolation if no method is supplied). The quality is set to "Interpolated" for those new values.
dataUnion = tsunion(dataSample)
dataUnion = 1-by-3 OPC UA Data object array: Timestamp Double Float Int32 ----------------------- -------------------------------------------------- ----------------------------------- ------------------------------------ 2015-04-22 03:00:02.000 2.000000 [Uncertain:Subnormal (Interpolated)] 10.000000 [Good (Raw)] 10 [Good (Raw)] 2015-04-22 03:00:10.000 10.000000 [Good (Raw)] 13.478261 [Good (Interpolated)] 13 [Good (Interpolated)] 2015-04-22 03:00:20.000 20.000000 [Good (Raw)] 17.826086 [Good (Interpolated)] 18 [Good (Interpolated)] 2015-04-22 03:00:25.000 25.000000 [Good (Interpolated)] 20.000000 [Good (Raw)] 20 [Good (Raw)] 2015-04-22 03:00:28.000 28.000000 [Good (Interpolated)] 25.000000 [Good (Raw)] 25 [Good (Raw)] 2015-04-22 03:00:30.000 30.000000 [Good (Raw)] 25.833334 [Good (Interpolated)] 26 [Good (Interpolated)] 2015-04-22 03:00:40.000 40.000000 [Bad (Raw)] 30.000000 [Good (Raw)] 30 [Good (Raw)] 2015-04-22 03:00:42.000 42.000000 [Good (Interpolated)] 0.000000 [Bad (Raw)] 0 [Bad (Raw)] 2015-04-22 03:00:48.000 48.000000 [Good (Interpolated)] 4.000000 [Good (Raw)] 40 [Good (Raw)] 2015-04-22 03:00:50.000 50.000000 [Good (Raw)] 27.000000 [Good (Interpolated)] 45 [Good (Interpolated)] 2015-04-22 03:00:52.000 52.000000 [Good (Interpolated)] 50.000000 [Good (Raw)] 50 [Good (Raw)] 2015-04-22 03:01:00.000 60.000000 [Good (Raw)] 54.000000 [Good (Interpolated)] 54 [Good (Interpolated)] 2015-04-22 03:01:10.000 70.000000 [Uncertain (Raw)] 59.000000 [Good (Interpolated)] 59 [Good (Interpolated)] 2015-04-22 03:01:12.000 72.000000 [Good (Interpolated)] 60.000000 [Good (Raw)] 60 [Good (Raw)] 2015-04-22 03:01:17.000 77.000000 [Good (Interpolated)] 70.000000 [Uncertain (Raw)] 70 [Uncertain (Raw)] 2015-04-22 03:01:20.000 80.000000 [Good (Raw)] 70.000000 [Good (Interpolated)] 70 [Good (Interpolated)] 2015-04-22 03:01:23.000 83.000000 [Good (Interpolated)] 70.000000 [Good (Raw)] 70 [Good (Raw)] 2015-04-22 03:01:26.000 86.000000 [Good (Interpolated)] 80.000000 [Good (Raw)] 80 [Good (Raw)] 2015-04-22 03:01:30.000 90.000000 [Good (Raw)] 90.000000 [Good (Raw)] 90 [Good (Raw)]
Plot the data with markers to show how the methods work.
figure; subplot(2,1,1); plot(dataSample, 'Marker','.'); hold all plot(dataIntersect, 'Marker','o', 'LineStyle','none'); title('Intersection of time series in Data object'); subplot(2,1,2); plot(dataSample, 'Marker','.'); hold all plot(dataUnion, 'Marker','o', 'LineStyle','--'); title('Union of time series in Data object');
Resample the small data set at specified time steps.
newTS = dataSample(1).Timestamp(1):seconds(5):dataSample(1).Timestamp(end); dataResampled = resample(dataSample,newTS) figure; plot(dataSample); hold all plot(dataResampled, 'Marker','x', 'Linestyle','none');
dataResampled = 1-by-3 OPC UA Data object array: Timestamp Double Float Int32 ----------------------- ----------------------------------- ----------------------------------- ------------------------------------ 2015-04-22 03:00:10.000 10.000000 [Good (Raw)] 13.478261 [Good (Interpolated)] 13 [Good (Interpolated)] 2015-04-22 03:00:15.000 15.000000 [Good (Interpolated)] 15.652174 [Good (Interpolated)] 16 [Good (Interpolated)] 2015-04-22 03:00:20.000 20.000000 [Good (Raw)] 17.826086 [Good (Interpolated)] 18 [Good (Interpolated)] 2015-04-22 03:00:25.000 25.000000 [Good (Interpolated)] 20.000000 [Good (Raw)] 20 [Good (Raw)] 2015-04-22 03:00:30.000 30.000000 [Good (Raw)] 25.833334 [Good (Interpolated)] 26 [Good (Interpolated)] 2015-04-22 03:00:35.000 35.000000 [Good (Interpolated)] 27.916666 [Good (Interpolated)] 28 [Good (Interpolated)] 2015-04-22 03:00:40.000 40.000000 [Bad (Raw)] 30.000000 [Good (Raw)] 30 [Good (Raw)] 2015-04-22 03:00:45.000 45.000000 [Good (Interpolated)] 2.000000 [Good (Interpolated)] 20 [Good (Interpolated)] 2015-04-22 03:00:50.000 50.000000 [Good (Raw)] 27.000000 [Good (Interpolated)] 45 [Good (Interpolated)] 2015-04-22 03:00:55.000 55.000000 [Good (Interpolated)] 51.500000 [Good (Interpolated)] 52 [Good (Interpolated)] 2015-04-22 03:01:00.000 60.000000 [Good (Raw)] 54.000000 [Good (Interpolated)] 54 [Good (Interpolated)] 2015-04-22 03:01:05.000 65.000000 [Good (Interpolated)] 56.500000 [Good (Interpolated)] 57 [Good (Interpolated)] 2015-04-22 03:01:10.000 70.000000 [Uncertain (Raw)] 59.000000 [Good (Interpolated)] 59 [Good (Interpolated)] 2015-04-22 03:01:15.000 75.000000 [Good (Interpolated)] 66.000000 [Good (Interpolated)] 66 [Good (Interpolated)] 2015-04-22 03:01:20.000 80.000000 [Good (Raw)] 70.000000 [Good (Interpolated)] 70 [Good (Interpolated)] 2015-04-22 03:01:25.000 85.000000 [Good (Interpolated)] 76.666664 [Good (Interpolated)] 77 [Good (Interpolated)] 2015-04-22 03:01:30.000 90.000000 [Good (Raw)] 90.000000 [Good (Raw)] 90 [Good (Raw)]
Filter Data by Quality
Find only the Good data from the second element of resampled data set.
resampledGood = filterByQuality(dataResampled(2), 'good')
resampledGood = 1-by-1 OPC UA Data object array: Timestamp Float ----------------------- ----------------------------------- 2015-04-22 03:00:10.000 13.478261 [Good (Interpolated)] 2015-04-22 03:00:15.000 15.652174 [Good (Interpolated)] 2015-04-22 03:00:20.000 17.826086 [Good (Interpolated)] 2015-04-22 03:00:25.000 20.000000 [Good (Raw)] 2015-04-22 03:00:30.000 25.833334 [Good (Interpolated)] 2015-04-22 03:00:35.000 27.916666 [Good (Interpolated)] 2015-04-22 03:00:40.000 30.000000 [Good (Raw)] 2015-04-22 03:00:45.000 2.000000 [Good (Interpolated)] 2015-04-22 03:00:50.000 27.000000 [Good (Interpolated)] 2015-04-22 03:00:55.000 51.500000 [Good (Interpolated)] 2015-04-22 03:01:00.000 54.000000 [Good (Interpolated)] 2015-04-22 03:01:05.000 56.500000 [Good (Interpolated)] 2015-04-22 03:01:10.000 59.000000 [Good (Interpolated)] 2015-04-22 03:01:15.000 66.000000 [Good (Interpolated)] 2015-04-22 03:01:20.000 70.000000 [Good (Interpolated)] 2015-04-22 03:01:25.000 76.666664 [Good (Interpolated)] 2015-04-22 03:01:30.000 90.000000 [Good (Raw)]
Filter the second element of the resampled data to return only the Interpolated data. Visualize the filtered data with the original.
resampledInterpolated = filterByQuality(dataResampled(2), 'Origin','interpolated') figure; plot(dataResampled(2)) hold on plot(resampledGood, 'Marker', '+', 'Linestyle','none', 'DisplayName', 'Good'); plot(resampledInterpolated, 'Marker','x', 'Linestyle','none', 'DisplayName', 'Interpolated'); legend('Location', 'NorthWest')
resampledInterpolated = 1-by-1 OPC UA Data object array: Timestamp Float ----------------------- ----------------------------------- 2015-04-22 03:00:10.000 13.478261 [Good (Interpolated)] 2015-04-22 03:00:15.000 15.652174 [Good (Interpolated)] 2015-04-22 03:00:20.000 17.826086 [Good (Interpolated)] 2015-04-22 03:00:30.000 25.833334 [Good (Interpolated)] 2015-04-22 03:00:35.000 27.916666 [Good (Interpolated)] 2015-04-22 03:00:45.000 2.000000 [Good (Interpolated)] 2015-04-22 03:00:50.000 27.000000 [Good (Interpolated)] 2015-04-22 03:00:55.000 51.500000 [Good (Interpolated)] 2015-04-22 03:01:00.000 54.000000 [Good (Interpolated)] 2015-04-22 03:01:05.000 56.500000 [Good (Interpolated)] 2015-04-22 03:01:10.000 59.000000 [Good (Interpolated)] 2015-04-22 03:01:15.000 66.000000 [Good (Interpolated)] 2015-04-22 03:01:20.000 70.000000 [Good (Interpolated)] 2015-04-22 03:01:25.000 76.666664 [Good (Interpolated)]