17.4. Data Organization

The OPC DataHub offers a hierarchical system to organize your data. The hierarchy is separate from the actual data. It contains points, but is not made up of data, per se. You specify the data model, similar to specifying a class in a programming language, and then you create zero or more instances of that data model. The data hierarchy can be viewed in the left-hand pane of the Data Browser window.

17.4.1. Data Domains

The highest level of the data hierarchy is the data domain. You can create as many data domains as you need, and use them to separate data by user, function, or any other criteria. Points in different data domains can have the same name because each data domain creates a separate namespace. Two data domains you are probably familiar with are default, the default data domain, and DataSim which holds data from DataSim. All the data domains in the DataHub are listed in the General option of the Properties window.

The written syntax used by the DataHub to denote data domains and points is:

domain:point

In many cases, this is the only level of data organization you will ever need. However, should you desire a more sophisticated way to structure your data, the DataHub provides a way.

17.4.2. Assemblies, Subassemblies, Attributes, and Properties

Within a data domain, data can be arranged hierarchically as assemblies, subassemblies, attributes, and properties. Each assembly can have zero or more attributes and zero or more subassemblies, and each attribute can have zero or more properties. Subassemblies can have subassemblies. You can think of assemblies and subassemblies as branches in a tree, and attributes as the leaves. Here is an example of what a tree might look like:

Data Domain
    Assembly
        Subassembly (zero or more)
            Attribute  (zero or more)
                Property  (zero or more)
        Attribute...
        Attribute...
        Attribute...
            Property...
            Property...
            Property...
        Subassembly
            Subassembly
                Attribute...
                  Property...
                  Property...
            Attribute...
            Attribute...
                Property...
    Assembly...

and so on.

The written syntax for all of these levels uses a dot (.) to divide the names, rather than a colon that was used for the data domain name. Hence, the syntax of point in a property in an attribute in a subassembly in an assembly in a data domain would be:

domain:assembly.subassembly.attribute.property

Properties describe the attributes in more detail. An attribute can have a default property such that if you interact with the attribute point directly you will in fact be interacting with its default property. For example, an item might be plant.temperature, with properties value, highlimit, units. This would create 4 tags:

plant.temperature
plant.temperature.highlimit
plant.temperature.units
plant.temperature.value

The tags:

plant.temperature
plant.temperature.value

are aliases of one another. Both refer to the default property of plant.temperature. If you specify no property at all for an item, the item takes on the default property.

17.4.3. Attributes and Types

It is common for attributes to contain the same type of information. For example, all temperatures in a system are likely to share units, high alarm level, and value. To avoid repeating this information for each and every temperature in the system, we use a type. A type is the prototype, or class, of an attribute. You define a type and its properties first, and then define attributes of that type on assemblies. When the assembly is instantiated, its attributes are instantiated by creating an attribute and then assigning the properties to it that are associated with the attribute's type.

There is an alternative to using types and attributes as described here, a private attribute. A private attribute provides a one-command (private_attribute) means of creating an attribute on an assembly without having to define a type. This prevents the attribute properties from being shared across more than one attribute in the assembly or in other assemblies, but is easier to use when defining simple hierarchies. (See Example 2.)

17.4.4. Example 1: Attributes and Types

Suppose we want to create a hierarchical data model like this: We have a control system consisting of process areas, that we will call "Plants". Each plant contains 2 boilers, and each boiler has a pump and 2 valves. Each boiler measures temperature, pressure and level. Each pump measures speed, on/off state and operating temperature. There are two types of valves - a normal one that only measures position, and another that also verifies that it has power applied to it. Temperatures have a value and a high alarm limit.

The sample file plant.cfg shown below included in the DataHub distribution will create a point hierarchy in the default data domain that looks like this:

You can have the DataHub load this plant.cfg configuration file on startup (see Appendix B, Configuration Files).

;;; Create a generic object to share all of the common properties and
;;; attributes in the model.  Give it a common property, called "name"

(assembly default Object)
(property default Object AUTO name string rw "unnamed" 100)

;;; Create a temperature attribute that can be shared by boilers and pumps.
;;; It has three properties: value,highlimit,units

(type default Temperature)
(property default Temperature AUTO value R8 rw 0 100)
(property default Temperature AUTO highlimit R8 rw 120 100)
(property default Temperature AUTO units STRING rw "C" 100)
(defaultprop default Temperature value)

;;; Create a pressure attribute for boilers.

(type default Pressure)
(property default Pressure AUTO value R8 rw 0 100)
(property default Pressure AUTO units STRING rw "kPa" 100)
(defaultprop default Pressure value)

;;; Create a plant model, sharing the properties and attributes of "object"

(assembly default Plant Object)

;;; Create a boiler model, as an "object"

(assembly default Boiler Object)
(attribute default Boiler temperature Temperature)
(attribute default Boiler pressure Pressure)

;;; Create a pump model, as an "object"

(assembly default Pump Object)
(attribute default Pump temperature Temperature)
(property default Pump AUTO speed R8 rw 0 100)
(property default Pump AUTO state I4 rw 0 100)

;;; Create a valve object.  It has a property, position, directly
;;; attached to the assembly.  We do not need an attribute unless
;;; there is more than one property to be associated with it.  In
;;; this example position has only a value, without limits or
;;; units.

(assembly default Valve Object)
(property default Valve AUTO position R8 rw 0 100)

;;; Create a specialization of a Valve that also measures whether
;;; the valve is powered.

(assembly default Powervalve Valve)
(property default Powervalve AUTO powered I4 rw 0 100)

;;; Create the hierarchy in the model

;;; Plants have two boilers, named boiler1 and boiler2
(subassembly default Plant Boiler boiler1)
(subassembly default Plant Boiler boiler2)

;;; Boilers have one Pump, named pump
(subassembly default Boiler Pump pump)

;;; Boilers have a normal valve and a powered valve, named valve1
;;; and valve2 respectively.
(subassembly default Boiler Valve valve1)
(subassembly default Boiler Powervalve valve2)

;;; Create two plants named plant1 and plant2.  These actually
;;; create the data points in the DataHub and arrange them in
;;; the hierarchy specified above.  Up to this point, the commands
;;; have just been building a model.  These calls instantiate the
;;; model.

(instance default plant1 Plant)
(instance default plant2 Plant)

17.4.5. Example 2: Private Attributes

Here is a simpler example for creating a hierarchical data model using private attributes. This models a control system in a factory with 2 pumps. The sample file shown below will create a point hierarchy in the default data domain that looks like this:

; Create two assemblies.
(assembly testdomain factory)
(assembly testdomain pump)

; Create two subassemblies.
(subassembly testdomain factory pump pump1)
(subassembly testdomain factory pump pump2)

; Assign private attributes.
(private_attribute testdomain pump flow R8 rw 0 100)
(private_attribute testdomain pump amps R8 rw 0 100)
(private_attribute testdomain pump onoff BOOL rw 0 100)

; Instantiate the model.
(instance testdomain factory1 factory)