Adding and Configuring a FieldAttribute to a derived template of $UserDefined

by Klaus Graefensteiner 3/24/2008 12:06:53 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 FieldAttribute to a $UserDefined template 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 add FieldAttributes to a derived template of $UserDefined

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

First create a derived template of the $UserDefined template. Give the new derived template the name "$UserDefined_021" and open the editor of the template.

Editor page of Field Attribute of type Integer

In the "Field Attributes" tab of the editor add a new analog Field Attribute called "AF_001" and a new discrete Field Attribute called "DF_001" to the Field Attributes list.

Editor page of Field Attribute of type Boolean

Change the "Input source" property of the new Analog Field Attribute "AF_001" to "T10.PV" and the "Input source" property of the new Discrete Field Attribute "DF_001" to "T10.InHiHi".

 

What happened under the hood?

This paragraph describes in GRAccess API terms what happened under the hood during the configuration of the $UserDefined_021" template:

Create the derived template

Query the Galaxies and Login
   1: Galaxies = GR.QueryGalaxies(GRMachineName);
   2: G = Galaxies[GalaxyName];
   3: G.Login(UserName, Password);
Get the $UserDefined template and derive a new template
   1: string[] Names = { "$UserDefined" };
   2: Objects = G.QueryObjectsByName(EgObjectIsTemplateOrInstance.gObjectIsTemplate, ref Names);
   3: T = (ITemplate)Objects[1];
   4: Parent = T.CreateTemplate(UDOTemplateName, true);
Checkout template
   1: Parent.CheckOut();
Add new FieldAttributes

This step is the key to successfully applying the GRAccess API in this case. Knowing that the list of Field Attributes gets maintained by a XML string in the Attribute "UserAttrData" is crucial. Adding a new Analog Field Attribute can be accomplished by inserting a <AnalogAttr> element into the XML string of the UserAttrData attribute. The "name" XML attribute of the <AnalogAttr> element gives the new Field Attribute its name. Creating a Discrete Field Attribute works the same way. First insert a <DiscreteAttr> XML element and set the name XML attribute equal to the name that you would like the Field Attribute to be called.

UserAttrData Attribute in the Properties tab of the User Defined Object

   1: IAttributes UDOAttributes = Parent.ConfigurableAttributes;
   2: IAttribute UDOUserAttrDataAttribute = UDOAttributes["UserAttrData"];
   3: IAttribute DiscreteFieldAttribute;
   4: IAttribute AnalogFieldAttribute;
   5: MxValue MxVal = new MxValueClass();
   6: MxVal.PutString("<AttrXML><DiscreteAttr Name=\"" + DiscreteFieldAttributeName + "\"/><AnalogAttr Name=\"" + AnalogFieldAttributeName + "\"/></AttrXML>");
   7: UDOUserAttrDataAttribute.SetValue(MxVal);
Save the template

This step is also very important. Saving the object at this point will process the XML string of the UserAttrData attribute and generate on the fly new attributes representing the Field Attributes that we just added.

   1: Parent.Save();

Configure the Input Source properties

At this point we are able to configure the Field Attribute the conventional way.

Set the Input Source of the Discrete Field Attribute

Discrete Field Attribute Properties

   1: //Now configure attributes as usual
   2: UDOAttributes = Parent.ConfigurableAttributes;
   3: DiscreteFieldAttribute = UDOAttributes[DiscreteFieldAttributeName + ".Input.InputSource"];
   4: IMxReference MXRef;
   5: MXRef = DiscreteFieldAttribute.value.GetMxReference();
   6: MXRef.FullReferenceString = DiscreteFieldAttributeReferenceName;
   7: MxVal.PutMxReference(MXRef);
   8: DiscreteFieldAttribute.SetValue(MxVal);
   9: Parent.Save();

Set the Input Source of the Analog Field Attribute

Analog Field Attribute Properties

   1: //Now configure attributes as usual
   2: UDOAttributes = Parent.ConfigurableAttributes;
   3: AnalogFieldAttribute = UDOAttributes[AnalogFieldAttributeName + ".Input.InputSource"];
   4: MXRef = AnalogFieldAttribute.value.GetMxReference();
   5: MXRef.FullReferenceString = AnalogFieldAttributeReferenceName;
   6: MxVal.PutMxReference(MXRef);
   7: AnalogFieldAttribute.SetValue(MxVal);
   8: Parent.Save();
Save and CheckIn
   1: Parent.Save();
   2: Parent.CheckIn("");

Download source files

Click the following link to download the code sample files: createfieldattribute.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:             //("   un=<UserDefined Template Name>. Templates start with '$'!");
  30:             //("   af=<Analog Field Attribute Name>");
  31:             //("   df=<Discrete Field Attribute Name>");
  32:             //("   ar=<Name of Input Reference of Analog Field Attribute>");
  33:             //("   dr=<Name of Input Reference of Discrete Field Attribute>");
  34:  
  35:             //("   -> The order of the parameters doesn't matter!");
  36:             //("   -> There must be 9 parameters!");
  37:             //("   -> Use empty space characters to separate parameter=value pairs!");
  38:             //("   -> Don't use commas or semi-colon to separate parameter=value pairs!");
  39:             //("   -> The parameter=value pairs can't be longer than 254 characters!");
  40:             //("   -> The parameter specifier can't be longer than 2 characters!");
  41:  
  42:             //("   Example:");
  43:             //("   CreateOPCClient gr=localhost g=PENGUINS u=Administrator pw=ww on=$OPCClient_01 
  44:             //                     os=ArchestrA.DASABTCP.1 oc=localhost og=Group1 oi1=N100:1 
  45:             //                     oa1=Counter_1 oi2=N200:1 oa2=Counter_2");
  46:  
  47:             //Initialize dictionary
  48:             Dictionary<string, string> CmdParams = new Dictionary<string, string>(9);
  49:  
  50:             CmdParams.Add("gr", Environment.MachineName);
  51:             CmdParams.Add("g", "");
  52:             CmdParams.Add("u", "");
  53:             CmdParams.Add("pw", "");
  54:             CmdParams.Add("un", "");
  55:             CmdParams.Add("df", "");
  56:             CmdParams.Add("af", "");
  57:             CmdParams.Add("dr", "");
  58:             CmdParams.Add("ar", "");
  59:  
  60:             if (args.GetLength(0) != CmdParams.Count)
  61:             {
  62:                 PrintHelp();
  63:                 return;
  64:             }
  65:             else
  66:             {
  67:                 foreach (string s in args)
  68:                 {
  69:                     if (s.Length > 255)
  70:                     {
  71:                         PrintHelp();
  72:                         return;
  73:                     }
  74:  
  75:                     if (s.IndexOf('=') > 2)
  76:                     {
  77:                         PrintHelp();
  78:                         return;
  79:                     }
  80:  
  81:                     if (s.Split('=').GetLength(0) != 2)
  82:                     {
  83:                         PrintHelp();
  84:                         return;
  85:                     }
  86:                     else
  87:                     {
  88:                         try
  89:                         {
  90:                             string temp = CmdParams[(s.Split('='))[0]];
  91:                         }
  92:                         catch
  93:                         {
  94:                             PrintHelp();
  95:                             return;
  96:                         }
  97:  
  98:                         CmdParams[(s.Split('='))[0]] = ((s.Split('='))[1]);
  99:                     }
 100:                 }
 101:             }
 102:  
 103:             if (0 == String.Compare(CmdParams["gr"], "localhost", true))
 104:             {
 105:                 CmdParams["gr"] = Environment.MachineName;
 106:             }
 107:  
 108:             string GRMachineName = CmdParams["gr"];
 109:             string GalaxyName = CmdParams["g"]; ;
 110:             string UserName = CmdParams["u"]; ;
 111:             string Password = CmdParams["pw"];
 112:             string UDOTemplateName = CmdParams["un"];
 113:             string DiscreteFieldAttributeName = CmdParams["df"];
 114:             string AnalogFieldAttributeName = CmdParams["af"];
 115:             string DiscreteFieldAttributeReferenceName = CmdParams["dr"];
 116:             string AnalogFieldAttributeReferenceName = CmdParams["ar"];
 117:  
 118:             #endregion
 119:             #region GRAccess Login
 120:             ICommandResult CR;
 121:             IGalaxies Galaxies;
 122:             IGalaxy G;
 123:             IgObjects Objects;
 124:             ITemplate T;
 125:             ITemplate Parent;
 126:             GRAccessAppClass GR = new GRAccessAppClass();
 127:  
 128:             Galaxies = GR.QueryGalaxies(GRMachineName);
 129:  
 130:             if (Galaxies == null || GR.CommandResult.Successful == false)
 131:             {
 132:                 System.Console.Out.WriteLine(GR.CommandResult.Text + " : " + GR.CommandResult.CustomMessage);
 133:                 return;
 134:             }
 135:  
 136:             G = Galaxies[GalaxyName];
 137:  
 138:             if (G == null)
 139:             {
 140:                 System.Console.Out.WriteLine("Galaxy {0} not found on server {1}!", GalaxyName, GRMachineName);
 141:                 return;
 142:             }
 143:  
 144:             G.Login(UserName, Password);
 145:             CR = GR.CommandResult;
 146:             if (!CR.Successful)
 147:             {
 148:                 System.Console.Out.WriteLine("Login Galaxy Failed: " + CR.Text + " : " + CR.CustomMessage);
 149:                 return;
 150:             }
 151:             else
 152:             {
 153:                 System.Console.Out.WriteLine("Login Galaxy Successful!");
 154:             }
 155:  
 156:             #endregion
 157:             #region Create Derived Template from $UserDefined
 158:             string[] Names = { "$UserDefined" };
 159:  
 160:             Objects = G.QueryObjectsByName(EgObjectIsTemplateOrInstance.gObjectIsTemplate, ref Names);
 161:  
 162:             CR = G.CommandResult;
 163:             if (!CR.Successful)
 164:             {
 165:                 System.Console.Out.WriteLine("QueryObjectsByName Failed for $UserDefined Template: " +
 166:                                  CR.Text + " : " +
 167:                                  CR.CustomMessage);
 168:                 return;
 169:             }
 170:  
 171:  
 172:             T = (ITemplate)Objects[1];
 173:  
 174:  
 175:             Parent = T.CreateTemplate(UDOTemplateName, true);
 176:             CR = T.CommandResult;
 177:             if (!CR.Successful)
 178:             {
 179:                 System.Console.Out.WriteLine("Create Template failed for " + UDOTemplateName + " :" +
 180:                                  CR.Text + " : " +
 181:                                  CR.CustomMessage);
 182:             }
 183:  
 184:             #endregion
 185:             #region Configure Derived $UserDefined Template
 186:  
 187:  
 188:             Parent.CheckOut();
 189:  
 190:             IAttributes UDOAttributes = Parent.ConfigurableAttributes;
 191:             IAttribute UDOUserAttrDataAttribute = UDOAttributes["UserAttrData"];
 192:             IAttribute DiscreteFieldAttribute;
 193:             IAttribute AnalogFieldAttribute;
 194:  
 195:             if (UDOUserAttrDataAttribute == null)
 196:             {
 197:                 CR = Parent.CommandResult;
 198:                 System.Console.WriteLine("Attribute UserAttrData not found: " +
 199:                 CR.Text + " : " +
 200:                 CR.CustomMessage);
 201:                 Parent.CheckIn("");
 202:                 return;
 203:             }
 204:  
 205:             //First Add the new FieldAttributes using the UserAttrData attribute
 206:             MxValue MxVal = new MxValueClass();
 207:             MxVal.PutString("<AttrXML><DiscreteAttr Name=\"" + DiscreteFieldAttributeName + "\"/><AnalogAttr Name=\"" + AnalogFieldAttributeName + "\"/></AttrXML>");
 208:             UDOUserAttrDataAttribute.SetValue(MxVal);
 209:             
 210:             CR = Parent.CommandResult;
 211:             if (!CR.Successful)
 212:             {
 213:  
 214:                 System.Console.WriteLine("Setting XML String failed: " +
 215:                 CR.Text + " : " +
 216:                 CR.CustomMessage);
 217:                 Parent.CheckIn("");
 218:             }
 219:             Parent.Save();
 220:  
 221:  
 222:             //Now configure attributes as usual
 223:             UDOAttributes = Parent.ConfigurableAttributes;
 224:             DiscreteFieldAttribute = UDOAttributes[DiscreteFieldAttributeName + ".Input.InputSource"];
 225:  
 226:             if (DiscreteFieldAttribute == null)
 227:             {
 228:                 CR = Parent.CommandResult;
 229:                 System.Console.WriteLine("Attribute " + DiscreteFieldAttributeName + ".Input.InputSource not found: " +
 230:                 CR.Text + " : " +
 231:                 CR.CustomMessage);
 232:                 Parent.CheckIn("");
 233:                 return;
 234:             }
 235:  
 236:             IMxReference MXRef;
 237:             MXRef = DiscreteFieldAttribute.value.GetMxReference();
 238:             if (MXRef == null)
 239:             {
 240:                 CR = Parent.CommandResult;
 241:                 System.Console.WriteLine("MXReference not found: " +
 242:                 CR.Text + " : " +
 243:                 CR.CustomMessage);
 244:                 Parent.CheckIn("");
 245:             }
 246:             else
 247:             {
 248:                 MXRef.FullReferenceString = DiscreteFieldAttributeReferenceName;
 249:  
 250:                 MxVal.PutMxReference(MXRef);
 251:                 DiscreteFieldAttribute.SetValue(MxVal);
 252:                 
 253:                 CR = Parent.CommandResult;
 254:  
 255:                 if (!CR.Successful)
 256:                 {
 257:                     System.Console.WriteLine("Setting MXReference String failed: " +
 258:                     CR.Text + " : " +
 259:                     CR.CustomMessage);
 260:                     Parent.CheckIn("");
 261:                 }
 262:             }
 263:             Parent.Save();
 264:  
 265:             //Now configure attributes as usual
 266:             UDOAttributes = Parent.ConfigurableAttributes;
 267:             AnalogFieldAttribute = UDOAttributes[AnalogFieldAttributeName + ".Input.InputSource"];
 268:  
 269:             if (DiscreteFieldAttribute == null)
 270:             {
 271:                 CR = Parent.CommandResult;
 272:                 System.Console.WriteLine("Attribute " + AnalogFieldAttributeName + ".Input.InputSource not found: " +
 273:                 CR.Text + " : " +
 274:                 CR.CustomMessage);
 275:                 Parent.CheckIn("");
 276:                 return;
 277:             }
 278:  
 279:             MXRef = AnalogFieldAttribute.value.GetMxReference();
 280:             if (MXRef == null)
 281:             {
 282:                 CR = Parent.CommandResult;
 283:                 System.Console.WriteLine("MXReference not found: " +
 284:                 CR.Text + " : " +
 285:                 CR.CustomMessage);
 286:                 Parent.CheckIn("");
 287:             }
 288:             else
 289:             {
 290:                 MXRef.FullReferenceString = AnalogFieldAttributeReferenceName;
 291:  
 292:                 MxVal.PutMxReference(MXRef);
 293:                 AnalogFieldAttribute.SetValue(MxVal);
 294:  
 295:                 CR = Parent.CommandResult;
 296:  
 297:                 if (!CR.Successful)
 298:                 {
 299:                     System.Console.WriteLine("Setting MXReference String failed: " +
 300:                     CR.Text + " : " +
 301:                     CR.CustomMessage);
 302:                     Parent.CheckIn("");
 303:                 }
 304:             }
 305:             Parent.Save();
 306:  
 307:  
 308:             Parent.CheckIn("");
 309:             #endregion
 310:  
 311:             System.Console.Out.WriteLine(UDOTemplateName + " has been successfully created and configured!");
 312:         }
 313:         #region Helper Methods
 314:         static void PrintHelp()
 315:         {
 316:             System.Console.Write("\n\n\n");
 317:             System.Console.Out.WriteLine("   g=<Galaxy Name>");
 318:             System.Console.Out.WriteLine("   gr=<GR Server Node>");
 319:             System.Console.Out.WriteLine("   u=<User Name>");
 320:             System.Console.Out.WriteLine("   pw=<Password>");
 321:             System.Console.Out.WriteLine("   un=<UserDefined Template Name>. Templates start with '$'!");
 322:             System.Console.Out.WriteLine("   af=<Analog Field Attribute Name>");
 323:             System.Console.Out.WriteLine("   df=<Discrete Field Attribute Name>");
 324:             System.Console.Out.WriteLine("   ar=<Name of Input Reference of Analog Field Attribute>");
 325:             System.Console.Out.WriteLine("   dr=<Name of Input Reference of Discrete Field Attribute>");
 326:  
 327:             System.Console.Write("\n\n");
 328:  
 329:             System.Console.Out.WriteLine("   -> The order of the parameters doesn't matter!");
 330:             System.Console.Out.WriteLine("   -> There must be 9 parameters!");
 331:             System.Console.Out.WriteLine("   -> Use empty space characters to separate parameter=value pairs!");
 332:             System.Console.Out.WriteLine("   -> Don't use commas or semi-colon to separate parameter=value pairs!");
 333:             System.Console.Out.WriteLine("   -> The parameter=value pairs can't be longer than 254 characters!");
 334:             System.Console.Out.WriteLine("   -> The parameter specifier can't be longer than 2 characters!");
 335:  
 336:             System.Console.Write("\n\n");
 337:             System.Console.Out.WriteLine("   Example:");
 338:             System.Console.Out.WriteLine("   CreateFieldAttributes gr=localhost g=PENGUINS u=Administrator pw=ww un=$UserDefined_001 af=AF_001 df=DF_001 ar=T10.PV dr=T10.InHiHi");
 339:         }
 340:         #endregion
 341:     }
 342: }

Compilation

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

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

Test run

To execute CreateFieldAttributes.exe run the following command:

   1: CreateFieldAttributes gr=localhost g=PENGUINS u=Administrator
   2: af=AF_001 df=DF_001 ar=T10.PV dr=T10.InHiHi

Summary

Knowing that the list of Field Attributes gets maintained by a XML string in the Attribute "UserAttrData" is crucial. Adding a new Analog Field Attribute can be accomplished by inserting a <AnalogAttr> element into the XML string of the UserAttrData attribute. The "name" XML attribute of the <AnalogAttr> element gives the new Field Attribute its name. Creating a Discrete Field Attribute works the same way. First insert a <DiscreteAttr> XML element and set the name XML attribute equal to the name that you would like the Field Attribute to be called.

Saving the object will process the XML string of the UserAttrData attribute and generate on the fly new attributes representing the Field Attributes that we just added. At this point we are able to configure the Field Attribute the conventional way.

Currently rated 5.0 by 2 people

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

Tags: ,

GRAccess Toolkit | Toolkits | Wonderware

Related posts

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