Part 4 - Equipment properties

This article is a part of "Creating an Equipment model" tutorial

Now that a simple equipment type hierarchy is defined, it is time to create some properties for the equipment types. The system will consist of two tanks, one pump, and two pipes. All of the properties of the system are defined in the following tables.

Pipe equipment type

PropertyData typeUnitData collection
Flowdoublem3/sYes
DiameterdoublecmNo
Manufacturerstring-No

Pump equipment type

PropertyData typeUnitData collection
Nominal powerdoubleWNo
PowerdoubleWYes
Manufacturerstring-No
Source tankGUID-No
Target tankGUID-No
Operational state *int16
(Enumeration: Binary Text(1), displayed as "Run"/"Stop")
-Yes
Power state *int16
(Enumeration: Binary Text(6), displayed as "On"/"Off")
-Yes

*) The type of properties Operational state and Power state is an integer, but in addition, they have a reference to an enumeration. Because of this, their values in the UI are displayed as text, not as numerical values.

Tank equipment type

PropertyData typeUnitData collection
LeveldoublemmYes
Volumedoublem3No
Manufacturerstring-No

The tables above suggest that each equipment type has a "Manufacturer" property, so it would be convenient to make it an inherited property defined only once for all equipment types devised from the "Device" type. That being said, let's add the "Manufacturer" equipment property for the "Device" equipment type.

// Create a new property
var property = (ABB.Vtrin.Interfaces.IPropertyDefinition)RTDBDriver.Classes["EquipmentPropertyInfo"].Instances.Add();

// Set property info
property.DisplayName = "Manufacturer";
property.Type = (int)Vtrin.cTypeCode.String;
property.Description = "The manufacturer of the device";
property.Historized = false;
property.Equipment = baseEquipment;

// Commit changes
property.CommitChanges();

Implementing the full method

Again, creating multiple equipment properties is a repetitive process. To avoid the copy-paste coding style, we will write a helper function that handles the property creation. The following method will create a new property by the given name if one doesn't already exist. Otherwise, it will update the existing property.

private static ABB.Vtrin.Interfaces.IPropertyDefinition CreateOrUpdateEquipmentProperty(
    string propertyName,
    ABB.Vtrin.cTypeCode propertyType,
    string propertyUnit,
    bool isHistorized,
    ABB.Vtrin.Interfaces.IEquipment equipmentType,
    string propertyDescription = null)
{
    ABB.Vtrin.Interfaces.IPropertyDefinition property;
    var equipmentPropertyInstances = RTDBDriver.Classes["EquipmentPropertyInfo"].Instances;

    // Query existing property infos using property name and equipment type
    var properties = equipmentPropertyInstances.GetInstanceSet("Equipment=? AND DisplayName=?", equipmentType, propertyName);

    // Case: No existing property found
    // > Create a new property
    if (properties.Length == 0)
        property = (ABB.Vtrin.Interfaces.IPropertyDefinition)equipmentPropertyInstances.Add();

    // Case: Existing property found
    // > Select that and begin to update
    else
        property = (ABB.Vtrin.Interfaces.IPropertyDefinition)properties[0].BeginUpdate();

    // Update property info
    property.DisplayName = propertyName;
    property.Type = (int)propertyType;
    property.Unit = propertyUnit;
    property.Description = propertyDescription;
    property.Historized = isHistorized;
    property.Equipment = equipmentType;

    // Save or update property
    property.CommitChanges();

    return property;
}

Using the method above, defining new equipment properties is easy. New equipment properties can be defined just like here.

// Common properties
// =================

CreateOrUpdateEquipmentProperty(
    propertyName: "Manufacturer",
    propertyType: ABB.Vtrin.cTypeCode.String,
    propertyUnit: "",
    propertyDescription: "The manufacturer of the device",
    isHistorized: false,
    equipmentType: baseEquipmentType);

// Tank properties
// ===============

CreateOrUpdateEquipmentProperty(
    propertyName: "Level",
    propertyType: ABB.Vtrin.cTypeCode.Double,
    propertyUnit: "mm",
    propertyDescription: "The water level inside the tank",
    isHistorized: true,
    equipmentType: tankType);

CreateOrUpdateEquipmentProperty(
    propertyName: "Volume",
    propertyType: ABB.Vtrin.cTypeCode.Double,
    propertyUnit: "m3",
    propertyDescription: "The volume of the water tank",
    isHistorized: false,
    equipmentType: tankType);

// Pipe properties
// ===============

CreateOrUpdateEquipmentProperty(
    propertyName: "Diameter",
    propertyType: ABB.Vtrin.cTypeCode.Double,
    propertyUnit: "cm",
    propertyDescription: "The diameter of the pipe",
    isHistorized: false,
    equipmentType: pipeType);

CreateOrUpdateEquipmentProperty(
    propertyName: "Flow",
    propertyType: ABB.Vtrin.cTypeCode.Double,
    propertyUnit: "l/min",
    propertyDescription: "The current water flow through the pipe",
    isHistorized: true,
    equipmentType: pipeType);

// Pump properties
// ===============

CreateOrUpdateEquipmentProperty(
    propertyName: "Power",
    propertyType: ABB.Vtrin.cTypeCode.Double,
    propertyUnit: "W",
    propertyDescription: "The current power of the pump",
    isHistorized: true,
    equipmentType: pumpType);

CreateOrUpdateEquipmentProperty(
    propertyName: "Nominal power",
    propertyType: ABB.Vtrin.cTypeCode.Double,
    propertyUnit: "W",
    propertyDescription: "The nominal power of the pump",
    isHistorized: false,
    equipmentType: pumpType);

CreateOrUpdateEquipmentProperty(
    propertyName: "Source tank",
    propertyType: ABB.Vtrin.cTypeCode.GUID,
    propertyUnit: null,
    propertyDescription: "The tank that pump is pumping water from",
    isHistorized: false,
    equipmentType: pumpType,
    referenceTarget: "Class:" + tankType.ClassName);

CreateOrUpdateEquipmentProperty(
    propertyName: "Target tank",
    propertyType: ABB.Vtrin.cTypeCode.GUID,
    propertyUnit: null,
    propertyDescription: "The tank that pump is pumping water into",
    isHistorized: false,
    equipmentType: pumpType,
    referenceTarget: "Class:" + tankType.ClassName);

CreateOrUpdateEquipmentProperty(
    propertyName: "Operational state",
    propertyType: ABB.Vtrin.cTypeCode.Int16,
    propertyUnit: null,
    propertyDescription: "Tells whether the pump is running or not",
    isHistorized: true,
    equipmentType: pumpType,
    referenceTarget: "Enumeration:Binary Text(1)");

CreateOrUpdateEquipmentProperty(
    propertyName: "Power state",
    propertyType: ABB.Vtrin.cTypeCode.Int16,
    propertyUnit: null,
    propertyDescription: "Tells whether the pump is powered or not",
    isHistorized: true,
    equipmentType: pumpType,
    referenceTarget: "Enumeration:Binary Text(6)");

What do we have now?

At this point, if you run the code, you should have all the needed equipment types and their properties defined. You can use Engineering UI to ensure if that is the case. Select "Configuration" > "Equipment Types" to browse your newly created equipment types. If you select the equipment type "Pump", for instance, by clicking it, you should see all the equipment properties that the "Pump" equipment type has:

Display nameData typeUnitHistorized
PowerFloating Point Value (64bit)WYes
Nominal powerFloating Point Value (64bit)WNo
Source tankGlobally Unique Identifier (GUID)(None)No
Target tankGlobally Unique Identifier (GUID)(None)No
Operational stateString(None)Yes
Power stateString(None)Yes
📘

Compare your code

This tutorial is following the code that can be found from our GitHub repository. Checking out the full example code is highly recommended.