Custom Transformation Plugins - The Service Component

IMPORTANT: Developing custom plugins as described in this section involves the use of Microsoft's Visual Studio integrated development environment (IDE) for Windows. It is not recommended for anyone who is unfamiliar with Visual Studio, C# Development, or object orientated programming.

The [TransformationName].cs file is the component used by the service.

The only thing that should be modified in the [TransformationName].cs class is the Transform(Tag t, string name, string ValueIn) method. This method is responsible for performing the manipulation of the tag data. Tag t is the tag to be transformed. The string “name” is the name of the transformation. The “name” is a user-specified identifier for the individual transformations created by user. Not to be confused with Global.Name that reflects the kind of transformation and the overall assembly. The string “ValueIn” is the value that gets transformed. ValueIn initially represents the tag’s InputValue and is used to store the transformed value in between transformations. Since a tag may have multiple transformations, the final output value should not be changed until each transformation has been processed. This brings us to an important requisite:

When modifying output, please use t.TempOutput to store the newly transformed value. Updating this value (and not t.Output) is critical for it to function correctly.

The first part of Transform is checking if ValueIn == “error” and returning if it is. Unless your transformation specifically calls for handling inputs of “error”, this should be left alone.  If a tag is in “error”, the alarm state will show the error message if it is coming from another transformation. The last thing we would want to do is overwrite the AlarmState of the error-inducing transformation, making it unclear where the error is originally coming from.



In MyTransformation, we retrieve the user specified value (stored in the transformation table) and compare it with ValueIn. The output depends on the result of the comparison and the state value from the transformation table.

Now, let’s declare some local variables. IMPORTANT: Local variables should be declared here, inside Transform() and NOT at the class level. Declaring variables at the class level may yield unpredictable results due to the multi-threading nature of the main program.


Here we have set up a double to store the user specified value and a string for the result of the comparison (whether it is “State-X” or “State-Y”).



We set the userSpecifiedValue equal to the row[“User Specified Value”] from the data table. Next, we compare it to ValueInAsDouble (ValueIn converted to a double). We set the condition to “X” or “Y” based on the result. After the comparison, t.TempOutput is changed to equal the text from the row [“State-X Label] or [“State-Y Label”], depending on the result.