Obtaining a List of Objects

Collecting a list of objects such as tags, is a fundamental programming task.  For example, you may wish to collect all instances of pump status tags within an area for a report or WAP page.

Using only a few functions, you can search for tags of any type(s) you need and filter the resulting list by any criteria required.  The tools you will need include:

 

    ListVars - returns a list of the variables in a module that match a given set of criteria.

    PointList – a subroutine built into the VTS layer that uses ListVars to provide a very specific search feature.

    Scope - performs a scope resolution and returns an object reference to the requested member within a module or other object.  While not a search function itself, Scope is useful for both selecting what to search for, and for filtering the list returned from one of the above functions.

Let’s begin with an example:  The following subroutine will search for tags of a given type (Type) that are linked to a given driver (TagName).  If any are found, an array of these objects will be returned.

 

{====================== TagList ==================================}

{=================================================================}

TagList

(

  Type          { Type of variable to filter                 };

  TagName       { Name of driver tag                         };

)

[

  Class         { Variable class of the desired type of variable };

  VarList       { Array of Variable tag names                    };

  NumVars       { Number of tags of desired type                 };

  i             { Loop counter                                   };

  ObjList       { Array of desired objects                       };

  ReturnList    { ObjList reduced to only valid values           };

  TagObj        { Object of the Tag in the area to filter        };

  VarObj        { Object of variable type in main loop           };

]

 

Main [

  If watch(1);

  [

     { Get an object reference of the given tag name.  If TagName is the name of a polling driver, then TagObj will be an object reference to that tag. The purpose is to gain access to all the properties of that tag for the upcoming search }

    TagObj = Scope(\Code, TagName);

 

     { Get the class of the tag type to search for. This will be used in the ListVars search to set the upper and lower limits on the classes to be searched }

    Class = VariableClass(FindVariable(Type, \Code, 0, 0));

 

     { Get a list of the all tags in the application matching the requested type. }

    VarList = ListVars(\VTSDB, "*", Class, Class,

                      0 {Match All}, 0 {All}, 0 {Global}, 0 {Names} ,

                      1 { Sorted });

 

     { Get the number of Tags of this class }

    NumVars = ArraySize(VarList, 0);

 

     { Create an array into which the matching I/O tags will be placed }

    ObjList = New(NumVars);

    i = 0;

     { Loop through each tag }

    WhileLoop(i < NumVars,

       { Get each Tag's object value }

      VarObj = Scope(\Code, VarList[i]);

 

       { Check if its driver matches the one given (For each VTScada I/O tag, the SitePoint property holds this information) }

      IfThen(VarObj\SitePoint == TagObj,

        ObjList[i] = VarObj;

      );

 

       { Next Tag }

      i++

 

    )  { End of WhileLoop };

 

     { Clean up the array by getting rid of the invalid slots }

     { Move all items to the beginning of the array }

    Compress(ObjList[0], NumVars);

     { Count the number of valid items in the array }

    i = AValid(ObjList[0], NumVars);

     { Build a new array of just the right size }

    ReturnList = New(i);

     { Copy the valid items from the first array to the second }

    ArrayOp2(ReturnList[0], ObjList[0], i, 0);

 

     { Return the array }

    Return(ReturnList);

 

     { Return the array }

    Return(ObjList);

  ]

]

 

{ End of TagList }

In the preceding example, ListVars is the primary search tool.  This powerful function will search the given scope as defined by its first parameter, and can return any of names, attributes, classes, pointers to variables, number of instances found, etc. as requested. 

What is to be searched for is defined by second, third and fourth parameters to ListVars.  The second parameter is a name for which to search. Wildcards such as “*” are permitted.  The third and fourth parameters give the beginning and ending of a range of classes within which to search.  Since each type of tag is defined as a member of a distinct class, the example uses this feature to limit the search to tags of a given type (which must be computed at run time).

 

The result returned by ListVars will often include more tags or variables than you are interested in.  As is the case in this example, you will often need to filter the returned results.

Here, this is done by taking each tag returned from the ListVars function and comparing it with a given value.  In this example, the comparison is to the I/O tag’s driver, as stored in the tag’s SitePoint value. Those that match are added to an output array. 

You can filter for any possible property, or combination of properties of a tag. The list of properties of any particular tag is long and will vary according to the tag type.  In most cases, you will only be interested in the tag parameters – those values that are stored in Points.MDB.

 

The PointList subroutine provides a very similar function to the one shown in the above example.  It is a module built into the VTS layer that allows you to quickly obtain a list of the tags of a matching type or group within a module.  For example, to obtain a list of analog input tags in a module you could use the statement:

MyAlarmTags = \PointList(“AnalogInput”, “*”);

If you were interested only in the analog inputs whose names matched a certain pattern, you might use something similar to the following, collecting the analog inputs on any lift station:

MyAlarmTags = \PointList(“AnalogInput”, “LiftStation*”);