Work with Structure-Formatted Data
When Structures Are Used
Industrial Communication Toolbox™ software uses structures to return data from an OPC server, for the following operations:
Synchronous read operations, executed using the
read
function.Asynchronous read operations, executed using the
readasync
function.Data change events generated by the OPC server for all active, subscribed groups or through a
refresh
function call.Retrieving logged data in structure format from memory using the
getdata
orpeekdata
functions.
In all cases, the structure of the returned data is the same. This section describes that structure, and how you can use the structure data to understand OPC operations.
Perform a Read Operation on Multiple Items
To illustrate how to use structure-formatted data, the following example reads values from three items on the Matrikon™ OPC Simulation Server.
Step 1: Create OPC Group Objects
This example creates a hierarchy of OPC objects for the Matrikon Simulation Server. To run this example on your system, you must have the Matrikon Simulation Server installed. Alternatively, you can replace the values used in the creation of the objects with values for a server you can access.
da = opcda('localhost','Matrikon.OPC.Simulation.1'); connect(da); grp = addgroup(da,'StructExample'); itm1 = additem(grp,'Random.Real8'); itm2 = additem(grp,'Saw-toothed Waves.UInt2'); itm3 = additem(grp,'Random.Boolean');
Step 2: Read Data
This example reads values first from the device and then from the server cache. The data is returned in structure format.
r1 = read(grp, 'device'); r2 = read(grp);
Step 3: Interpret the Data
The data is returned in structure format. To interpret the data, you must extract the relevant information from the structures. In this example, you compare the Value, Quality, and TimeStamp to confirm that they are the same for both read operations.
disp({r1.ItemID;r1.Value;r2.Value}) disp({r1.ItemID;r1.Quality;r2.Quality}) disp({r1.ItemID;r1.TimeStamp;r2.TimeStamp})
Step 4: Read More Data
By reading first from the cache and then from the device, you can compare the returned data to see if any change has occurred. In this case, the data will not be the same.
r3 = read(grp); r4 = read(grp, `device'); disp({r3.ItemID;r3.Value;r4.Value})
Step 5: Clean Up
Always remove toolbox objects from memory, and the variables that reference them, when you no longer need them.
disconnect(da) delete(da) clear da grp itm1 itm2 itm3
Interpret Structure-Formatted Data
All data returned by the read
, opcread
, and
getdata
functions, and included in the data change and read
async event structures passed to callback functions, has the same underlying format.
The format is best explained by starting with the output from the
read
function, which provides the basic building block of
structure-formatted data.
Structure-Formatted Data for a Single Item
When you execute the read
function with a single
daitem
object, the following structure is
returned.
rSingle = read(itm1) rSingle = ItemID: 'Random.Real8' Value: 1.0440e+004 Quality: 'Good: Non-specific' TimeStamp: [2004 3 10 14 46 9.5310] Error: ''
All structure-formatted data for an item will contain the
ItemID
, Value
,
Quality
, and TimeStamp
fields.
Note
The Error
field in this example is specific to the
read
function, and is used to indicate any error
message the server generated for that item.
Structure-Formatted Data for Multiple Items
If you execute the read
function with a group object
containing more than one item, a structure array is returned.
rGroup = read(grp) rGroup = 3x1 struct array with fields: ItemID Value Quality TimeStamp Error
In this case, the structure array contains one element for each item that was
read. The ItemID
field in each element identifies the item
associated with that element of the structure array.
Note
When you perform asynchronous read operations, and for data change events, the order of the items in the structure array is determined by the OPC server. The order may not be the same as the order of the items passed to the read function.
Structure-Formatted Data for Events
Event structures contain information specifically about the event, as well as the data associated with that event.
The following example displays the contents of a read async event.
cleareventlog(da); tid = readasync(itm); % Wait for the read async event to occur pause(1); event = get(da, 'EventLog') event = Type: 'ReadAsync' Data: [1x1 struct]
The Data field of the event structure contains
event.Data ans = LocalEventTime: [2004 3 11 10 59 57.6710] TransID: 4 GroupName: 'StructExample' Items: [1x1 struct]
The Items field of the Data structure contains
event.Data.Items ans = ItemID: 'Random.Real8' Value: 9.7471e+003 Quality: 'Good: Non-specific' TimeStamp: [2004 3 11 10 59 57.6710]
From the example, you can see that the event structure embeds the
structure-formatted data in the Items
field of the
Data
structure associated with the event. Additional
fields of the Data
structure provide information on the
event, such as the source of the event, the time the event was received by the
toolbox, and the transaction ID of that event.
Structure-Formatted Data for a Logging Task
Industrial Communication Toolbox software logs data to memory and/or disk using the data change
event. When you return structure-formatted data for a logging task using the
opcread
or getdata
function, the returned
structure array contains the data change event information arranged in a
structure array. Each element of the structure array contains a
record, or data change event. The structure array has
the LocalEventTime
and Items
fields from
the data change event. The Items
field is in turn a structure
array containing the fields ItemID
, Value
,
Quality
, and TimeStamp
.
When to Use Structure-Formatted Data
For the read, read async and data change events, you must use structure-formatted data. However, for a logging task, you have the option of retrieving the data in structure format, or numeric or cell array format.
For a logging task, you should use structure-formatted data when you are interested in
The “raw” event information returned by the OPC server. The raw information may help in diagnosing the OPC server configuration or the client configuration. For example, if you see a data value that does not change frequently, yet you know that the device should be changing frequently, you can examine the structure-formatted data to determine when the OPC server notifies clients of a change in Value, Quality and/or TimeStamp.
Timing information rather than time series data. If you need to track when an operator changed the state of a switch, structure-formatted data provides you with event-based data rather than time series data.
For other tasks that involve time series data, such as visualization of the data,
analysis, modeling, and optimization operations, you should consider using the cell
or numeric array output format for getdata
and
opcread
. For more information on array formats, see Array-Formatted Data.
Convert Structure-Formatted Data to Array Format
If you retrieve data from memory or disk in structure format, you can convert the
resulting structure into array format using the opcstruct2array
function. You pass the structure array to the
function, and it will return the ItemID
,
Value
, Quality
, TimeStamp
,
and EventTime
information contained in that structure
array.
The opcstruct2array
function is particularly useful when you
want to visualize or analyze time series data without removing it from memory.
Because peekdata
only returns structure arrays
(due to speed considerations), you can use opcstruct2array
to
convert the contents of the structure data into separate arrays for visualization
and analysis purposes.
Note
You should always retrieve data in numeric or cell array format whenever you
only want to manipulate the time series data. Although the
opcstruct2array
function has been designed to use as
little memory as possible, conversion in MATLAB® software still requires storage space for both the structure array
and the resulting arrays.
For an example of using opcstruct2array
, see Write a Callback Function.