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 2015-04-22 09:01:30 3 unique qualities Float 12 single values 2015-04-22 09:00:02 2015-04-22 09:01:30 3 unique qualities Int32 12 int32 values 2015-04-22 09:00:02 2015-04-22 09:01:30 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. Since 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 10.000000 [Good (Raw)] 10 [Good (Raw)] 2015-04-22 09:00:25 20.000000 [Good (Raw)] 20 [Good (Raw)] 2015-04-22 09:00:28 25.000000 [Good (Raw)] 25 [Good (Raw)] 2015-04-22 09:00:40 30.000000 [Good (Raw)] 30 [Good (Raw)] 2015-04-22 09:00:42 0.000000 [Bad (Raw)] 0 [Bad (Raw)] 2015-04-22 09:00:48 4.000000 [Good (Raw)] 40 [Good (Raw)] 2015-04-22 09:00:52 50.000000 [Good (Raw)] 50 [Good (Raw)] 2015-04-22 09:01:12 60.000000 [Good (Raw)] 60 [Good (Raw)] 2015-04-22 09:01:17 70.000000 [Uncertain (Raw)] 70 [Uncertain (Raw)] 2015-04-22 09:01:23 70.000000 [Good (Raw)] 70 [Good (Raw)] 2015-04-22 09:01:26 80.000000 [Good (Raw)] 80 [Good (Raw)] 2015-04-22 09:01:30 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 40.000000 [Bad (Raw)] 30.000000 [Good (Raw)] 30 [Good (Raw)] 2015-04-22 09:01:30 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 12:30:02 2.000000 [Uncertain:Subnormal (Interpolated)] 10.000000 [Good (Raw)] 10 [Good (Raw)] 2015-04-22 12:30:10 10.000000 [Good (Raw)] 13.478261 [Good (Interpolated)] 13 [Good (Interpolated)] 2015-04-22 12:30:20 20.000000 [Good (Raw)] 17.826086 [Good (Interpolated)] 18 [Good (Interpolated)] 2015-04-22 12:30:25 25.000000 [Good (Interpolated)] 20.000000 [Good (Raw)] 20 [Good (Raw)] 2015-04-22 12:30:28 28.000000 [Good (Interpolated)] 25.000000 [Good (Raw)] 25 [Good (Raw)] 2015-04-22 12:30:30 30.000000 [Good (Raw)] 25.833334 [Good (Interpolated)] 26 [Good (Interpolated)] 2015-04-22 12:30:40 40.000000 [Bad (Raw)] 30.000000 [Good (Raw)] 30 [Good (Raw)] 2015-04-22 12:30:42 42.000000 [Good (Interpolated)] 0.000000 [Bad (Raw)] 0 [Bad (Raw)] 2015-04-22 12:30:48 48.000000 [Good (Interpolated)] 4.000000 [Good (Raw)] 40 [Good (Raw)] 2015-04-22 12:30:50 50.000000 [Good (Raw)] 27.000000 [Good (Interpolated)] 45 [Good (Interpolated)] 2015-04-22 12:30:52 52.000000 [Good (Interpolated)] 50.000000 [Good (Raw)] 50 [Good (Raw)] 2015-04-22 12:31:00 60.000000 [Good (Raw)] 54.000000 [Good (Interpolated)] 54 [Good (Interpolated)] 2015-04-22 12:31:10 70.000000 [Uncertain (Raw)] 59.000000 [Good (Interpolated)] 59 [Good (Interpolated)] 2015-04-22 12:31:12 72.000000 [Good (Interpolated)] 60.000000 [Good (Raw)] 60 [Good (Raw)] 2015-04-22 12:31:17 77.000000 [Good (Interpolated)] 70.000000 [Uncertain (Raw)] 70 [Uncertain (Raw)] 2015-04-22 12:31:20 80.000000 [Good (Raw)] 70.000000 [Good (Interpolated)] 70 [Good (Interpolated)] 2015-04-22 12:31:23 83.000000 [Good (Interpolated)] 70.000000 [Good (Raw)] 70 [Good (Raw)] 2015-04-22 12:31:26 86.000000 [Good (Interpolated)] 80.000000 [Good (Raw)] 80 [Good (Raw)] 2015-04-22 12:31:30 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 on plot(dataIntersect, 'Marker','o', 'LineStyle','none'); title('Intersection of time series in Data object'); subplot(2,1,2); plot(dataSample, 'Marker','.'); hold on 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 on plot(dataResampled, 'Marker','x', 'Linestyle','none');
dataResampled = 1-by-3 OPC UA Data object array: Timestamp Double Float Int32 ------------------- ----------------------------------- ----------------------------------- ------------------------------------ 2015-04-22 12:30:10 10.000000 [Good (Raw)] 13.478261 [Good (Interpolated)] 13 [Good (Interpolated)] 2015-04-22 12:30:15 15.000000 [Good (Interpolated)] 15.652174 [Good (Interpolated)] 16 [Good (Interpolated)] 2015-04-22 12:30:20 20.000000 [Good (Raw)] 17.826086 [Good (Interpolated)] 18 [Good (Interpolated)] 2015-04-22 12:30:25 25.000000 [Good (Interpolated)] 20.000000 [Good (Raw)] 20 [Good (Raw)] 2015-04-22 12:30:30 30.000000 [Good (Raw)] 25.833334 [Good (Interpolated)] 26 [Good (Interpolated)] 2015-04-22 12:30:35 35.000000 [Good (Interpolated)] 27.916666 [Good (Interpolated)] 28 [Good (Interpolated)] 2015-04-22 12:30:40 40.000000 [Bad (Raw)] 30.000000 [Good (Raw)] 30 [Good (Raw)] 2015-04-22 12:30:45 45.000000 [Good (Interpolated)] 2.000000 [Good (Interpolated)] 20 [Good (Interpolated)] 2015-04-22 12:30:50 50.000000 [Good (Raw)] 27.000000 [Good (Interpolated)] 45 [Good (Interpolated)] 2015-04-22 12:30:55 55.000000 [Good (Interpolated)] 51.500000 [Good (Interpolated)] 52 [Good (Interpolated)] 2015-04-22 12:31:00 60.000000 [Good (Raw)] 54.000000 [Good (Interpolated)] 54 [Good (Interpolated)] 2015-04-22 12:31:05 65.000000 [Good (Interpolated)] 56.500000 [Good (Interpolated)] 57 [Good (Interpolated)] 2015-04-22 12:31:10 70.000000 [Uncertain (Raw)] 59.000000 [Good (Interpolated)] 59 [Good (Interpolated)] 2015-04-22 12:31:15 75.000000 [Good (Interpolated)] 66.000000 [Good (Interpolated)] 66 [Good (Interpolated)] 2015-04-22 12:31:20 80.000000 [Good (Raw)] 70.000000 [Good (Interpolated)] 70 [Good (Interpolated)] 2015-04-22 12:31:25 85.000000 [Good (Interpolated)] 76.666664 [Good (Interpolated)] 77 [Good (Interpolated)] 2015-04-22 12:31:30 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 12:30:10 13.478261 [Good (Interpolated)] 2015-04-22 12:30:15 15.652174 [Good (Interpolated)] 2015-04-22 12:30:20 17.826086 [Good (Interpolated)] 2015-04-22 12:30:25 20.000000 [Good (Raw)] 2015-04-22 12:30:30 25.833334 [Good (Interpolated)] 2015-04-22 12:30:35 27.916666 [Good (Interpolated)] 2015-04-22 12:30:40 30.000000 [Good (Raw)] 2015-04-22 12:30:45 2.000000 [Good (Interpolated)] 2015-04-22 12:30:50 27.000000 [Good (Interpolated)] 2015-04-22 12:30:55 51.500000 [Good (Interpolated)] 2015-04-22 12:31:00 54.000000 [Good (Interpolated)] 2015-04-22 12:31:05 56.500000 [Good (Interpolated)] 2015-04-22 12:31:10 59.000000 [Good (Interpolated)] 2015-04-22 12:31:15 66.000000 [Good (Interpolated)] 2015-04-22 12:31:20 70.000000 [Good (Interpolated)] 2015-04-22 12:31:25 76.666664 [Good (Interpolated)] 2015-04-22 12:31:30 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 12:30:10 13.478261 [Good (Interpolated)] 2015-04-22 12:30:15 15.652174 [Good (Interpolated)] 2015-04-22 12:30:20 17.826086 [Good (Interpolated)] 2015-04-22 12:30:30 25.833334 [Good (Interpolated)] 2015-04-22 12:30:35 27.916666 [Good (Interpolated)] 2015-04-22 12:30:45 2.000000 [Good (Interpolated)] 2015-04-22 12:30:50 27.000000 [Good (Interpolated)] 2015-04-22 12:30:55 51.500000 [Good (Interpolated)] 2015-04-22 12:31:00 54.000000 [Good (Interpolated)] 2015-04-22 12:31:05 56.500000 [Good (Interpolated)] 2015-04-22 12:31:10 59.000000 [Good (Interpolated)] 2015-04-22 12:31:15 66.000000 [Good (Interpolated)] 2015-04-22 12:31:20 70.000000 [Good (Interpolated)] 2015-04-22 12:31:25 76.666664 [Good (Interpolated)]