.Net Framework Functions
The .NET Framework functions are for configuring and evoking alarm type custom functions in the Expressions tab.
- Every .NET function must be a part of a .NET Framework class library, compiled for the same .NET Framework version as the Hyper Alarm Server host process. Implement functions in the function library as a public .NET class, where all public methods can be exposed as “custom functions.”
- To enable the method for use as a custom function, the expression text must be formatted in a specific way. The number of parameters must match the number of arguments declared in .NET method. The following syntax is used to configure a .NET function:
See the Function library design for additional information.
- Custom Functions: Design custom functions as synchronous or asynchronous processing.
- It's important to use synchronous functions for fast, non-blocking function implementations for fast, in-memory processing.
- Implement long-lasting or blocking calls using asynchronous methods to prevent blocking of other alarm sources evaluation.
- Design Rules:
- For synchronous methods, do not read data from external data sources directly from a function call (files, databases, etc.).
- Do not create large data collections with unpredictable length. This may end up with “out of memory” exceptions.
Throwing .NET exceptions is expensive! Do not use exceptions to handle standard processing errors.
The following table lists all possible input and output data types for function library methods. This data type definition applies to both synchronous and asynchronous function types.
See the Synchronous and Asynchronous method calls for additional information.
.NET Type
Description
Char (char)
A Unicode character
SByte (sbyte)
An Integer Value, range -128...127
Int16 (short)
An Integer Value, range -32,768...32,767
Int32 (int)
An Integer Value, range -2,147,483,648...2,147,483,647
Int64 (long)
An Integer Value, range -9,223,372,036,854,775,808...9,223,372,036,854,775,807
Byte (byte)
An Integer Value, range 0...255
UInt16 (ushort)
An Integer Value, range 0...65,535
UInt32 (uint)
An Integer Value, range 0...4,294,967,295
UInt64 (ulong)
An Integer Value, range 0...18,446,744,073,709,551,615
Double (double)
A Floating-point Value, range -1.79769313486232e308…1.79769313486232e308
Single (float)
A Floating-point Value, range -3.402823e38...3.402823e38
Boolean (bool)
True or False
String (string)
A string of Unicode characters.
DateTime
Represents an instant in time, value between January 1, 0001 and December 31, 9999 in the Gregorian calendar.
TimeSpan
Represents a time interval.
DataValue
A data value is a value, value status, source, and server timestamps, and is defined by FrameWorX infrastructure.
Variant
A value wrapped in FrameWorX friendly form and is used as a part of data value.
ExpressionValue
Data structure defined by expression engine – more native way to exchange values between evaluator and function library calls
Object
Unspecified data type. Used with care—it is always faster/better to use strongly-typed data types.
SByte[ ] (sbyte[ ])
An array of signed byte values.
Int16[ ] (short[ ])
An array of short values.
Int32[ ] (int[ ])
An array of integer values.
Int64[ ] (long[ ])
An array of long values.
Byte[ ] (byte[ ])
An array of byte values.
UInt16[ ] (ushort[ ])
An array of unsigned short values.
UInt32[ ] (uint[ ])
An array of unsigned integer values
UInt64[ ] (ulong[ ])
An array of unsigned long values.
Double[ ] (double[ ])
An array of double values.
Single[ ] (float[ ])
An array of float values.
Boolean[ ] (bool[ ])
An array of bool values.
String[ ] (string[ ])
An array of string values.
DateTime[ ]
An array of DateTime values.
TimeSpan[ ]
An array of TimeSpan values.
DataValue[ ]
An array of DataValue values (FrameWorX infrastructure type)
Variant[ ]
An array of Variant values (FrameWorX infrastructure type)
ExpressionValue[ ]
An array of ExpressionValue values (expression evaluation engine).
- Function Library Design: Each function library must be derived from FunctionLibrary base class, defined in AlmsRuntime.dll (namespace Ico.Alms.Runtime.Types.Expressions.CustomFunctions). An instance of the IExpressionDataAccess interface allows access to real-time, historical, and other data types fromHyper Alarm Server communication infrastructure. The following code snippet shows the most straightforward skeleton of a function library code without a deinitialization phase.
When the deinitialization procedure is necessary, the code can be enhanced by the IDisposable implementation.
- DataValue
- ExpressionValue
- ValueStatusCodePair<T>, where T can be any .NET type specified in the table above.
When data quality makes sense to return a custom function, the following data types are available:
All data structures support the quality (status) code formatted in a FrameWorX infrastructure-friendly way, such as StatusCode or aStatusCode numerical representation.
The FunctionLibrary base class also exposes a set of protected methods that you can use to read data from other data sources using FrameWorX infrastructure. These are asynchronous methods that are used in asynchronous method implementations.
- Synchronous Method Calls are the simplest way to implement methods for custom functions. However, you must only use the synchronous method calls for very fast, in-process data processing. The following code fragment is a simple example of synchronous method implementation.
- Asynchronous method calls are suitable when a function needs to access data outside of Hyper Alarm Server. For example, data accessible via the FrameWorX communication infrastructure (real-time, historical), database values, and so forth. To make a function asynchronous, use a standard .NET async pattern. The following code snippet modifies the synchronous example (listed above) to its asynchronous form—it only demonstrates an async pattern (the snippet does not make much sense to use in the real-world scenario.)
The following code snippet demonstrates a more helpful code method, which reads real-time values from a dynamically-defined point name and adds a constant value. Since a read of real-time value may fail and could return a bad quality value, this method handles such a situation.
This code snippet above demonstrates the use of DataPointReader class, which wraps a complete sequence of reading real-time points using the Hyper Alarm Server infrastructure. First, the point gets subscribed to and then waits for the initial value. Finally, the subscribed point is released.
Since asynchronous processing is built on top of the Hyper Alarm Server infrastructure, there is no need for the subscribe/release operations to be directly propagated to FrameWorX™ infrastructure. When a point is already subscribed (used as a source input), it returns the current data point value.
Another structure used in this code snippet is ValueStatusCodePair<T>. It is useful when a method returns a strongly typed value together with value quality. Another possibility is using either instance of DataValue class or ExpressionValue struct. Both contain value quality information and could return value timestamp if needed.