The Refresh Module

Your tag's Refresh module is called by VTScada when the tag starts and whenever any of the tag's parameters change. It is responsible for ensuring that new values are of the correct type for each parameter. Refresh must update every parameter of your tag other than the four commonly found in the ID tab.

The module will always have one parameter, "Parms", which is a pointer to an array of the tag's parameter values prior to being modified by the user. The tag's actual parameters will have already changed by the time "Refresh" is called. The "Parms" array can be used to watch for changes in the values, and take appropriate action based upon the changes

It is extremely important that the Refresh module contain a Return statement. The module will be called as a subroutine and must therefore have a return statement, even if it does not actually return any value.

 

In the case of tags that perform I/O, the Refresh module does not read from equipment, but does send an AddRead call to the driver. See Link to a Driver for more information on I/O.

In the following example, you will see instances of \ExpressionManager\SafeRefresh, which is common. This syntax is used for any parameter that can be configured using an expression, as is the case with Latitude and Longitude in a Context-derived tag where those parameters have been enabled.

The steps to add expression support for your parameters are covered in Expressions as Tag Parameters.

<
{================================ Refresh ==================================}
{ This subroutine will be called whenever the parameters for the module     }
{ are changed and allow the tag to perform any necessary actions to         }
{ undo any previous effects necessary such as changing drivers.  It is      }
{ passed an array of the previous parameter values.  The current parameter  }
{ values for the tag have already been changed by the time this is called.  }
{===========================================================================}
Refresh
(
  Parms                    { This is a pointer to an array which contains
                             the values of all of the parameters for the
                             tag prior to their change.                };
)

Refresh [
  If 1;
  [
    \ExpressionManager\SafeRefresh(&Scope(Root, "Latitude", TRUE), Parms\Latitude);
    \ExpressionManager\SafeRefresh(&Scope(Root, "Longitude", TRUE), Parms\Longitude);
    \ExpressionManager\SafeRefresh(&Scope(Root, "ConnectorColor", TRUE), Parms\ConnectorColor);

    \SetMapIcon(Root);

    Return(Invalid);
  ]
]

{ End of Refresh }
>

An example of the code used to update a tag parameter that does not have expression support follows. Here, the Analog Status tag's scan rate is being refreshed:

ScanRate = PickValid(Cast(ScanRate, 3), GetDefaultValue(&ScanRate));

A portion of the Analog Status tag's refresh module is shown here as an example. Note that the portion of a Refresh module that relates to writing data to, or reading data from a PLC is covered in the topic, Linking to a Driver.

<
{====================== AnalogStatus\Refresh ===========================}
{ This subroutine called at startup and whenever the point's parameters }
{   change                                                              }
{=======================================================================}
Refresh
(
  Parms                { Array for parameters prior to their change };
)

[
  NeedValueUpdate = FALSE;
]

Refresh [
  If 1;
  [
    ScanRate = PickValid(Cast(ScanRate, 3), GetDefaultValue(&ScanRate));

    {*****************************************************************}
    { Scaling                                                         }
    {*****************************************************************}
    UnscaledMin = PickValid(Cast(UnscaledMin, 3 { Float }), 
                            GetDefaultValue(&UnscaledMin));
    UnscaledMax = PickValid(Cast(UnscaledMax, 3 { Float }), 
                            GetDefaultValue(&UnscaledMax));
    ScaledMin   = PickValid(Cast(ScaledMin,   3 { Float }), 
                            GetDefaultValue(&ScaledMin));
    ScaledMax   = PickValid(Cast(ScaledMax,   3 { Float }), 
                            GetDefaultValue(&ScaledMax));

    IsText = UnscaledMin == UnscaledMax;

    {*****************************************************************}
    { Units                                                           }
    {*****************************************************************}
    { Provide default Units (%) for new points                        }
    Units = HookPointUnits = Cast(Units, 4 { Text });

    {*****************************************************************}
    { ManualValue                                                     }
    {*****************************************************************}
    ManualValue = Cast(ManualValue, 3 { Float });
    IfThen(ManualValue != Parm[#ManualValue] || 
           Valid(ManualValue) != Valid(Parm[#ManualValue]),
      NeedValueUpdate = TRUE;
    );
    {*****************************************************************}
    { Questionable                                                    }
    {*****************************************************************}
    Questionable = PickValid(Cast(Questionable, 0 { Boolean }),
                             GetDefaultValue(&Questionable));


    Return(0);
  ]
]
{ End of AnalogStatus\Refresh }
>

Refresh is called prior to the tag's data being written to the tag properties database and is passed an array of the previous parameter values for the tag. The current parameter values for the tag have already been changed by the time the Refresh module has been called. Refresh provides a way to reduce the memory requirements of the tag by reducing the number of active variable references and code required in the tag's main module, and thereby reduces the amount of memory required for each instance of the tag.