Creating an Application Object script using GRAccess

by Klaus Graefensteiner 3/31/2008 2:31:13 AM

Introduction

The GRAccess toolkit enables developers to automate activities that users normally perform manually using the Industrial Application Server Integrated Development Environment (IDE). This blog post describes how to create and configure a DataChange Script using a C# console application.

Prerequisites

To execute the GRAccess sample application that is described in this document, you will need the following prerequisites:

  1. Visual Studio 2005
  2. Industrial Application Server 2.1 or higher

Using the IDE to create and configure a DataChange script

Before I start automating IDE tasks using GRAccess, I describe the manual IDE configuration steps that are going to be automated.

First create an object instance of the $UserDefined template. Give the new object the name "UserDefined_001" and open its editor.

In the "UDAs" tab of the editor add a new boolean User Defined Attribute called "Switch" that will be used later as the trigger of the DataChange script.

UDAs Editor Tab in IDE

After the UDA has been created go to the "Scripts" tab of the object editor and start configuring the DataChange script. First declare a variable in the "Declarations" section. This variable will be in scope during the whole runtime of the object. Use the following statement for the declaration:

   1: Dim Number as Integer;

In the "Scripts" tab add a new script and name it "HelloWorld". In the "Expression" field write "me.Switch". Select "DataChange" as "Trigger Type". Write the following script as body of the "HelloWorld" script:

   1: LogMessage("Hello World!");
   2: LogMessage("Number of ScanState changes: " + StringFromIntg(Number, 10));
   3: Number = Number + 1;

The following screen shot shows the script settings in the editor:

Script Extension Editor

What happened under the hood?

This paragraph describes in GRAccess API terms what happened under the hood during the configuration of the "UserDefined_001" object:

Create the object instance

Query the Galaxies and Login
   1: Galaxies = GR.QueryGalaxies(GRMachineName);
   2: G = Galaxies[GalaxyName];
   3: G.Login(UserName, Password);
Get the $UserDefined template and create a new object instance
   1: // Find $UserDefined template
   2: Objects = G.QueryObjectsByName(EgObjectIsTemplateOrInstance.gObjectIsTemplate, ref Names);
   3: T = (ITemplate)Objects[1];
   4: // Create instance of $UserDefined
   5: ObjectInstance = T.CreateInstance(ObjectName, true);
Checkout the object
   1: ObjectInstance.CheckOut();
Add new User Defined Attribute
   1: // Add UDA
   2: ObjectInstance.AddUDA(TriggerUDAName, 
   3:                         MxDataType.MxBoolean, 
   4:                         MxAttributeCategory.MxCategoryWriteable_USC_Lockable, 
   5:                         MxSecurityClassification.MxSecurityFreeAccess, false, null);
Save the object

This step is important. Saving the object at this point will generate the new attribute and make it accessible to the configuration steps to follow.

   1: ObjectInstance.Save();

Create the DataChange script

At this point we are ready to add and configure the script (Script Extension Primitive). First we add a new script into the list of scripts. Then we save the object. This will generate all the attributes required to configure the script the conventional way. Here is the list of the configurable attributes of the ScriptExtension primitive:

Attribute Name Comment
ExecuteText  
AliasReferences  
Aliases  
TriggerType  
DataChangeDeadband  
Expression  
DeclarationsText  
StartupText  
ShutdownText  
OnScanText  
OffScanText  
ExecutionError.Alarmed  
TriggerPeriod  
ScriptExecutionGroup  
ScriptOrder  
RunsAsync  
State.Historized  
ExecuteTimeout.Limit  
TriggerOnQualityChange New in 3.0
Add the Script Extension Primitive
   1: ObjectInstance.AddExtensionPrimitive("ScriptExtension", DataChangeScriptName, true);
Save the object and generate script attributes
   1: ObjectInstance.Save();
Configure the Script Extension attributes
   1: IAttribute ScriptBodyTextAttribute = ObjectInstance.ConfigurableAttributes[DataChangeScriptName + ".ExecuteText"];
   2: IAttribute ScriptDeclarationsTextAttribute = ObjectInstance.ConfigurableAttributes[DataChangeScriptName + ".DeclarationsText"];
   3: IAttribute ScriptTriggerTypeAttribute = ObjectInstance.ConfigurableAttributes[DataChangeScriptName + ".TriggerType"];
   4: IAttribute ScriptExpessionAttribute = ObjectInstance.ConfigurableAttributes[DataChangeScriptName + ".Expression"];
   5:  
   6: MxValue v = new MxValueClass();
   7:  
   8:  
   9: //Setting the script delarations text
  10: v.PutString("dim " + TriggerCounterVariableName + " as Integer;");
  11: ScriptDeclarationsTextAttribute.SetValue(v);
  12:  
  13: //Setting the script type
  14: v.PutString("DataChange");
  15: ScriptTriggerTypeAttribute.SetValue(v);
  16:  
  17: //Setting the script Expression
  18: v.PutString("me." + TriggerUDAName);
  19: ScriptExpessionAttribute.SetValue(v);
  20:  
  21: //Setting the scripts execute text
  22: v.PutString("LogMessage(\"Hello World!\");\n" +
  23: "LogMessage(\"Number of ScanState changes: \" + StringFromIntg("+ TriggerCounterVariableName + ", 10));\n" 
  24: + TriggerCounterVariableName + " = " +  TriggerCounterVariableName + " + 1;");
  25: ScriptBodyTextAttribute.SetValue(v);

The following screen shots show the now available Script Extension attributes.

Script Extension Attributes Part 1

Script Extension Attributes Part 2

Save the object and check it
   1: ObjectInstance.Save();
   2: ObjectInstance.CheckIn("");

Download source files

Click the following link to download the code sample files: CreateScriptExtension.zip

The complete source listing

Here is the complete listing of the program.cs file.

   1: using System;
   2: using System.Collections.Generic;
   3: using System.Text;
   4: using System.IO;
   5: using System.Xml;
   6:  
   7:  
   8: //GRAccess
   9: using ArchestrA.GRAccess;
  10:  
  11:  
  12: namespace CreateFieldAttributes
  13: {
  14:     class Program
  15:     {
  16:         static void Main(string[] args)
  17:         {
  18:  
  19:             #region Command Line Argument Parsing
  20:  
  21:  
  22:             //("CreateOPCClient Usage:");
  23:             //("+++++++++++++++++++++");
  24:  
  25:             //("   g=<Galaxy Name>");
  26:             //("   gr=<GR Server Node>");
  27:             //("   u=<User Name>");
  28:             //("   pw=<Password>");
  29:             //("   on=<UserDefined Object Name>");
  30:             //("   dc=<Name of UDA that triggers data change script>");
  31:             //("   sn=<Name of data change script>");
  32:             //("   vn=<Name of trigger counter variable>";
  33:  
  34:             //("   -> The order of the parameters doesn't matter!");
  35:             //("   -> There must be 8 parameters!");
  36:             //("   -> Use empty space characters to separate parameter=value pairs!");
  37:             //("   -> Don't use commas or semi-colon to separate parameter=value pairs!");
  38:             //("   -> The parameter=value pairs can't be longer than 254 characters!");
  39:             //("   -> The parameter specifier can't be longer than 2 characters!");
  40:  
  41:             //("   Example:");
  42:             //("   CreateScript gr=localhost g=PENGUINS u=Administrator pw=ww on=UserDefined_001 
  43:             //                     dc=Switch sn=HelloWorld vn=Counter");
  44:  
  45:             //Initialize dictionary
  46:             Dictionary<string, string> CmdParams = new Dictionary<string, string>(9);
  47:  
  48:             CmdParams.Add("gr", Environment.MachineName);
  49:             CmdParams.Add("g", "");
  50:             CmdParams.Add("u", "");
  51:             CmdParams.Add("pw", "");
  52:             CmdParams.Add("on", "");
  53:             CmdParams.Add("dc", "");
  54:             CmdParams.Add("sn", "");
  55:             CmdParams.Add("vn", "");
  56:  
  57:             if (args.GetLength(0) != CmdParams.Count)
  58:             {
  59:                 PrintHelp();
  60:                 return;
  61:             }
  62:             else
  63:             {
  64:                 foreach (string s in args)
  65:                 {
  66:                     if (s.Length > 255)
  67:                     {
  68:                         PrintHelp();
  69:                         return;
  70:                     }
  71:  
  72:                     if (s.IndexOf('=') > 2)
  73:                     {
  74:                         PrintHelp();
  75:                         return;
  76:                     }
  77:  
  78:                     if (s.Split('=').GetLength(0) != 2)
  79:                     {
  80:                         PrintHelp();
  81:                         return;
  82:                     }
  83:                     else
  84:                     {
  85:                         try
  86:                         {
  87:                             string temp = CmdParams[(s.Split('='))[0]];
  88:                         }
  89:                         catch
  90:                         {
  91:                             PrintHelp();
  92:                             return;
  93:                         }
  94:  
  95:                         CmdParams[(s.Split('='))[0]] = ((s.Split('='))[1]);
  96:                     }
  97:                 }
  98:             }
  99:  
 100:             if (0 == String.Compare(CmdParams["gr"], "localhost", true))
 101:             {
 102:                 CmdParams["gr"] = Environment.MachineName;
 103:             }
 104:  
 105:             string GRMachineName = CmdParams["gr"];
 106:             string GalaxyName = CmdParams["g"]; ;
 107:             string UserName = CmdParams["u"]; ;
 108:             string Password = CmdParams["pw"];
 109:             string ObjectName = CmdParams["on"];
 110:             string TriggerUDAName = CmdParams["dc"];
 111:             string DataChangeScriptName = CmdParams["sn"];
 112:             string TriggerCounterVariableName = CmdParams["vn"];
 113:  
 114:             #endregion
 115:             #region GRAccess Login
 116:             ICommandResult CR;
 117:             IGalaxies Galaxies;
 118:             IGalaxy G;
 119:             IgObjects Objects;
 120:             ITemplate T;
 121:             IInstance ObjectInstance;
 122:             GRAccessAppClass GR = new GRAccessAppClass();
 123:  
 124:             Galaxies = GR.QueryGalaxies(GRMachineName);
 125:  
 126:             if (Galaxies == null || GR.CommandResult.Successful == false)
 127:             {
 128:                 System.Console.Out.WriteLine(GR.CommandResult.Text + " : " + GR.CommandResult.CustomMessage);
 129:                 return;
 130:             }
 131:  
 132:             G = Galaxies[GalaxyName];
 133:  
 134:             if (G == null)
 135:             {
 136:                 System.Console.Out.WriteLine("Galaxy {0} not found on server {1}!", GalaxyName, GRMachineName);
 137:                 return;
 138:             }
 139:  
 140:             G.Login(UserName, Password);
 141:             CR = GR.CommandResult;
 142:             if (!CR.Successful)
 143:             {
 144:                 System.Console.Out.WriteLine("Login Galaxy Failed: " + CR.Text + " : " + CR.CustomMessage);
 145:                 return;
 146:             }
 147:             else
 148:             {
 149:                 System.Console.Out.WriteLine("Login Galaxy Successful!");
 150:             }
 151:  
 152:             #endregion
 153:             #region Create Instance of $UserDefined
 154:             string[] Names = { "$UserDefined" };
 155:  
 156:             // Find $UserDefined template
 157:             Objects = G.QueryObjectsByName(EgObjectIsTemplateOrInstance.gObjectIsTemplate, ref Names);
 158:  
 159:             CR = G.CommandResult;
 160:             if (!CR.Successful)
 161:             {
 162:                 System.Console.Out.WriteLine("QueryObjectsByName Failed for $UserDefined Template: " +
 163:                                  CR.Text + " : " +
 164:                                  CR.CustomMessage);
 165:                 return;
 166:             }
 167:  
 168:  
 169:             T = (ITemplate)Objects[1];
 170:  
 171:  
 172:             // Create instance of $UserDefined
 173:             ObjectInstance = T.CreateInstance(ObjectName, true);
 174:             CR = T.CommandResult;
 175:             if (!CR.Successful)
 176:             {
 177:                 System.Console.Out.WriteLine("Create Instance failed for " + ObjectName + " :" +
 178:                                  CR.Text + " : " +
 179:                                  CR.CustomMessage);
 180:             }
 181:  
 182:             #endregion
 183:             #region Create Trigger UDA of type Boolean
 184:  
 185:  
 186:             ObjectInstance.CheckOut();
 187:  
 188:             // Add UDA
 189:             ObjectInstance.AddUDA(TriggerUDAName, MxDataType.MxBoolean, MxAttributeCategory.MxCategoryWriteable_USC_Lockable, MxSecurityClassification.MxSecurityFreeAccess, false, null);
 190:             CR = ObjectInstance.CommandResult;
 191:             if (!CR.Successful)
 192:             {
 193:                 Console.WriteLine("Adding UDA " + TriggerUDAName + " to " + ObjectName + " failed: " +
 194:                                  CR.Text + " : " +
 195:                                  CR.CustomMessage);
 196:                 ObjectInstance.CheckIn("");
 197:                 return;
 198:             }
 199:  
 200:             ObjectInstance.Save();
 201:  
 202:             #endregion
 203:             #region Add DataChange Script
 204:  
 205:             ObjectInstance.AddExtensionPrimitive("ScriptExtension", DataChangeScriptName, true);
 206:             CR = ObjectInstance.CommandResult;
 207:             if (!CR.Successful)
 208:             {
 209:                 Console.WriteLine("AddExtensionPrimitive failed!" +
 210:                                  CR.Text + " : " +
 211:                                  CR.CustomMessage);
 212:                 return;
 213:             }
 214:  
 215:             ObjectInstance.Save();
 216:             CR = ObjectInstance.CommandResult;
 217:             if (!CR.Successful)
 218:             {
 219:                 Console.WriteLine("Save failed" +
 220:                                  CR.Text + " : " +
 221:                                  CR.CustomMessage);
 222:                 return;
 223:             }
 224:  
 225:             #endregion
 226:             #region Edit DataChange Script
 227:  
 228:             //Configurable attributes of the Scripting Primitive
 229:             //(".ExecuteText");
 230:             //(".AliasReferences");
 231:             //(".Aliases");
 232:             //(".TriggerType");
 233:             //(".DataChangeDeadband");
 234:             //(".Expression");
 235:             //(".DeclarationsText");
 236:             //(".StartupText");
 237:             //(".ShutdownText");
 238:             //(".OnScanText");
 239:             //(".OffScanText");
 240:             //(".ExecutionError.Alarmed");
 241:             //(".TriggerPeriod");
 242:             //(".ScriptExecutionGroup");
 243:             //(".ScriptOrder");
 244:             //(".RunsAsync");
 245:             //(".State.Historized");
 246:             //(".ExecuteTimeout.Limit");
 247:             //(".TriggerOnQualityChange"); //(New in WAS 3.0)
 248:             
 249:             IAttribute ScriptBodyTextAttribute = ObjectInstance.ConfigurableAttributes[DataChangeScriptName + ".ExecuteText"];
 250:             IAttribute ScriptDeclarationsTextAttribute = ObjectInstance.ConfigurableAttributes[DataChangeScriptName + ".DeclarationsText"];
 251:             IAttribute ScriptTriggerTypeAttribute = ObjectInstance.ConfigurableAttributes[DataChangeScriptName + ".TriggerType"];
 252:             IAttribute ScriptExpessionAttribute = ObjectInstance.ConfigurableAttributes[DataChangeScriptName + ".Expression"];
 253:  
 254:             MxValue v = new MxValueClass();
 255:  
 256:             
 257:             //Setting the script delarations text
 258:             v.PutString("dim " + TriggerCounterVariableName + " as Integer;");
 259:             ScriptDeclarationsTextAttribute.SetValue(v);
 260:  
 261:             //Setting the script type
 262:             v.PutString("DataChange");
 263:             ScriptTriggerTypeAttribute.SetValue(v);
 264:  
 265:             //Setting the script Expression
 266:             v.PutString("me." + TriggerUDAName);
 267:             ScriptExpessionAttribute.SetValue(v);
 268:  
 269:             //Setting the scripts execute text
 270:             v.PutString("LogMessage(\"Hello World!\");\n" +
 271:             "LogMessage(\"Number of ScanState changes: \" + StringFromIntg("+ TriggerCounterVariableName + ", 10));\n" 
 272:             + TriggerCounterVariableName + " = " +  TriggerCounterVariableName + " + 1;");
 273:             ScriptBodyTextAttribute.SetValue(v);
 274:  
 275:  
 276:             ObjectInstance.Save();
 277:             CR = ObjectInstance.CommandResult;
 278:             if (!CR.Successful)
 279:             {
 280:                 Console.WriteLine("Save failed" +
 281:                                  CR.Text + " : " +
 282:                                  CR.CustomMessage);
 283:                 return;
 284:             }
 285:  
 286:             ObjectInstance.CheckIn("");
 287:             CR = ObjectInstance.CommandResult;
 288:             if (!CR.Successful)
 289:             {
 290:                 Console.WriteLine("Checkin failed" +
 291:                                  CR.Text + " : " +
 292:                                  CR.CustomMessage);
 293:                 return;
 294:             }
 295:             #endregion
 296:             System.Console.Out.WriteLine(ObjectName + " has been successfully created and configured!");
 297:         }
 298:         #region Helper Methods
 299:         static void PrintHelp()
 300:         {
 301:             System.Console.Write("\n\n\n");
 302:             System.Console.Out.WriteLine("   g=<Galaxy Name>");
 303:             System.Console.Out.WriteLine("   gr=<GR Server Node>");
 304:             System.Console.Out.WriteLine("   u=<User Name>");
 305:             System.Console.Out.WriteLine("   pw=<Password>");
 306:             System.Console.Out.WriteLine("   dc=<Name of UDA that triggers data change script>");
 307:             System.Console.Out.WriteLine("   sn=<Name of data change script>");
 308:             System.Console.Out.WriteLine("   vn=<Name of trigger counter variable>");
 309:  
 310:             System.Console.Out.WriteLine("   -> The order of the parameters doesn't matter!");
 311:             System.Console.Out.WriteLine("   -> There must be 8 parameters!");
 312:             System.Console.Out.WriteLine("   -> Use empty space characters to separate parameter=value pairs!");
 313:             System.Console.Out.WriteLine("   -> Don't use commas or semi-colon to separate parameter=value pairs!");
 314:             System.Console.Out.WriteLine("   -> The parameter=value pairs can't be longer than 254 characters!");
 315:             System.Console.Out.WriteLine("   -> The parameter specifier can't be longer than 2 characters!");
 316:  
 317:             System.Console.Out.WriteLine("   Example:");
 318:             System.Console.Out.WriteLine("   CreateScript gr=localhost g=PENGUINS u=Administrator pw=ww on=UserDefined_001 dc=Switch sn=HelloWorld vn=Counter");
 319:         }
 320:         #endregion
 321:     }
 322: }

Compilation

To compile the program.cs file run the following command in the Visual Studio 2005 command prompt:

   1: csc /out:CreateScript.exe program.cs /r:"C:\Program Files\Common Files\
   2: ArchestrA\ArchestrA.GRAccess.dll"

Test run

To execute CreateScript.exe run the following command:

   1: CreateScript gr=localhost g=PENGUINS u=Administrator pw=ww on=UserDefined_001 dc=Switch sn=HelloWorld vn=Number
   2:  

Summary

Creating a script using GRAccess is a two-step process. First the Script Extension Primitive needs to be added to the object using the AddExtension() method. Saving the object will then generate the attributes that are required to configure the script. Setting these Script Extension Attributes in the usual way is the second step.

Currently rated 5.0 by 1 people

  • Currently 5/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags: ,

C# | GRAccess Toolkit | Toolkits | Wonderware

Related posts

Comments

4/14/2008 11:30:34 PM

Klaus

Test, Test, Test

Klaus us

Comments are closed

Powered by BlogEngine.NET 1.3.0.0
Vanilla Theme by Klaus Graefensteiner

About Klaus Graefensteiner

GRAVATAR icon of Klaus Graefensteiner I enjoy the programming of machines.

E-mail me Send mail
Blogroll as OPML OPML LinkedIn Profile View Klaus Graefensteiner's LinkedIn profile

Calendar

<<  January 2009  >>
MoTuWeThFrSaSu
2930311234
567891011
12131415161718
19202122232425
2627282930311
2345678

View posts in large calendar

Recent comments

Disclaimer

The opinions expressed herein are my own personal opinions and do not represent my employer's view in anyway.

© Copyright 2009

Sign in