# Configuring Attributes

Attributes are the data items of an object or primitive. By reading from and writing to attributes, objects can exchange data with each other.

You can configure attributes for an ApplicationObject or reusable primitive by using the ArchestrA Object Toolkit’s Object Designer. You can:

- Add, edit and delete attributes and array attributes. See Adding Attributes to an Object or Primitive and Renaming or Deleting Attributes.
- Configure set handlers for attributes. See Configuring Config Time Set Handlers and Configuring Run Time Set Handlers.
- Make attributes historizable and alarmable. See Configuring Attribute Extensions.
- Add inputs and outputs to read and write data to and from the field. See Adding Inputs and Outputs.
- Configure “Advise Only Active” support for attributes. See Configuring “Advise Only Active” Support for an Attribute.

You can also configure attributes directly in the code. For more information, see the *ArchestrA Object Toolkit Reference* *Guide*.

Attributes that you configure using the ArchestrA Object Toolkit are different from the User-Defined Attributes (UDAs) that you can configure in the ArchestrA IDE. You can only view or edit their configuration in the ArchestrA IDE using your custom object editor, but not the standard UDAs page.

Also, the ArchestrA attributes that we talk about here are not the same as C# attributes. Unless specifically noted, when this manual talks about “attributes,” we mean ArchestrA attributes, not C# attributes.

## Adding Attributes to an Object or Primitive

The easiest way to add attributes and array attributes to an ApplicationObject or reusable primitive is by using the Object Designer.

**To add an attribute**

1. Open the Object Designer.
2. In the **Shape** pane, select the location where you want to add the attribute. For example, if you want to add an attribute to a local primitive, select that primitive or one of its attributes.
3. In the **Shape** pane, click the down arrow next to the **Add** icon.
4. Click **Attribute**. The properties of the new attribute are shown in the **Configuration** pane.
5. In the **External Name** box, enter a unique external name for the attribute. This is the name by which other objects can access the attribute. The name must be ArchestrA compliant. See Naming Conventions for applicable restrictions.

If you change this name later, you must manually update any references where the attribute name is passed as a string, for example, in the custom object editor.

6. In the **Internal Name** box, enter a unique internal name for the attribute. This is the name by which you can refer to the attribute in the object’s code. The name must be C# compliant. The maximum length is 329 characters.

If you change this name later, you must manually update any references where the attribute name is passed as a string.

7. In the **Type** list, select a data type for the attribute. For available options, see ArchestrA Data Types. If the data type isn’t known in advance, select **Variant**. You can then set the data type as required using custom config time or run time code.
8. In the **Category** list, select a category for the attribute. The category determines who can write to the attribute and whether it is lockable in the template. It also determines whether the additional attribute options in the following steps are available or not. For more information, see ArchestrA Attribute Categories.
9. If you want to create custom config time and/or run time set handlers for the attribute, select the **Configuration Set** **Handler** and/or **Runtime Set Handler** check boxes.
10. Select the **Supports Calculated Quality and Calculated Time** check box if the object should be able to set the attribute’s quality and timestamp. This may be necessary if you use field data (with potentially Bad or Uncertain quality) to calculate the attribute’s value. If you clear this check box, the attribute’s quality is always Good, and the timestamp is always the object’s startup time.
11. Select the **Frequently Accessed** check box to mark the attribute as a “frequently accessed” attribute for the Galaxy Browser. (Users can enable a filter to only display these attributes in the Galaxy Browser.)
12. Select the **Advise only Active** check box if you want to implement “Advise Only Active” support for the attribute. For more information, see Configuring “Advise Only Active” Support for an Attribute.
13. In the **Value** box, enter the attribute’s default value.
14. Click the shield icon next to the **Value** box and select the attribute’s security classification. For available options, see ArchestrA Security Classifications.
15. To make the attribute an array:
a. Select the **Array** check box. The array properties appear.
b. In the **Array Length** box, enter the size of the array.
c. In the grid, enter default values for each array element.
1. Click **OK** to save the attribute, or go back to step 2 and add more attributes.

### Creating a Default Attribute

If you create an attribute with an external name of “PV,” this attribute is considered the object’s “default” attribute. This attribute is used when a reference only specifies the object name without any attribute name. For example, a script can refer to “Tank2Volume.PV” simply as “Tank2Volume”. The attribute “PV” is implied.

### Creating a "Hidden" Attribute

You can “hide” an attribute so that it doesn’t appear in the Galaxy Browser or Object Viewer by default. Other objects can still access the hidden attribute, but regular users won’t see it unless they explicitly choose to display hidden attributes.

Some good reasons to create hidden attributes are:

- To preserve private configuration data in the configuration database
- To preserve private run time data in the checkpoint file
- To allow private data to be transferred from the config time component to the run time component when the object is deployed

**To create a hidden attribute**

1. When defining the attribute in the Object Designer, prefix its external name with an underscore. For example, _MyHiddenAttribute.

## Configuring Config Time Set Handlers

You can configure a config time set handler for any attribute that can be written to at config time. The code in this set handler is executed every time a value is written to the attribute during configuration. The set handler can then accept the value and write it to the attribute, or reject it. For an example, see Example: Configuring a Config Time Set Handler.

A set handler can also perform other actions, like modifying the values of other attributes or clamping a value.

When rejecting a value, a config time set handler should not generate an alarm, event, or Logger message. Instead, return a localized message to the client. See the example in the section below.

**To configure a config time set handler for an attribute**

1. Make sure the **Configuration Set Handler** check box is selected in the attribute’s configuration. For more information, see Adding Attributes to an Object or Primitive.
2. In the Object Design View, expand the **Attributes** folder.
3. Expand the attribute name.
4. Double-click **Configtime Set Handler**. The code section for the config time set handler appears in the Visual Studio code editor.
5. Enter the code for the config time set handler. When you are done, save your changes.

### Example: Configuring a Config Time Set Handler

Assume you want to return a custom, localized error message to the configuration client if the requested value for an attribute “Attr1” is out of range. First, you set up the error message in the object dictionary. Let’s say you give it an ID of 10001 (IDs up to 10000 are reserved for standard messages). Then you code the config time set handler for Attr1 to look something like this:

```csharp
if (<conditions for valid value>)
{
    Attr1 = e.value; // set the new value
}
else
{
    // Reject the value and set the error message if the value is out of range
    e.Message = GetText(10001); // ID of your error message
}
```

Now, when an invalid message is written to the attribute at config time, the localized message corresponding to the ID 10001 is shown.

## Configuring Run Time Set Handlers

You can configure a run time set handler for any attribute that can be written to at run time. The code in this set handler is executed whenever anyone other than the primitive logic associated with that attribute attempts to write to it. The set handler can then accept the value and write it to the attribute, or reject it.

A set handler can also perform other actions, for example, modify the values of other attributes or clamp a value.

When the set handler is called at run time, it is passed not only the new value, but also information about the client making the call (whether the client is a user, another object, or another primitive within the same object). The set handler can take this information into account when deciding whether to accept the new value.

When rejecting a value, run time set handlers should not generate an alarm, event, or Logger message. Instead, return an appropriate error code to the client. See the example in the section below. The MxStatusDetail enumeration provides a number of standard error codes that you should use if they fit your object’s error situations.

**To configure a run time set handler for an attribute**

1. Make sure the **Runtime Set Handler** check box is selected in the attribute’s configuration. For more information, see Adding Attributes to an Object or Primitive.
2. In the Object Design View, expand the **Attributes** folder.
3. Expand the attribute name.
4. Double-click **Runtime Set Handler**. The code section for the run time set handler appears in the Visual Studio code editor.
5. Enter the code for the run time set handler. When you are done, save your changes.

### Example: Configuring a Run Time Set Handler

Assume you want to return a custom, localized error message to the client if the requested value for an attribute “Attr1” is out of range. First, you set up the error message in the object dictionary. Let’s say you give it an ID of 10001 (IDs up to 10000 are reserved for standard messages). Then you code the run time set handler for Attr1 to look something like this:

```csharp
if (<conditions for valid value>)
{
    Attr1 = e.value; // set the new value
}
else
{
    // Reject the value and set the error status if the value is out of range
    e.status.detail = 10001; // ID of your error message
    e.status.Category = MxStatusCategory.MxCategoryOperationalError;
    e.status.detectedBy = MxStatusSource.MxSourceRespondingAutomationObject;
}
```

When the client receives the error, the GetStatusDesc run time event handler is triggered. By default it returns the localized message corresponding to the ID that you put into `e.status.detail`, which is automatically passed to GetStatusDesc as `e.DetailedErrorCode`:

```csharp
switch (e.detailedErrorCode)
{
    default:
        e.status = GetText((int)e.detailedErrorCode);
        break;
}
```

## Configuring Dynamic Attribute Set Handlers

The ArchestrA Object Toolkit allows you to dynamically create attributes at config time or run time. For more information, see the documentation on the AddAttribute and DeleteAttribute methods in the *ArchestrA Object Toolkit* *Reference Guide*. As with regular attributes, you can create set handler code for these “dynamic” attributes. The ArchestrA Object Toolkit provides a special code section for this.

Technically, there is only one set handler for all dynamic attributes. However, when this set handler is called, the name of the attribute that it’s called for is passed as an argument. By checking this name, you can branch your code and use different set handler code for different dynamic attributes.

**To edit the dynamic attribute set handler code**

1. In the Object Design View, expand the **Configtime** or **Runtime** folder, depending on which set handler you want to edit.
2. Double-click **Dynamic Attributes Set Handler**. The set handler region for dynamic attributes appears in the code editor.
3. Enter any required code, and then save your changes.

### Example: Configuring a Set Handler for a Dynamic Attribute

Assume your object has three dynamic attributes at config time: DynAtt1, DynAtt2, and DynAtt3. You want to assure that DynAtt1 is only set to positive values, whereas any values are valid for the other two attributes. You would configure a set handler like the following:

```csharp
string attrName = Get(e.attributeHandle.shAttributeId, e.attributeHandle.shPrimitiveId, EATTRIBUTEPROPERTY.idxAttribPropName); // Get name of attribute for which set was made
if (attrName == "DynAtt1") // In this case, reject negative values
{
    if (e.Value < 0)
    {
        e.Message = string.Format("Value for {0} must be positive", attrName);
    }
    else
    {
        SetValue(attrName, e.Value);
    }
    return;
}
SetValue(attrName, e.Value); // In all other cases, just set the value
```

## Configuring Attribute Extensions

You can “extend” an attribute’s functionality in the following ways:

- Historizing the attribute
- Making the attribute alarmable

The following sections explain how to configure these extensions in the Object Designer.

Technically, the extension features are implemented as primitives. The following sections also include reference information on these primitives’ attributes.

### Historizing an Attribute

You can enable history for attributes of the following data types: Float, Double, Integer, Boolean, String, CustomEnum, and ElapsedTime. When you do this, the attribute’s run time values are historized according to the settings of the engine that the object is deployed to. (If historization is disabled for the engine, no attribute values are historized even if history is enabled for the attribute.)

> **Note** 
> Some attribute categories don’t support historization. For example, attributes that exist only at config time can’t be historized.

As a guideline, enable history only for those attributes that most of your users would want to historize. If your users want to historize additional attributes, they can always do so by setting up attribute extensions in the ArchestrA IDE.

Technically, when you enable history for an attribute, a history primitive is added to the object. You can make this primitive virtual so that your users can choose whether or not they actually need the history functionality. For information on the primitive’s attributes, see Attributes of the History Primitive.

**To enable history for an attribute**

1. Open the Object Designer.
2. In the **Shape** pane, click the attribute name.
3. In the **Configuration** pane, select the **Historizable** check box. The historization options appear. Depending on the attribute’s data type, some options may be disabled.
4. Configure the history options for the attribute:
a. In the **Engineering Units** list, select the attribute that contains the engineering units string for the attribute. (The list shows all string attributes defined in your object.)
b. In the **Value Deadband** box, enter the value deadband (in engineering units) for historization. If the attribute value changes, the new value is only historized if it exceeds this deadband.
c. In the **Trend Scale Max** and **Trend Scale Min** boxes, enter the default maximum and minimum scale values for showing the attribute’s data in a trend.
d. In the **Forced Storage Period** box, enter a time interval in milliseconds. The attribute value is always historized at this interval, regardless of whether it has changed. A value of 0 disables this setting, that is, attribute values are only historized if and when they change.
e. In the **Interpolation Type** list, select the interpolation type to be used.
f. In the **Rate Deadband** box, enter a deadband rate for swinging door storage (if applicable).
g. In the **Roll Over Value** box, enter the rollover value (only applicable if Counter retrieval will be used for this attribute’s data).
h. In the **Sample Count** box, enter the number of samples to be stored in the Active Image buffer of the Historian.
i. In the **Description** box, enter a description to be stored for the attribute on the Historian. This can also be a reference to an attribute that contains the description.
j. Select the **Enable Swinging Door** check box to enable swinging door storage.
1. Select the **Virtual** check box to make the history primitive virtual.

This automatically enables the **Add Attribute to** **enable/disable History** check box as well. When this check box is enabled, an additional attribute named “<AttributeName>.Historized” is added with config time set handler code to enable and disable the history primitive. You can simply add this attribute to the custom object editor to allow your users to enable or disable history for the attribute. If you don’t want this attribute, clear the check box.

2. To lock or unlock any history option, click the padlock icon next to its input box. Locked options can’t be changed at run time.
3. Click **OK**, or go back to step 2 and configure history for additional attributes.

#### Attributes of the History Primitive

You can use the following attributes of the History primitive to monitor or re-configure it at config time and run time.

| Name | Type | Category | Description |
| --- | --- | --- | --- |
| _EngUnitsAttrName | String | PackageOnly_Lockable | Name of the attribute that defines the engineering units string for the value being historized. Only applies to numerical attributes. |
| _InterPolationTypeEnum | String[3] | Constant | Possible interpolation types: "Stairstep", "Linear", "SystemDefault" |
| _ValueAttrName | String | PackageOnly_Lockable | Name of the attribute whose values should be historized. |
| Description | String | Writeable_USC_Lockable | A brief description for the historized attribute. May be a literal string or a reference to another string attribute containing the description. The content is only considered to be a reference if the reference is of the form "me.AttrName". By default, the object’s “ShortDesc” attribute is used. (Value can’t be set at run time.) |
| EnableSwingingDoor | Boolean | Writeable_USC_Lockable | Enable or disable swinging door storage. (Value can’t be set at run time.) |
| ForceStoragePeriod | Integer | Writeable_USC_Lockable | The time interval, in milliseconds, at which the value is always stored, regardless of the value deadband setting. Effectively, this allows a continuous storage interval to be superimposed upon the value deadband mechanism. A value less than or equal to 0 disables this feature. As an example, a setting of 360000 indicates the value must be stored once per hour (measured from the time the object was last put OnScan). A value less than the host engine’s scan period causes the forced storage to occur every scan cycle. |
| InterpolationType | Custom Enum | Writeable_USC_Lockable | Interpolation type (Stairstep, Linear, SystemDefault, or None). (Value can’t be set at run time.) |
| RateDeadBand | Float | Writeable_USC_Lockable | Deadband rate for swinging door storage. (Value can’t be set at run time.) |
| RolloverValue | Float | Writeable_USC_Lockable | Rollover value for Counter retrieval. (Value can’t be set at run time.) |
| SampleCount | Integer | Writeable_USC_Lockable | Number of samples to be stored in Active Image. (Value can’t be set at run time.) |
| TrendHi | Float | Writeable_USC_Lockable | The default top of the trend scale for clients. Must be greater than or equal to TrendLo. |
| TrendLo | Float | Writeable_USC_Lockable | The default bottom of the trend scale for clients. Must be less than or equal to TrendHi. |
| ValueDeadBand | Float | Writeable_USC_Lockable | The amount, in engineering units, by which the value of the historized attribute must change in order for the new value to be historized. A value of 0 means that all new values are historized. Also, when the attribute’s quality changes, the value is always historized regardless of this setting. Only expose this attribute in the configuration environment for numerical datatypes such as Float, Double, or Integer. |

### Making an Attribute Alarmable

To configure alarms for an attribute, you create an additional Boolean attribute for each alarm type that you want to enable. Then, you enable the alarm extension and configure alarm options for each of these Boolean attributes. Finally, you create custom code that checks for the alarm conditions and changes the value of the these Boolean attributes accordingly to raise or clear the respective alarms. An alarm is active when the alarmed Boolean attribute is True, and inactive when it is False.

For an example, see Example: Configuring a Value Alarm for an Attribute.

> **Caution** 
> Simply making an attribute alarmable does not ensure that the alarm condition is actually monitored at run time! You must create custom run time code that checks for the alarm condition and raises or clears the alarm as required. The alarm extension only *reports* the alarm to the alarm system, but it does not *detect* it on its own.

As a guideline, configure only those alarms that most of your users would want to enable. If your users want to configure additional alarms, they can always do so by setting up attribute extensions in the ArchestrA IDE.

Technically, when you make an attribute alarmable, an alarm primitive is added to the object. You can make this primitive virtual so that your users can choose whether or not they actually need the alarm functionality. For information on the primitive’s attributes, see Attributes of the Alarm Primitive.

We recommend that you lock any alarm settings that you don’t expect your users to change (such as the alarm category).

**To make an attribute alarmable**

1. Open the Object Designer.
2. In the **Shape** pane, click the Boolean attribute name.
3. In the **Configuration** pane, select the **Alarmable** check box.
4. In the **Category** list, select the category to be shown for the alarm. Use the main categories as follows:

| Category | Purpose |
| --- | --- |
| Value | Limit alarms (LoLo, Lo, Hi, HiHi) |
| Deviation | Deviation from a setpoint (major, minor) |
| ROC | Rate-of-change alarms (value changes slower or faster than expected) |
| Batch | Alarms or events associated with a batch process |
| Discrete | Discrete alarms |
| Process | Alarms or events associated with the physical process/plant |
| SPC | SPC alarms (out-of-spec, out-of-control, “run rules;” etc.) |
| System | Alarms or events associated with the automation system |
| Software | Alarms or events associated with a software operation/logic (such as “divide by zero” in a script) |

1. In the **Priority** box, enter a priority for the alarm (0 = highest, 999 = lowest).
2. Optionally, in the **Engineering Units** list, select the attribute that contains the engineering units string for the attribute. (The list shows all string attributes defined in your object.)
3. Optionally, in the **Value** list, select the attribute whose value the alarm relates to.
4. Optionally, in the **Limit** list, select the attribute that contains the alarm limit value.
5. Optionally, in the **Description** list, select the attribute whose value should be used as the alarm description.
6. Select the **Virtual** check box to make the alarm primitive virtual.

This automatically enables the **Add Attribute to** **enable/disable Alarm** check box as well. When this check box is enabled, an additional attribute named “<AttributeName>.Alarmed” is added with config time set handler code to enable and disable the alarm primitive. You can simply add this attribute to the custom object editor to allow your users to enable or disable the alarm. If you don’t want this attribute, clear the check box.

7. To lock or unlock any alarm option, click the padlock icon next to its input box. Locked options can’t be changed at run time.
8. Click **OK**, or go back to step 2 and configure alarms for additional attributes.

#### Example: Configuring a Value Alarm for an Attribute

Assume you want to set up a HiHi value alarm for an Integer attribute named “AlmAtt1.” To do this, you would follow these general steps:

1. Create attributes to manage the alarm. You need at least the Boolean attribute that represents the alarm condition. In this example, we will also set up attributes for the limit value and description of the alarm. It’s convenient to group these attributes in a separate primitive. So, add a new local primitive with an empty external name and the following attributes:

| Name | Data type | Description |
| --- | --- | --- |
| AlmAtt1.HiHi | Boolean | Indicates if the alarm condition is met |
| AlmAtt1.HiHi. Limit | Integer | HiHi limit value |
| AlmAtt1.HiHi. AlmDesc | String | Alarm description/comment |

1. Make AlmAtt1.HiHi alarmable (see Making an Attribute Alarmable). Set the category to “ValueHiHi” and specify a priority. Set the **Value** attribute to “AlmAtt1,” the **Limit** attribute to “AlmAtt1.HiHi.Limit,” and the **Description** attribute to “AlmAtt1.HiHi.AlmDesc.”
2. Add code to the Execute run time event handler of the local primitive you added. The code should:
    - Check the value of AlmAtt1 to see if it exceeds the value of AlmAtt1.HiHi.Limit.
    - If yes, and AlmAtt1.HiHi is False (that is, the actual alarm condition has just occurred), set AlmAtt1.HiHi to True. If AlmAtt1.HiHi is already True, there is no need to set it again.
    - If no, and AlmAtt1.HiHi is True (that is, the value has just returned to normal), set AlmAtt1.HiHi to False. If AlmAtt1.HiHi is already False, there is no need to set it again.

Now, when the value of AlmAtt1 exceeds its limit at run time, the primitive code detects this and sets AlmAtt1.HiHi to True. Because you made AlmAtt1.HiHi alarmable, its alarm primitive detects this change in value and reports an alarm using the information that you configured (Category = HiHi, value = current value of AlmAtt1, etc.)

#### Attributes of the Alarm Primitive

You can use the following attributes of the Alarm primitive to monitor or re-configure it at config time and run time.

| Name | Type | Category | Description |
| --- | --- | --- | --- |
| _AlmEngUnitsAttrName | String | PackageOnly_Lockable | Name of the attribute containing the Engineering Units string. |
| _AlmValueAttrName | String | PackageOnly_Lockable | Name of the attribute whose value is monitored for the alarm condition. |
| _CategoryEnum | String [14] | Constant | Possible values for the Category attribute: Discrete, Value LoLo, Value Lo, Value Hi, Value HiHi, DeviationMinor, DeviationMajor, ROC Lo, ROC Hi, SPC, Process, System, Batch, Software |
| _ConditionAttrName | String | PackageOnly_Lockable | Name of the Boolean attribute that represents the alarm condition. |
| _LimitAttrName | String | PackageOnly_Lockable | Name of the attribute that contains the limit value for the alarm condition. |
| Acked | Boolean | Calculated | Indicates whether the alarm is acknowledged. This attribute is updated when a user sets the AckMsg attribute. It is always set to false when a new alarm condition is detected (that is, when the InAlarm attribute changes from false to true). |
| AckMsg | String | Writeable_US | Operator acknowledgement comment. **Run time set handler:** Stores received text and sets the Acked attribute to true. Also sets the TimeAlarmAcked attribute to the current time. |
| AlarmInhibit | Boolean | Writeable_US | When true, the alarm is disabled. This attribute is intended to be written to typically by a script or user or input extension. Only the individual alarm is disabled. No other alarms are disabled in the same object or in any assigned or contained objects. |
| AlarmMode | CustomEnum | Calculated Retentive | Current alarm mode (based on the commanded mode). |
| AlarmModeCmd | CustomEnum | Writeable_US | Currently commanded alarm mode. |
| Category | CustomEnum | Writeable_USC_Lockable | Category of the alarm. The label of each alarm category is fixed. See the _CategoryEnum attribute for possible values. **Run time set handler:** Ensures that the value is between 1 and 15. |
| DescAttrName | String | Writeable_USC_Lockable | Description for the alarm condition. May be a literal string or a reference to another string attribute containing the description. The content is only considered to be a reference if the reference is of the form "me.AttrName". By default, the object’s “ShortDesc” attribute is used. |
| InAlarm | Boolean | Calculated | This bit represents the alarm state. This is exactly the same as the attribute in the host primitive that represents the alarm condition except when the alarm state is disabled. In that case, InAlarm is set to false regardless of the actual condition state. |
| Priority | Integer | Writeable_USC_Lockable | Priority of the alarm. Valid values are 0 to 999. 0 is the highest priority. |
| TimeAlarmAcked | Time | Calculated | Time stamp indicating the last time the alarm was acknowledged. |
| TimeAlarmOff | Time | Calculated | Time stamp indicating the last time the alarm went off. |
| TimeAlarmOn | Time | Calculated | Time stamp indicating the last time the alarm went on. |

## Adding Inputs and Outputs

By adding inputs and outputs to your objects or primitives, you can read and write data to and from other ArchestrA objects. For example, your object could have an input that reads data from an attribute of a DIObject, which in turn reads data from an item in a physical PLC.

Technically, inputs and outputs are implemented not as single attributes, but as primitives that expose multiple attributes. However, you can add and configure them much like attributes in the Object Designer. There are three types of input/output primitives:

- **Input:** Reads values from an external reference.
- **Output:** Writes values to an external reference.
- **Input/Output:** Reads and writes values to and from an external reference. Optionally, the input reference can be different from the output reference, that is, values can be written to a different address than the one they are read from.

An instance of the relevant primitive is added for every input or output that you configure. To read and write the I/O data at run time, you simply use the attributes of each primitive instance.

### Adding an Input

Using an input, you can read single data values from an external input source. Often, that source will be a DeviceIntegration object attribute that represents a register or piece of data in a field device, but you can configure any attribute of any AutomationObject as the input source. The actual reference is usually configured by the end user.

If you know the expected data type, specify it and lock it in the Object Designer after you add the input. Give the input a useful external name that indicates its purpose to the end user.

When you add a static (non-virtual) input primitive, wrapper classes are added automatically. Use these wrappers to access the input values, quality, and status at run time. For example:

```csharp
if (Input1.Value.Quality == DataQuality.DataQualityGood)
{
    double myValue = Input1.Value;
}
```

For virtual input primitives, you can use the primitive’s attributes instead. For more information, see Attributes of the Input Primitive.

For more information on input primitive wrappers and using the InputPrimitive wrapper to create instances of a virtual input primitive, see the *ArchestrA Object Toolkit* *Reference* *Guide*.

**To add an input**

1. Open the Object Designer.
2. In the **Shape** pane, select the location where you want to add the input. For example, if you want to add an input to a local primitive, select that primitive or one of its attributes.
3. In the **Shape** pane, click the down arrow next to the **Add** icon.
4. Click **Input**. A primitive node for the input is added to the object tree in the **Shape** pane. The properties of the new input are shown in the **Configuration** pane of the Object Designer.
5. In the **External Name** box, enter a unique external name for the input. This is the name by which other objects can access the input. The name must be ArchestrA compliant.
6. In the **Internal Name** box, enter a unique internal name for the input. This is the name by which you can refer to the input in the object’s code. The name must be C# compliant.
7. Select the **Virtual** check box.if the new input primitive should be virtual.
8. In the **Shape** pane, click the **DataType** item underneath the new primitive node. The **Configuration** pane now shows the data type properties.
9. In the **Value** list, select the data type for the input.
10. In the **Shape** pane, click the **InputSource** item underneath the new primitive node. The **Configuration** pane now shows the input source properties.
11. In the **Value** box, enter the input source reference.
12. Click **OK**, or go back to step 2 to add more inputs.

#### Attributes of the Input Primitive

You can use the following attributes of the Input primitive to monitor or re-configure it at config time and run time.

| Name | Type | Category | Description |
| --- | --- | --- | --- |
| DataType | Data Type | Writeable_C_Lockable | Specifies the expected data type of the Value attribute. If you know the data type in advance, you’ll probably lock this attribute in the primitive. **Config time set handler:** Sets the Type property of the Value attribute to the matching type. Only can be done on templates, not instances. |
| InputSource | Reference | Writeable_USC_Lockable | Identifies the target attribute from which the value and quality are to be read. **Run time set handler:** Unregisters the old reference. Registers the new reference, sets Value.Quality to “Initializing,” and ReadStatus to “OK” (if the object is off scan) or “Pending” (if on scan). |
| ReadStatus | Status | Calculated | Indicates the cause of any errors while reading data from the input reference. This is the Message Exchange status, not the status of communication to external devices such as PLCs. The status is updated on every execution. If data is successfully received, but cannot be coerced to the specified data type, ReadStatus is set to “Configuration Error.” ReadStatus is set to “OK” when the object is off scan, and to “Pending” when it goes on scan. When Quality is “Bad,” ReadStatus can be OK or in error. |
| Value | Variant | Calculated | The value received from the input reference. The Value attribute is “calculated” using data received by a Message Exchange GetAttribute call. Quality can be one of the following:     •   “Initializing” when the object goes on scan.         •   “Bad” if data is successfully received, but cannot be coerced to the specified data type.         •   “Bad” when the object goes off scan.         •   The reported quality of the external data in all other cases. |
| • | “Initializing” when the object goes on scan. |  |  |
| • | “Bad” if data is successfully received, but cannot be coerced to the specified data type. |  |  |
| • | “Bad” when the object goes off scan. |  |  |
| • | The reported quality of the external data in all other cases. |  |  |

### Adding an Output

Using an output, you can write single data values to an external output destination. Often, that destination will be a DeviceIntegration object attribute that represents a register or piece of data in a field device, but you can configure any attribute of any AutomationObject as the output destination. The actual reference is usually configured by the end user.

If you know the expected data type, specify it and lock it in the Object Designer after you add the output. Give the output a useful external name that indicates its purpose to the end user.

When you add a static (non-virtual) output primitive, wrapper classes are added automatically. Use these wrappers to write output values and monitor the write status at run time. For example, to write an output value:

```csharp
Output1.Value = myValue;
```

Or, to check the write status in a subsequent scan cycle:

```csharp
MxStatus stat = Output1.WriteStatus;
if (stat.Category == MxStatusCategory.MxCategoryOk)
{
    (... any required code ...)
}
```

For virtual output primitives, you can use the primitive’s attributes instead. For more information, see Attributes of the Output Primitive.

For more information on output primitive wrappers and using the OutputPrimitive wrapper to create instances of a virtual output primitive, see the *ArchestrA Object Toolkit* *Reference Guide*.

**To add an output**

1. Open the Object Designer.
2. In the **Shape** pane, select the location where you want to add the output. For example, if you want to add an output to a local primitive, select that primitive or one of its attributes.
3. In the **Shape** pane, click the down arrow next to the **Add** icon.
4. Click **Output**. A primitive node for the output is added to the object tree in the **Shape** pane. The properties of the new output are shown in the **Configuration** pane of the Object Designer.
5. In the **External Name** box, enter a unique external name for the output. This is the name by which other objects can access the output. The name must be ArchestrA compliant.
6. In the **Internal Name** box, enter a unique internal name for the output. This is the name by which you can refer to the output in the object’s code. The name must be C# compliant.
7. Select the **Virtual** check box.if the new output primitive should be virtual.
8. In the **Shape** pane, click the **DataType** item underneath the new primitive node. The **Configuration** pane now shows the data type properties.
9. In the **Value** list, select the data type for the output.
10. In the **Shape** pane, click the **OutputDest** item underneath the new primitive node. The **Configuration** pane now shows the output destination properties.
11. In the **Value** box, enter the output destination reference.
12. Click **OK**, or go back to step 2 to add more outputs.

#### Attributes of the Output Primitive

You can use the following attributes of the Output primitive to monitor or re-configure it at config time and run time.

| Name | Type | Category | Description |
| --- | --- | --- | --- |
| DataType | Data Type | Writeable_C_Lockable | Specifies the expected data type of the Value attribute. If you know the data type in advance, you’ll probably lock this attribute in the primitive. |
| OutputDest | Reference | Writeable_USC_Lockable | Identifies the target attribute to which the value is to be written. **Run time set handler:** Unregisters the old reference. Registers the new reference and sets WriteStatus to “OK” (if the object is off scan) or “Pending” (if on scan). |
| Value | Variant | Calculated | The value to be written to the output destination. **Run time set handler:** Caches the new value and initiates a SupervisorySetAttribute call to the output destination on the object’s next execution. |
| WriteStatus | Status | Writeable_S | Indicates the cause of any errors while writing data to the output destination. This is the Message Exchange status and also, if the output destination is a DeviceIntegration object, the status of communication to the external device (such as a PLC). Updated on each attempt to write a new value only. If data is successfully sent, but cannot be coerced to the specified data type, WriteStatus is set to “Configuration Error.” WriteStatus is set to “OK” when the object is off scan. On a new write attempt, WriteStatus is initially set to the temporary value “Pending” until the write either succeeds or fails. If the output destination is in a DeviceIntegration object, the “Pending” state remains until the DeviceIntegration object returns (asynchronously) the actual completion status to its target, usually an external field device. |

### Adding an Input/Output

Using an input/output, you can read and write single data values to and from an external location. You can specify an input source that is different from the output destination. This will be the case when the input is read back from a secondary source location that is different from the output destination. Some field devices may be set up with separate input and output locations for security or robustness purposes.

The actual references are usually configured by the end user. If you know the expected data type, specify it and lock it in the Object Designer after you add the input/output. Give the input/output a useful external name that indicates its purpose to the end user.

When you add a static (non-virtual) input/output primitive, wrapper classes are added automatically. Use these wrappers to read/write I/O values and monitor the I/O status at run time.

For virtual input/output primitives, you can use the primitive’s attributes instead. For more information, see Attributes of the Input/Output Primitive.

For more information on input/output primitive wrappers and using the InputOutputPrimitive wrapper to create instances of a virtual input/output primitive, see the *ArchestrA Object Toolkit* *Reference Guide*.

**To add an input/output**

1. Open the Object Designer.
2. In the **Shape** pane, select the location where you want to add the input/output. For example, if you want to add an input/output to a local primitive, select that primitive or one of its attributes.
3. In the **Shape** pane, click the down arrow next to the **Add** icon.
4. Click **Input/Output**. A primitive node for the input/output is added to the object tree in the **Shape** pane. The properties of the new input/output are shown in the **Configuration** pane of the Object Designer.
5. In the **External Name** box, enter a unique external name for the input/output. This is the name by which other objects can access the input/output. The name must be ArchestrA compliant.
6. In the **Internal Name** box, enter a unique internal name for the input/output. This is the name by which you can refer to the input/output in the object’s code. The name must be C# compliant.
7. Select the **Virtual** check box.if the new input/output primitive should be virtual.
8. In the **Shape** pane, click the **DataType** item underneath the new primitive node. The **Configuration** pane now shows the data type properties.
9. In the **Value** list, select the data type for the input/output.
10. In the **Shape** pane, click the **Reference** item underneath the new primitive node. The **Configuration** pane now shows the input/output reference properties.
11. In the **Value** box, enter the output destination reference. This reference is also used as the input source unless you configure a separate input source.
12. To configure an input source that is different from the output destination:
a. In the **Shape** pane, click the **SeparateFeedbackConfigured** item underneath the new primitive node. In the **Configuration** pane, select the **true/false** check box.
b. In the **Shape** pane, click the **ReferenceSecondary** item underneath the new primitive node. In the Configuration pane, enter the input source reference in the **Value** box.
1. Click **OK**, or go back to step 2 to add more inputs/outputs.

#### Attributes of the Input/Output Primitive

You can use the following attributes of the Input/Output primitive to monitor or re-configure it at config time and run time.

| Name | Type | Category | Description |
| --- | --- | --- | --- |
| DataType | Data Type | Writeable_C_Lockable | Specifies the expected data type of the ReadValue and WriteValue attributes. If you know the data type in advance, you’ll probably lock this attribute in the primitive. |
| ReadStatus | Status | Calculated | Indicates the cause of any errors while reading data from the input reference. This is the Message Exchange status, not the status of communication to external devices such as PLCs. The status is updated on every execution. If data is successfully received, but cannot be coerced to the specified data type, ReadStatus is set to “Configuration Error.” ReadStatus is set to “OK” when the object is off scan, and to “Pending” when it goes on scan. When Quality is “Bad,” ReadStatus can be OK or in error. |
| ReadValue | Variant | Calculated | The value received from the input reference. The ReadValue attribute is “calculated” using data received by a Message Exchange GetAttribute call. Quality can be one of the following:     •   “Initializing” when the object goes on scan.         •   “Bad” if data is successfully received, but cannot be coerced to the specified data type.         •   “Bad” when the object goes off scan.         •   The reported quality of the external data in all other cases. |
| • | “Initializing” when the object goes on scan. |  |  |
| • | “Bad” if data is successfully received, but cannot be coerced to the specified data type. |  |  |
| • | “Bad” when the object goes off scan. |  |  |
| • | The reported quality of the external data in all other cases. |  |  |
| Reference | Reference | Writeable_USC_Lockable | Identifies the target attribute to which the value is to be written. If no separate input reference is specified, this also serves as the input reference. **Run time set handler:** Unregisters the old reference. Registers the new reference and sets WriteStatus to “OK” (if the object is off scan) or “Pending” (if on scan). |
| ReferenceSecondary | Reference | Writeable_USC_Lockable | If the SeparateFeedbackConfigured attribute is set to TRUE, ReferenceSecondary identifies the source attribute from which the value and quality are to be read. If left empty, both the input and output use the single location specified in the Reference attribute. **Run time set handler:** Unregisters the old reference. Registers the new reference, sets Value.Quality to “Initializing,” and ReadStatus to “OK” (if the object is off scan) or “Pending” (if on scan). **Config time set handler:** Only allows this attribute to be set if SeparateFeedbackConfigured is TRUE. |
| SeparateFeedback Configured | Boolean | PackageOnly_Lockable | Specifies whether the primitive receives input data from a source address that is different from the output destination. |
| WriteStatus | Status | Writeable_S | Indicates the cause of any errors while writing data to the output destination. This is the Message Exchange status and also, if the output destination is a DeviceIntegration object, the status of communication to the external device (such as a PLC). Updated on each attempt to write a new value only. If data is successfully sent, but cannot be coerced to the specified data type, WriteStatus is set to “Configuration Error.” WriteStatus is set to “OK” when the object is off scan. On a new write attempt, WriteStatus is initially set to the temporary value “Pending” until the write either succeeds or fails. If the output destination is in a DeviceIntegration object, the “Pending” state remains until the DeviceIntegration object returns (asynchronously) the actual completion status to its target, usually an external field device. |
| WriteValue | Variant | Calculated | The value to be written to the output destination. **Run time set handler:** Caches the new value and initiates a SupervisorySetAttribute call to the output destination on the object’s next execution. |

## Supporting Buffered Data

If a given attribute changes its value several times during a single scan cycle, the values of multiple data changes within a single scan typically are overwritten and only the last value is retrieved. This is called data folding. The Buffered Data feature ensures that there is no folding of data.

AOT provides the ability to read and write buffered data by means of the following two .Net classes:

- VtqBufferReader
- VtqBufferWriter

> **Note** 
> These classes are available in the ArchestrA.Toolkit.VtqBuffer.dll, a managed C++ assembly that comes with AOT.

### Enabling Buffered Data for a Config-time Dynamic Attribute

You can enable the buffer property of a config-time dynamic attribute either from the package code, or the editor code.

For package code, use the following:

```csharp
Set("Attribute1", EATTRIBUTEPROPERTY.idxAttribPropHasBuffer, true);
```

For editor code, use the following:

```csharp
SetData("Attribute1", "hasbuffer", 1);
```

Enter false (or “0”) as the last parameter to disable the buffer property.

> **Note** 
> You can enable the buffer property and the VtqBufferWriter for OnObject config-time dynamic attributes. You can initialize VtqBufferReader for both OnObject and OffObject config-time dynamic attributes. Even if the config-time dynamic attribute is located on OnObject, you cannot use Editor functions SetData and GetData, and Runtime functions Set and Get, if the attribute reference contains an object name. For example, **myTestAOT_001.myuda**.

### Initializing VtqBufferReader

You need to declare VtqBufferReader to support buffer processing at run time. The VtqBufferReader class is derived from IEnumerable, which allows it to be used in a C# foreach statement.

The VTQ value type may be Boolean, integer, float, double, string, data time, or time span.

The following are examples of VTQ’s time stamp and quality:

```csharp
DateTime TimeStamp
CMxDataQualith Quality
```

**To support buffer processing at run time**

1. Declare a VtqBufferReader in your object’s Run-time class definition. For example:

```csharp
    VtqBufferReader Reader;
```

1. Initialize the VtqBufferReader in the Run-time Startup code. For example:

```csharp
    Reader = new VtqBufferReader(this, "me.Attribute1");
```

1. Process the buffer in the Run-time Execute code. For example:

```csharp
    foreach (vtq in vtqBufReader)
    {
    // do something with vtq.Value, vtq.TimeStamp and vtq.Quality
    }
```

### Using VtqBufferWriter

The VtqBufferWriter class provides an assortment of AddVtq overloads, one of which is called multiple times to build a buffer of VTQs. Call Getbuffer to retrieve the accumulated buffer from the VtqBufferWriter. The buffer is returned as a custom structure contained in a CMxValue. GetBuffer empties the buffer in the underlying buffer writer.

**To support writing a buffer at run time**

1. Declare a VtqBufferWriter instance. For example:

```csharp
    VtqBufferWriter vtqBufWriter;
```

1. Initialize the VtqBufferWriter. For example:

```csharp
    vtqBufWriter = new VtqBufferWriter ();
```

1. Create instances of Value, Time, and Quality. For example:

```csharp
    Bool V = true;
    DateTime T = DateTime.Now;
    CMxDataQuality Q = new CMxDataQuality(DataQuality.DataQualityGood);
```

1. Add multiple VTQs to VtqBufferWriter. For example:

```csharp
    vtqBufWriter.AddVtq(V,T,Q);
    vtqBufWriter.AddVtq(V,T,Q);
    vtqBufWriter.AddVtq(V,T,Q);
    vtqBufWriter.AddVtq(V,T,Q);
    vtqBufWriter.AddVtq(V,T,Q);
```

1. Get the buffer from VtqBufferWriter and write to the buffered attribute. For example:

```csharp
    CMxValue mxvalBuffer = vtqBufWriter.GetBuffer();
    AttributeHandle attrHandle = GetAttributeHandle(“Attribute1”);
    Set(attrHandle.shAttributeId, attrHandle.shPrimitiveId, EATTRIBUTEPROPERTY.idxAttribPropBuffer, mxvalBuffer);
```

## Configuring "Advise Only Active" Support for an Attribute

You can implement “Advise Only Active” support for attributes in your objects and primitives. This allows you to configure individual attributes to stop updating if noone is subscribing to them. This reduces the processing and network load.

When you enable “Advise Only Active” support for an attribute, the Application Server infrastructure continually monitors whether there are active subscriptions to that attribute. When there are no (or no more) subscriptions, it calls a special, attribute-specific method to notify the attribute that it should suspend updates. When the first subscription starts, Application Server calls the same method again to notify the attribute that it should resume updates. You can customize this method for each attribute to suspend or resume subscriptions to any data sources that the attribute uses.

Typically, you would only implement “Advise Only Active” support for attributes that are associated with “live” updates from external sources, for example, an input or an attribute in another object that your object subscribes to via Message Exchange. For example, if noone is polling the value of a calculated attribute that uses an value from an input primitive, you could stop requesting the value so as to reduce the load on the associated I/O server and network.

You can implement “Advise Only Active” support for all attribute types and categories that are available at run time.

Note the following:

- Before you can implement “Advise Only Active” support for individual attributes, you must enable it on the ApplicationObject level. For more information, see Enabling “Advise Only Active” Support for the Object. To use “Advise Only Active” in a reusable primitive, it must be enabled in the containing object.
- When you enable “Advise Only Active” support for an ApplicationObject, all Input and InputOutput primitives within the object (including its child primitives) are suspended automatically on startup. In most cases, this should fit your needs. However, if you have any attributes that are not configured for “Advise Only Active” and that require data from these Input or InputOutput primitives at each scan, you must activate these inputs at startup time by calling their ActivateUpdatesList() methods. For example, `Input1.ActivateUpdatesList();`.

**To implement “Advise Only Active” support for an attribute**

1. Enable the “Advise Only Active” option for the attribute:
a. Open the Object Designer.
b. In the **Shape** pane, click the attribute name.
c. In the **Configuration** pane, select the **Advise only Active** check box.
d. Click **OK**.
The ArchestrA Object Toolkit automatically adds a method named “*AttributeName*_AdviseOnlyActive()” to the run time code. This is the method that the Application Server infrastructure calls to notify the attribute that it should suspend or resume updates.

1. In the Object Design View, expand the **Attributes** folder. Expand the attribute name.
2. Double-click the contained **Advise only Active** node. The “*AttributeName*_AdviseOnlyActive()” method section of the run time code file appears in the Visual Studio code editor.
3. The `if (suspending)` branch is executed when Application Server determines that there are no more subscriptions to the attribute. Enter code here to suspend updates from any data sources that the attribute uses. For example:
    - If the data source is an Input or Input/Output primitive, call its SuspendUpdatesList() wrapper method.
    - If the data source is an attribute in another object, use the CMxIndirect.Suspend() method.
1. The `else` branch is executed when subscriptions to the attribute start again. Enter code here to re-activate updates from any data sources that the attribute uses. For more information on available methods, see the *ArchestrA Object Toolkit* *Reference Guide*.
2. When you are done, save your work.

## Renaming or Deleting Attributes

You can rename or delete attributes even if other places in your object already refer to them. Note the following:

- When you change the *internal name* of an attribute, references in your object are automatically updated. However, you must manually update any references where the internal name is passed as a string.
- When you change the *external name* of an attribute, you must manually update any references where the external name is passed as a string. This includes any references in the custom object editor or GetValue/SetValue calls.
- When you delete an attribute, references in your object are automatically checked and updated, but you must manually update any references where the internal or external name is passed as a string.
