Files
wwtools/aot/dev-guide/06-configuring-attributes.md
Joseph Doherty 32f26272ae Initial commit: Wonderware / System Platform tools and reference
Five tools under one repo, all docs organized per DOCS-GUIDE.md:

- aalogcli: .NET 4.8 / x86 CliFx CLI for reading System Platform binary
  logs (*.aaLGX) for LLM debugging, built on aaOpenSource/aaLog. Commands:
  last, tail, range, unread, fields. Stable JSON envelope under --llm-json.
  Build template under lib/build/ for rebuilding aaLogReader.dll.

- aot: ArchestrA Object Toolkit 2014 v4.0 reference material. Dev guide
  (Markdown converted from CHM), API reference for the ArchestrA.Toolkit
  namespace, and the Monitor / Watchdog VS sample solutions.

- graccesscli: .NET 4.8 / x86 CliFx CLI that automates Galaxy
  configuration via the ArchestrA GRAccess COM interop. Includes session
  daemon, IPC protocol, and llm-json envelope contract.

- grdb: SQL/DDL exploration of the Galaxy Repository database. DDL
  captures, reusable queries, hierarchy / contained-name <-> tag-name
  translation notes.

- histdb: LLM-oriented reference for AVEVA Historian retrieval. INSQL
  linked-server, extension tables, every wwXxx time-domain extension,
  every retrieval mode, alarm/event SQL recipes, REST API. Distilled
  from the 243-page Historian Retrieval Guide.

Root contains:
- CLAUDE.md: thin index pointing into each tool's README.
- DOCS-GUIDE.md: doctrine for organizing docs for LLM consumption.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-03 18:22:20 -04:00

55 KiB
Raw Permalink Blame History

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 Toolkits 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.

  1. 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 objects 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.

  1. In the Type list, select a data type for the attribute. For available options, see ArchestrA Data Types. If the data type isnt known in advance, select Variant. You can then set the data type as required using custom config time or run time code.
  2. 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.
  3. 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.
  4. Select the Supports Calculated Quality and Calculated Time check box if the object should be able to set the attributes quality and timestamp. This may be necessary if you use field data (with potentially Bad or Uncertain quality) to calculate the attributes value. If you clear this check box, the attributes quality is always Good, and the timestamp is always the objects startup time.
  5. 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.)
  6. 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.
  7. In the Value box, enter the attributes default value.
  8. Click the shield icon next to the Value box and select the attributes security classification. For available options, see ArchestrA Security Classifications.
  9. 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.
  10. 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 objects “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 doesnt appear in the Galaxy Browser or Object Viewer by default. Other objects can still access the hidden attribute, but regular users wont 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 attributes 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. Lets 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:

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 objects 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 attributes 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. Lets 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:

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:

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 its 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:

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 attributes 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 attributes 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 dont support historization. For example, attributes that exist only at config time cant 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 primitives 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 attributes 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 attributes 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 attributes 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.
  5. 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 “.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 dont want this attribute, clear the check box.

  1. To lock or unlock any history option, click the padlock icon next to its input box. Locked options cant be changed at run time.
  2. 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 objects “ShortDesc” attribute is used. (Value cant be set at run time.)
EnableSwingingDoor Boolean Writeable_USC_Lockable Enable or disable swinging door storage. (Value cant 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 engines 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 cant be set at run time.)
RateDeadBand Float Writeable_USC_Lockable Deadband rate for swinging door storage. (Value cant be set at run time.)
RolloverValue Float Writeable_USC_Lockable Rollover value for Counter retrieval. (Value cant be set at run time.)
SampleCount Integer Writeable_USC_Lockable Number of samples to be stored in Active Image. (Value cant 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 attributes 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 primitives attributes, see Attributes of the Alarm Primitive.

We recommend that you lock any alarm settings that you dont 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 “.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 dont want this attribute, clear the check box.

  1. To lock or unlock any alarm option, click the padlock icon next to its input box. Locked options cant be changed at run time.
  2. 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. Its 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 objects “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:

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

For virtual input primitives, you can use the primitives 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 objects 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, youll 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:

Output1.Value = myValue;

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

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

For virtual output primitives, you can use the primitives 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 objects 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, youll 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 objects 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 primitives 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 objects 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.
  13. 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, youll 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 objects 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:

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

For editor code, use the following:

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 VTQs time stamp and quality:

DateTime TimeStamp
CMxDataQualith Quality

To support buffer processing at run time

  1. Declare a VtqBufferReader in your objects Run-time class definition. For example:
    VtqBufferReader Reader;
  1. Initialize the VtqBufferReader in the Run-time Startup code. For example:
    Reader = new VtqBufferReader(this, "me.Attribute1");
  1. Process the buffer in the Run-time Execute code. For example:
    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:
    VtqBufferWriter vtqBufWriter;
  1. Initialize the VtqBufferWriter. For example:
    vtqBufWriter = new VtqBufferWriter ();
  1. Create instances of Value, Time, and Quality. For example:
    Bool V = true;
    DateTime T = DateTime.Now;
    CMxDataQuality Q = new CMxDataQuality(DataQuality.DataQualityGood);
  1. Add multiple VTQs to VtqBufferWriter. For example:
    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:
    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.

  2. In the Object Design View, expand the Attributes folder. Expand the attribute name.

  3. 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.

  4. 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.
  5. 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.

  6. 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.